0

我正在尝试列出打印机上的作业。我尝试第一次调用 enumjobs 以获取我需要在第二次调用中作为参数传递的缓冲区的大小(正如 microsoft 文档中所建议的那样)但是,在调用 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;
4

2 回答 2

2

他妈的……我做错了吗?!

基本上,您从 Spooler 子系统获得了错误的句柄,因此出现了ERROR_INVALID_HANDLE错误。OpenPrinter势必会为 Spooler subsys 对象打开各种句柄。特别是,您的声明:

if not OpenPrinter(nil,handlePrinter,nil) then

打开本地打印服务器的句柄,它既不支持作业队列枚举也不支持详细的打印机(2级)信息,但显然支持安全(3级)信息。必须指定确切的打印机名称才能获得有效的打印机句柄,例如:

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

另外,请注意Sertac Akyuz 的评论。还有另一个,检查Win32CheckSysErrorMessage实用功能,它们在处理 WinAPI 时非常方便。

于 2014-09-17T00:28:38.980 回答
1

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

使用这样的代码进行测试(使用Rodrigo Ruz的“WMI Delphi 代码创建器”创建)

//-----------------------------------------------------------------------------------------------------
//     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 编译的),您可以获得如下结果:

在此处输入图像描述

问候。

于 2014-09-16T10:53:51.230 回答