Solved

I need a little description about EnumJobs API..

Posted on 2002-07-13
12
313 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
Comment Utility
I had understand that Job_Info_x determines the record type which turns from EnumJobs API .  
0
 

Author Comment

by:Mozzak
Comment Utility
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
Comment Utility
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
 

Author Comment

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

Author Comment

by:Mozzak
Comment Utility
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
Comment Utility
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
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 

Author Comment

by:Mozzak
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

744 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now