在delphi中打印后台处理程序api

时间:2014-09-16 10:17:06

标签: delphi print-spooler-api

我正在尝试在打印机上列出作业。 我尝试第一次调用enumjobs来获取缓冲区的大小,我需要在第二次调用中作为参数传递(在microsoft文档中建议) 但是,在调用enumjobs时,我一直在使用enumjobs api获取描述符无效错误。

我做错了什么? !

procedure showLastError();
var
pErrorText:pchar;
lastError:integer;
begin
   lastError := GetLastError();
   pErrorText := nil;

   if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ALLOCATE_BUFFER
                 ,nil,lastError,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),@pErrorText,0,nil)<> 0) then
   begin
    showmessage(pErrorText);
   end;
end;

procedure TForm3.Button1Click(Sender: TObject);
var
handlePrinter:NativeUInt;
pJob:pointer;
sizePJob:integer;
pcbNeeded:cardinal;
pcReturned:cardinal;
cByteNeeded,cByteUsed:cardinal;

i:integer;
pJobInfo: PJobInfo1;
temp:integer;
ret:boolean;
pPrinterInfo:PPrinterInfo2W;
PPRINTER_INFO_1 : PRINTER_INFO_1;

begin
 handlePrinter := 0;
 if not OpenPrinter(nil,handlePrinter,nil) then
 begin
  showLastError();
  exit;
 end;
 if not GetPrinter(handlePrinter,3,nil,0,@cByteNeeded)then
 begin
  if (GetLastError() <> ERROR_INSUFFICIENT_BUFFER) then
  begin
   showLastError();
   exit;
  end;
 end;
 pPrinterInfo := allocMem(  cByteNeeded);
 if not GetPrinter(handlePrinter,3,pPrinterInfo,cByteNeeded,@cByteUsed)then
 begin
  if (GetLastError() <> ERROR_INSUFFICIENT_BUFFER) then
  begin
   showLastError();
   FreeMem(pPrinterInfo);
   exit;
  end;
 end;

 ret := EnumJobs(handlePrinter,0,pPrinterInfo.cJobs,2,nil,0,&pcbNeeded,&pcReturned);
 if (not ret)then
 begin
  if (GetLastError() <> ERROR_INSUFFICIENT_BUFFER) then
  begin
   showLastError();
   FreeMem(pPrinterInfo);
   exit;
  end;
 end;
 FreeMem(pPrinterInfo);
end;

2 个答案:

答案 0 :(得分:2)

  

我做错了什么? !

基本上,您从后台处理程序子系统获取了错误的句柄,因此出现ERROR_INVALID_HANDLE错误。 OpenPrinter必须为Spooler子对象打开各种句柄。特别是你的陈述:

if not OpenPrinter(nil,handlePrinter,nil) then

打开本地打印服务器的句柄,它既不支持job queue enumeration也不支持detailed printer (level 2) information,但显然支持security (level 3) information。您 指定确切的打印机名称以获取打印机的有效句柄,例如:

if not OpenPrinter('Xerox ColorQube 9301 PS', handlePrinter, nil) then

另外,请注意Sertac Akyuz's comments。另外,检查Win32CheckSysErrorMessage实用程序函数,它们在处理WinAPI时非常方便。

答案 1 :(得分:1)

另一种选择是使用WMI。 您可以尝试使用 Win32_PrintJob 类(从Win32_PrintJob中选择*)。

使用这样的代码进行测试(使用&#34; WMI Delphi代码创建者&#34;来自Rodrigo Ruz创建)

//-----------------------------------------------------------------------------------------------------
//     This code was generated by the Wmi Delphi Code Creator (WDCC) Version 1.8.5.0
//     http://code.google.com/p/wmi-delphi-code-creator/
//     Blog http://theroadtodelphi.wordpress.com/wmi-delphi-code-creator/
//     Author Rodrigo Ruz V. (RRUZ) Copyright (C) 2011-2014 
//----------------------------------------------------------------------------------------------------- 
//
//     LIABILITY DISCLAIMER
//     THIS GENERATED CODE IS DISTRIBUTED "AS IS". NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED.
//     YOU USE IT AT YOUR OWN RISK. THE AUTHOR NOT WILL BE LIABLE FOR DATA LOSS,
//     DAMAGES AND LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING OR MISUSING THIS CODE.
//
//----------------------------------------------------------------------------------------------------
program GetWMI_Info;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  ActiveX,
  ComObj,
  Variants,
  Dialogs;



// La clase Win32_PrintJob representa un trabajo de impresión generado por una aplicación Win32. Las unidades de trabajo generadas por el comando Imprimir de una aplicación que se ejecuta en un sistema Win32 son descendientes (o miembros) de esta clase.
// Ejemplo: un documento de impresora creado por una aplicación de Office 97

procedure  GetWin32_PrintJobInfo;
const
  WbemUser            ='';
  WbemPassword        ='';
  WbemComputer        ='localhost';
  wbemFlagForwardOnly = $00000020;
var
  FSWbemLocator : OLEVariant;
  FWMIService   : OLEVariant;
  FWbemObjectSet: OLEVariant;
  FWbemObject   : OLEVariant;
  oEnum         : IEnumvariant;
  iValue        : LongWord;
  str:String;
begin;
  FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  FWMIService   := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
  FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_PrintJob','WQL',wbemFlagForwardOnly);
  oEnum         := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
  Str := '';
  while oEnum.Next(1, FWbemObject, iValue) = 0 do
  begin
    Str := Str + sLineBreak + Format('Caption           %s',[String(FWbemObject.Caption)]);// String
    Str := Str + sLineBreak + Format('DataType          %s',[String(FWbemObject.DataType)]);// String
    Str := Str + sLineBreak + Format('Description       %s',[String(FWbemObject.Description)]);// String
    Str := Str + sLineBreak + Format('Document          %s',[String(FWbemObject.Document)]);// String
    Str := Str + sLineBreak + Format('DriverName        %s',[String(FWbemObject.DriverName)]);// String
    Str := Str + sLineBreak + Format('ElapsedTime       %s',[String(FWbemObject.ElapsedTime)]);// Datetime
    Str := Str + sLineBreak + Format('HostPrintQueue    %s',[String(FWbemObject.HostPrintQueue)]);// String
    Str := Str + sLineBreak + Format('JobId             %d',[Integer(FWbemObject.JobId)]);// Uint32
    Str := Str + sLineBreak + Format('JobStatus         %s',[String(FWbemObject.JobStatus)]);// String
    Str := Str + sLineBreak + Format('Name              %s',[String(FWbemObject.Name)]);// String
    Str := Str + sLineBreak + Format('Notify            %s',[String(FWbemObject.Notify)]);// String
    Str := Str + sLineBreak + Format('Owner             %s',[String(FWbemObject.Owner)]);// String
    Str := Str + sLineBreak + Format('PagesPrinted      %d',[Integer(FWbemObject.PagesPrinted)]);// Uint32
    Str := Str + sLineBreak + Format('PrintProcessor    %s',[String(FWbemObject.PrintProcessor)]);// String
    Str := Str + sLineBreak + Format('Priority          %d',[Integer(FWbemObject.Priority)]);// Uint32
    Str := Str + sLineBreak + Format('Size              %d',[Integer(FWbemObject.Size)]);// Uint32
    Str := Str + sLineBreak + Format('Status            %s',[String(FWbemObject.Status)]);// String
    Str := Str + sLineBreak + Format('StatusMask        %d',[Integer(FWbemObject.StatusMask)]);// Uint32
    Str := Str + sLineBreak + Format('TimeSubmitted     %s',[String(FWbemObject.TimeSubmitted)]);// Datetime
    Str := Str + sLineBreak + Format('TotalPages        %d',[Integer(FWbemObject.TotalPages)]);// Uint32
    Str := Str + sLineBreak + '--------------------------------------------------------';

    MessageDlg(Str, mtInformation, [mbOK], 0);

    FWbemObject:=Unassigned;
  end;
end;


begin
 try
    CoInitialize(nil);
    try
      GetWin32_PrintJobInfo;
    finally
      CoUninitialize;
    end;
 except
    on E:EOleException do
        Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode])); 
    on E:Exception do
        Writeln(E.Classname, ':', E.Message);
 end;
 Writeln('Press Enter to exit');
 Readln;      
end.

如果您将文件发送到打印机并执行项目(这是使用Delphi 6编译的),您可以获得如下结果:

enter image description here

问候。