soapsiam
asked on
EnumPrintProcessors in Delphi
I have studied Microsoft WinDDK and found that if I want to track detail of print job from each client (win98, XP, 2000) then I have two choices to choose
1. Writing print monitor (Language or port monitor)
2. Writing print processor
However writing print monitor in Delphi is a mad process. It has difficulty in translate some header file which is easier in MS VC++. So I choose the PrintProcessor. In all approach I have to study Printer Language like PCL5, PCL5e, PCL6 etc and use information found in RAW data file to count printed page. I begin studying from PrintProcessor Installer program and some related functions. And I have problem in getting result from EnumPrintProcessors API function
in case of there are more than one processor. This is my function:
procedure TForm1.MyEnumPrintProcesso rs(AServer : string);
var pInfo : Pointer;
cbBuf, pcbNeeded, pcbReturned : Cardinal;
i : integer;
begin
cbBuf := 128;
try
GetMem(pInfo,cbBuf);
if EnumPrintProcessors(PChar( AServer),n il,1,pInfo , cbBuf,pcbNeeded,pcbReturne d) then
begin
Memo1.Lines.Add('Enumprint Processors Succeeded - buffer size needed is '+IntToStr(pcbNeeded));
Memo1.Lines.Add('Enumprint Processors Succeeded - number of PrintProcessors '+inttostr(pcbReturned));
for i := 1 to pcbReturned do
begin
Memo1.Lines.Add(' Printprocessor #'+IntToStr(i)+' named "'+string(pInfo^));
//Inc(,pcbNeeded);
end;
end
else
Memo1.Lines.Add('Failed');
finally
FreeMem(pInfo);
end;
end;
In my case pcbReturned is 2 which is the number of print processor installed. The problem is how can I get the second string from pInfo pointer.
soapsiam
1. Writing print monitor (Language or port monitor)
2. Writing print processor
However writing print monitor in Delphi is a mad process. It has difficulty in translate some header file which is easier in MS VC++. So I choose the PrintProcessor. In all approach I have to study Printer Language like PCL5, PCL5e, PCL6 etc and use information found in RAW data file to count printed page. I begin studying from PrintProcessor Installer program and some related functions. And I have problem in getting result from EnumPrintProcessors API function
in case of there are more than one processor. This is my function:
procedure TForm1.MyEnumPrintProcesso
var pInfo : Pointer;
cbBuf, pcbNeeded, pcbReturned : Cardinal;
i : integer;
begin
cbBuf := 128;
try
GetMem(pInfo,cbBuf);
if EnumPrintProcessors(PChar(
begin
Memo1.Lines.Add('Enumprint
Memo1.Lines.Add('Enumprint
for i := 1 to pcbReturned do
begin
Memo1.Lines.Add(' Printprocessor #'+IntToStr(i)+' named "'+string(pInfo^));
//Inc(,pcbNeeded);
end;
end
else
Memo1.Lines.Add('Failed');
finally
FreeMem(pInfo);
end;
end;
In my case pcbReturned is 2 which is the number of print processor installed. The problem is how can I get the second string from pInfo pointer.
soapsiam
Parametes pInfo :
Points to an ARRAY of PRINTPROCESSOR_INFO_1 structures. One structure is created for each available print processor.
string(pInfo^) - this if what you need, but the address is the address of the first element. The index starts from 0
string(pInfo[1]^) - should be the second one.
ASKER
That is not correct as in Delphi pInfo is Pointer. However in MS SDK it specifies that pInfo points to array of printprocessorinfo1. It may be point to string separated by NULL (#0).
I think I have to check this.
I think I have to check this.
ASKER
I found the solution it is:
unit Main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, WinSpool, Printers;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure MyEnumPrintProcessors(pSer ver: PChar);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function IncPtr(P:Pointer;Delta:Int eger=1):Po inter;regi ster;
asm
add eax, edx
end;
procedure TForm1.MyEnumPrintProcesso rs(pServer : PChar);
var pInfo : Pointer;
pcbNeeded, pcbReturned : Cardinal;
i : integer;
pProcessInfo : PPrintProcessorInfo1;
begin
EnumPrintProcessors(nil,ni l,1,pInfo, 0, pcbNeeded, pcbReturned);
if (GetLastError <> ERROR_INSUFFICIENT_BUFFER) then exit;
Memo1.Lines.Add('Enumprint Processors Succeeded - buffer size needed is '+IntToStr(pcbNeeded));
GetMem(pInfo, pcbNeeded);
try
if EnumPrintProcessors(nil,ni l,1,pInfo, pcbNeeded,pcbNeeded,pcbRet urned) then
begin
Memo1.Lines.Add('Enumprint Processors Succeeded - number of PrintProcessors installed is '+inttostr(pcbReturned));
for i := 0 to pcbReturned-1 do
begin
pProcessInfo := IncPtr(pInfo,i*SizeOf(TPri ntProcesso rInfo1));
Memo1.Lines.Add(' Printprocessor #'+IntToStr(i)+' named "'+string(pProcessInfo.pNa me)+'"');
end;
end
else
begin
Memo1.Lines.Add('Failed');
RaiseLastOSError;
end
finally
FreeMem(pInfo);
end;
end;
procedure TForm1.Button1Click(Sender : TObject);
begin
MyEnumPrintProcessors(nil) ;
end;
end.
unit Main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, WinSpool, Printers;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure MyEnumPrintProcessors(pSer
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function IncPtr(P:Pointer;Delta:Int
asm
add eax, edx
end;
procedure TForm1.MyEnumPrintProcesso
var pInfo : Pointer;
pcbNeeded, pcbReturned : Cardinal;
i : integer;
pProcessInfo : PPrintProcessorInfo1;
begin
EnumPrintProcessors(nil,ni
if (GetLastError <> ERROR_INSUFFICIENT_BUFFER)
Memo1.Lines.Add('Enumprint
GetMem(pInfo, pcbNeeded);
try
if EnumPrintProcessors(nil,ni
begin
Memo1.Lines.Add('Enumprint
for i := 0 to pcbReturned-1 do
begin
pProcessInfo := IncPtr(pInfo,i*SizeOf(TPri
Memo1.Lines.Add(' Printprocessor #'+IntToStr(i)+' named "'+string(pProcessInfo.pNa
end;
end
else
begin
Memo1.Lines.Add('Failed');
RaiseLastOSError;
end
finally
FreeMem(pInfo);
end;
end;
procedure TForm1.Button1Click(Sender
begin
MyEnumPrintProcessors(nil)
end;
end.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
procedure TForm1.MyEnumPrintProcesso
var
pServerName : PChar;
pInfo : array[1..255] of TPrintProcessorInfo1;
pcbNeeded, pcbReturned : Cardinal;
i : integer;
begin
try
if AServer = '' then
pServerName := nil
else
pServerName := PChar(AServer);
if EnumPrintProcessors(pServe
begin
Memo1.Lines.Add('Enumprint
Memo1.Lines.Add('Enumprint
for i := 1 to pcbReturned do
begin
Memo1.Lines.Add(' Printprocessor #'+IntToStr(i)+' named "'+string(pInfo[i].pName)+
end;
end
else
Memo1.Lines.Add('Failed');
finally
end;
end;