[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 961
  • Last Modified:

function to resume all paused print jobs + delphi

hi there!!!!!

i need a function in delphi that will resume all paused print jobs that are currently in the print job queue of the printer.

i have some code that resumes the printer but not the jobs. hope it helps. i need some urgent help.


***************************
procedure ResumePrinter;
var
  hPrinter : THandle;
  PrinterName : PChar;
  PrinterDefaults : TPrinterDefaultsA;
  DevMode : PDeviceModeA;
  Needed : integer;
  handle:thandle;
  begin
  try
    PrinterName := PChar(Printer.Printers[Printer.PrinterIndex]);
    WinSpool.OpenPrinter(PrinterName,hPrinter,nil);
    Needed := WinSpool.DocumentProperties(Handle,hPrinter,PrinterName,DevMode^,DevMode^,0);
      if Needed < 0 then
        begin
          exit;
        end;
  GetMem(DevMode,Needed);
  WinSpool.DocumentProperties(Handle,hPrinter,PrinterName,DevMode^,DevMode^,DM_COPY);
  PrinterDefaults.pDatatype := nil;
  PrinterDefaults.pDevMode := @DevMode^;
  PrinterDefaults.DesiredAccess := PRINTER_ALL_ACCESS;
  ClosePrinter(hPrinter);
  if OpenPrinter(PrinterName,hPrinter,@PrinterDefaults) then
    begin
      if WinSpool.SetPrinter(hPrinter,0,nil,PRINTER_CONTROL_RESUME) then
        begin
          ClosePrinter(hPrinter);
        end
    end;
  ClosePrinter(hPrinter);
  FreeMem(DevMode);
  except
  on e: exception do HandleException(e, 'ResumePrinter2000');
  end;
  end;
******************************



thanks a lot

0
nikolaosk
Asked:
nikolaosk
  • 2
  • 2
  • 2
2 Solutions
 
Russell LibbySoftware Engineer, Advisory Commented:

Below is an example of what you asking for. Please be aware though, that to be able to successfully call SetPrinter with a pause/resume command requires admin privs for the printer. Let me know if there are questions or problems.

Regards,
Russell



type
  PJob1Array        =  ^TJob1Array;
  TJob1Array        =  Array [0..1023] of TJobInfo1;

procedure ResumePrinterJobs;
var  lpJobs:        PJob1Array;
     lpDefaults:    TPrinterDefaults;
     hPrinter:      THandle;
     dwAlloced:     DWORD;
     dwNeeded:      DWORD;
     dwCount:       DWORD;
     dwIndex:       DWORD;
begin

  // Clear printer defaults
  FillChar(lpDefaults, SizeOf(TPrinterDefaults), 0);

  // This access is REQUIRED in order to pause / resume the printer itself
  lpDefaults.DesiredAccess:=PRINTER_ACCESS_ADMINISTER;

  // Open the default printer
  if OpenPrinter(PChar(Printer.Printers[Printer.PrinterIndex]), hPrinter, @lpDefaults) then
  begin
     // Resource protection
     try
        // Resume the printer
        if SetPrinter(hPrinter, 0, nil, PRINTER_CONTROL_RESUME) then
        begin
           // Enum the printer jobs
           if not(EnumJobs(hPrinter, 0, High(TJob1Array), 1, lpJobs, 0, dwNeeded, dwCount)) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
           begin
              // Set alloc size
              dwAlloced:=dwNeeded;
              // Allocate memory to get jobs
              lpJobs:=AllocMem(dwAlloced);
              // Resource protection
              try
                 // Enum the printer jobs
                 if EnumJobs(hPrinter, 0, High(TJob1Array), 1, lpJobs, dwAlloced, dwNeeded, dwCount) then
                 begin
                    // Iterate the job array
                    for dwIndex:=0 to Pred(dwCount) do
                    begin
                       // Check the job status
                       if ((lpJobs^[dwIndex].Status and JOB_STATUS_PAUSED) = JOB_STATUS_PAUSED) then
                       begin
                          // Resume the job
                          Win32Check(SetJob(hPrinter, lpJobs^[dwIndex].JobId, 0, nil, JOB_CONTROL_RESUME));
                       end;
                    end;
                 end
                 else
                    // Raise last win32 error
                    RaiseLastWin32Error;
              finally
                 // Free memory
                 FreeMem(lpJobs);
              end;
           end;
        end
        else
           // Raise last win32 error
           RaiseLastWin32Error;
     finally
        // Close the printer handle
        ClosePrinter(hPrinter);
     end;
  end
  else
     // Raise last win32 error
     RaiseLastWin32Error;

end;

 
0
 
atul_parmarCommented:
Hi, the following will resume all the paused jobs for default printer. To resume for other printer, set PrinterName to the the printer for which you want to resume all the paused jobs.

proceure ResumeAllJobs;
var
  PrinterName : string;
  hPrinter : THandle;
  NumJobs : cardinal;
  pcbNeed,pcReturned:DWord;
  i : integer;
  Buffer: Pointer;
begin
  PrinterName := Printer.Printers[Printer.PrinterIndex];
  OpenPrinter(PAnsiChar(Printername), hPrinter, nil);
  NumJobs := 10;
  EnumJobs(hPrinter, 0, NumJobs, 2, nil, 0, pcbNeed, pcReturned);
  GetMem(Buffer, pcbNeed);
  if EnumJobs(hPrinter, 0, NumJobs, 2, Buffer, pcbNeed, pcbNeed, pcReturned) then
  begin
    for i := 1 to pcReturned do
    begin
      if TArrayofJobs(buffer^)[i].Status = JOB_STATUS_PAUSED then
        SetJob(hPrinter, TArrayofJobs(buffer^)[i].JobId, 0, nil, JOB_CONTROL_RESUME);
    end;
  end;
end;
0
 
nikolaoskAuthor Commented:
atul,

hi again

i get an error code

undeclared identifier:TArrayofJobs

please advise.
thanks
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Russell LibbySoftware Engineer, Advisory Commented:

If your going to use atul's code, then you will also need to add in a call to FreeMem to avoid the memory leak.

Russell
0
 
atul_parmarCommented:
Hi, just copy and paste the following function.

type
  TArrayofJobs = array[1..1024] of JOB_INFO_2;

procedure ResumeAllJobs;
var
  PrinterName : string;
  hPrinter : THandle;
  NumJobs : cardinal;
  pcbNeed,pcReturned:DWord;
  i : integer;
  Buffer: Pointer;
  d : PRINTER_DEFAULTS;
begin
  PrinterName := Printer.Printers[Printer.PrinterIndex];
  FillChar(d, SizeOf(PRINTER_DEFAULTS), #0);
  d.DesiredAccess := PRINTER_ALL_ACCESS;
  OpenPrinter(PAnsiChar(Printername), hPrinter, @d);
  NumJobs := 10;
  EnumJobs(hPrinter, 0, NumJobs, 2, nil, 0, pcbNeed, pcReturned);
  GetMem(Buffer, pcbNeed);
  try
    if EnumJobs(hPrinter, 0, NumJobs, 2, Buffer, pcbNeed, pcbNeed, pcReturned) then
    begin
      for i := 1 to pcReturned do
      begin
        if TArrayofJobs(buffer^)[i].Status = JOB_STATUS_PAUSED then
          SetJob(hPrinter, TArrayofJobs(buffer^)[i].JobId, 0, nil, JOB_CONTROL_RESUME);
      end;
    end;
  finally
    FreeMem(Buffer, pcbNeed);
  end;
end;
0
 
nikolaoskAuthor Commented:
hi there!!!

both solutions worked.

but i did use rllibby's first.
thanks
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 2
  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now