Solved

I need a little description about EnumJobs API..

Posted on 2002-07-13
12
317 Views
Last Modified: 2010-08-05
Hi ,

  I have only 30 points now but i will increase available points of this qestion :)

  I want to manage printing jobs(job names,page number..etc) in shared network printer so i'm try to learn EnumJobs API but i can't understand the usage of Job_Info_1 and Job_Info_2 clearly . So i need short and clear example and explanation about how can i use Job_Info_x ?

Regards..  
0
Comment
Question by:Mozzak
  • 8
  • 4
12 Comments
 

Author Comment

by:Mozzak
ID: 7151329
I had understand that Job_Info_x determines the record type which turns from EnumJobs API .  
0
 

Author Comment

by:Mozzak
ID: 7151331
I had understand that Job_Info_x determines the record type which turns from EnumJobs API .  
0
 
LVL 2

Accepted Solution

by:
mullet_attack earned 45 total points
ID: 7153729
this uses job_info_1

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, winspool,
  StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button2Click(Sender: TObject);
var
  hPrinter : THandle;
  dwNeeded, dwReturned, i : DWORD;
  pJobInfo, pJob : PJobInfo1;
  MyJobInfo : TJobInfo1;
//  pJob : pointer;//pChar;
begin
  // subsitute your printer's name for mine !
  OpenPrinter('HP LaserJet III', hPrinter, nil);

   // First you call EnumJobs() to find out how much memory you need
   if not EnumJobs( hPrinter, 0, $FFFFFFFF, 1, Nil, 0, dwNeeded, dwReturned ) then
     begin
     // It should have failed, but if it failed for any reason other
     // than "not enough memory", you should bail out
       if not GetLastError = ERROR_INSUFFICIENT_BUFFER then
         begin
           ClosePrinter( hPrinter );
           exit;
         end;
     end;
   // Allocate enough memory for the JOB_INFO_1 structures plus
   // the extra data - dwNeeded from the previous call tells you
   // the total size needed
   try
     GetMem(pJobInfo,dwNeeded );
   except
     ClosePrinter( hPrinter );
     exit;
   end;

   // Call EnumJobs() again and let it fill out our structures
   if not EnumJobs(hPrinter, 0, $FFFFFFFF, 1, pJobInfo,
                   dwNeeded, dwNeeded, dwReturned ) then
     begin
       ClosePrinter( hPrinter );
       freemem( pJobInfo );
       exit;
     end;
   // You're done with the printer handle, close it
   ClosePrinter( hPrinter );

   // dwReturned tells how many jobs there are
   // Here, you'll simply display the number of jobs found
   memo1.lines.add(format('Number of jobs %d', [dwReturned]));

   // It's easy to loop through the jobs and access each one
   pJob := pointer(pChar(pJobInfo)); //twisted pointer arithmetic
   for i := 0 to dwReturned -1 do
     begin
       memo1.lines.add('');
       memo1.lines.add(format('Job Number %d', [i]));
       pJob := pointer(pChar(pJobInfo) + (Sizeof(TJobInfo1) * i));

     // so here you could do whatever you want for each job
        memo1.lines.add('Docment Name : ' + pJob^.pDocument); // get the document name
        memo1.lines.add('User Name : ' + pJob^.pUserName); // get the document name
        memo1.lines.add('Status : ' + pJob^.pStatus); // get the document name
     end;

   // Clean up
   freemem( pJobInfo );

end;

end.
0
Ransomware-A Revenue Bonanza for Service Providers

Ransomware – malware that gets on your customers’ computers, encrypts their data, and extorts a hefty ransom for the decryption keys – is a surging new threat.  The purpose of this eBook is to educate the reader about ransomware attacks.

 

Author Comment

by:Mozzak
ID: 7154082
I had try your code but It didn't work . I don't understand why everything seems ok .
0
 

Author Comment

by:Mozzak
ID: 7154086
I had try your code but It didn't work . I don't understand why everything seems ok .
0
 
LVL 2

Expert Comment

by:mullet_attack
ID: 7154146
Hmm, works fine here...

I'm using :

D5 SP2
Win2K SP2
used both local and network printer

drop a button on the form, call it Button2
deop a memo on the form, then paste the entire code into unit1.

Should work, if not, pls specify what doesn't work exactly.
0
 

Author Comment

by:Mozzak
ID: 7154208
I was open the new project then copy-paste your code to there without make any changes . Memo1 and Button2 but when i run and click the button2 and Memo1 stay the same . There was a printing jobs in queue but there wasn't anything shown in Memo1 .  

D6 SP2
Win98
Network Printer
0
 
LVL 2

Expert Comment

by:mullet_attack
ID: 7154277
when you "openPrinter" do you get a valid hPrinter?

does GetLastError = ERROR_INSUFFICIENT_BUFFER ?

does this work ? GetMem(pJobInfo,dwNeeded );
 
does the second call to enumjobs succeed?

if so, what's the value of dwReturned ?

0
 

Author Comment

by:Mozzak
ID: 7154472
I don't know but this works ;

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Printers, WinSpool, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    Function GetCurrentPrinterHandle: THandle;
    Function SafePChar( p: PChar ): PChar;
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function TForm1.GetCurrentPrinterHandle: THandle;
Const
    Defaults: TPrinterDefaults = (
      pDatatype : nil;
      pDevMode  : nil;
      DesiredAccess : PRINTER_ACCESS_USE or PRINTER_ACCESS_ADMINISTER );
Var
    Device, Driver, Port : array[0..255] of char;
    hDeviceMode: THandle;
Begin { GetCurrentPrinterHandle }
    Printer.GetPrinter(Device, Driver, Port, hDeviceMode);
    If not OpenPrinter(@Device, Result, @Defaults) Then
      RaiseLastWin32Error;
End; { GetCurrentPrinterHandle }

function TForm1.SafePChar(p: PChar): PChar;
const error: PChar = 'Nil';
begin
  if not assigned( p ) then
    result := error
  else
    result := p;
end;

procedure TForm1.Button2Click(Sender: TObject);
type
  TJobs = Array [0..1000] of JOB_INFO_1;    // Job_Info_1 tipinden bir array
  PJobs = ^TJobs;                           // PJobs ile TJobs array i iºaret ediyor
var
  hPrinter : THandle;
  bytesNeeded, numJobs, i: Cardinal;
  pJ: PJobs;                                
begin
  hPrinter:= GetCurrentPrinterHandle;
  try
    EnumJobs( hPrinter, 0, 1000, 1, Nil, 0, bytesNeeded,
              numJobs );
    pJ := AllocMem( bytesNeeded );
    If not EnumJobs( hPrinter, 0, 1000, 1, pJ, bytesNeeded,
                     bytesNeeded, numJobs )
    Then
      RaiseLastWin32Error;
      memo1.clear;
    if numJobs = 0 Then
      memo1.lines.add('There is not any job in queue')
    else
      For i:= 0 to Pred(numJobs) Do
        memo1.lines.add( Format('Job %s, Status (%d): %s, printer (%s), machine %s, totalpages %s, printedpage %s',[SafePChar(pJ^[i].pUserName), pJ^[i].Status, SafePChar(pJ^[i].pStatus),SafePChar(pJ^[i].pPrinterName),SafePChar(pJ^[i].pMachineName),inttostr(pJ^[i].TotalPages),inttostr(pJ^[i].PagesPrinted)]));
  finally
    ClosePrinter( hPrinter );
  end;
end;

end.
0
 
LVL 2

Expert Comment

by:mullet_attack
ID: 7154617
same thing, the only difference is you do this :

TJobs = Array [0..1000] of JOB_INFO_1;
PJobs = ^TJobs;              
var
 pJ: PJobs;                                

which makes it easier and neater to go thru the returned results. D6 probably doesn't like the PCHAR arithmetic that I did (I was in a hurry to write example).

anyway, it looks like you got what you wanted, an example of how to use jobinfo1, and you now have working code which is the desired result....

just a thought, when you cut-and-paste my code, did you re-attach the button's onclick event?
0
 

Author Comment

by:Mozzak
ID: 7154631
Yes , i have attached all the code . But i needed explanation of the enumjob code and you gave it to me . Thanks..
0
 

Author Comment

by:Mozzak
ID: 7155478
When the job start to printing , i can't take any information from the printer . I don't know why . Can you try this code for me ? What's wrong with this code ?

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Printers, WinSpool, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    Function GetCurrentPrinterHandle: THandle;
    Function SafePChar( p: PChar ): PChar;
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function TForm1.GetCurrentPrinterHandle: THandle;
Const
    Defaults: TPrinterDefaults = (
      pDatatype : nil;
      pDevMode  : nil;
      DesiredAccess : PRINTER_ACCESS_USE or PRINTER_ACCESS_ADMINISTER );
Var
    Device, Driver, Port : array[0..255] of char;
    hDeviceMode: THandle;
Begin { GetCurrentPrinterHandle }
    Printer.GetPrinter(Device, Driver, Port, hDeviceMode);
    If not OpenPrinter(@Device, Result, @Defaults) Then
      RaiseLastWin32Error;
End; { GetCurrentPrinterHandle }

function TForm1.SafePChar(p: PChar): PChar;
const error: PChar = 'Nil';
begin
  if not assigned( p ) then
    result := error
  else
    result := p;
end;

procedure TForm1.Button2Click(Sender: TObject);
type
  TJobs = Array [0..1000] of JOB_INFO_1;    // Job_Info_1 tipinden bir array
  PJobs = ^TJobs;                           // PJobs ile TJobs array i iºaret ediyor
var
  hPrinter : THandle;
  bytesNeeded, numJobs, i: Cardinal;
  pJ: PJobs;                                
begin
  hPrinter:= GetCurrentPrinterHandle;
  try
    EnumJobs( hPrinter, 0, 1000, 1, Nil, 0, bytesNeeded,
              numJobs );
    pJ := AllocMem( bytesNeeded );
    If not EnumJobs( hPrinter, 0, 1000, 1, pJ, bytesNeeded,
                     bytesNeeded, numJobs )
    Then
      RaiseLastWin32Error;
      memo1.clear;
    if numJobs = 0 Then
      memo1.lines.add('There is not any job in queue')
    else
      For i:= 0 to Pred(numJobs) Do
        memo1.lines.add( Format('Job %s, Status (%d): %s, printer (%s), machine %s, totalpages %s, printedpage %s',[SafePChar(pJ^[i].pUserName), pJ^[i].Status, SafePChar(pJ^[i].pStatus),SafePChar(pJ^[i].pPrinterName),SafePChar(pJ^[i].pMachineName),inttostr(pJ^[i].TotalPages),inttostr(pJ^[i].PagesPrinted)]));
  finally
    ClosePrinter( hPrinter );
  end;
end;

end.
0

Featured Post

ScreenConnect 6.0 Free Trial

Want empowering updates? You're in the right place! Discover new features in ScreenConnect 6.0, based on partner feedback, to keep you business operating smoothly and optimally (the way it should be). Explore all of the extras and enhancements for yourself!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.

773 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question