Programmatically Printing in Adobe Reader 9 using .NET Interop

15,165

Solution 1

Using this method to print multiple documents is not going to work good as you found.

Having it work is quite tricky but here is a general description of the solution.

I use System.Diagnostics.Process to print using myProcess.StartInfo.Verb = "Print" Then I check the Status and State of printer queue in two steps to make sure that the printing is ready enough to be able to print the next document. Use WMI and ManagementObjectSearcher to enumerate the printer info using "SELECT * FROM Win32_Printer". The logic is that I try to see if the spooling is started before continuing to print the next one.

See http://msdn.microsoft.com/en-us/library/aa394363.aspx for the Win32_Printer WMI class.

Solution 2

I had the same problem using AcroPDF in Delphi.. then I figured out that when I "stop" the processo using a message, AcroPDF starts to print.

So I just create a modal TForm that closes itself after some seconds.

var
  formModal : TFormModal;
begin
  formModal := TFormModal.Create(self);
  //PrintMethodHere  
  frmPecas.CarregarDocumentoParaImpressao();
  formModal.ShowModal;
end;

The TFormModal is this and I just insert a loading icon on the form to represents something like "printing".

unit FModal;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, Animate, GIFCtrl;

type
  TFormModal = class(TForm)
    Timer: TTimer;
    imgGif: TRxGIFAnimator;
    procedure TimerTimer(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  FormModal: TFormModal;

implementation

{$R *.dfm}
//    Author: Anderson Mello  Date: 09-fev-2012
//  DEscription: Using TTimer after 5 seconds I close this form
procedure TFormModal.TimerTimer(Sender: TObject);
begin
 close;
end;

//    Author: Anderson Mello  Date: 09-fev-2012
//  Description: Enable the timer only when the form is shown
procedure TFormModal.FormShow(Sender: TObject);
begin
 Timer.Enabled := true;
end;

//  Description: disable when close
procedure TFormModal.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 Timer.Enabled := false;
end;

//    Author: Anderson Mello  Date: 09-fev-2012
//  Description: disable close button "X", so the user can't close 
procedure TFormModal.FormCreate(Sender: TObject);
var
  hSysMenu:HMENU;
begin
  hSysMenu:=GetSystemMenu(Self.Handle,False);
  if hSysMenu <> 0 then begin
    EnableMenuItem(hSysMenu,SC_CLOSE,MF_BYCOMMAND or MF_GRAYED);
    DrawMenuBar(Self.Handle);
  end;
  KeyPreview:=True;
end;

//    Author: Anderson Mello  Date: 09-fev-2012
//  Description: disable shortcuts to close
procedure TFormModal.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if (Key = VK_F4) and (ssAlt in Shift) then
    Key:=0;
end;
Share:
15,165
Christopher Edwards
Author by

Christopher Edwards

Updated on June 04, 2022

Comments

  • Christopher Edwards
    Christopher Edwards almost 2 years

    I am using VB.Net WinForms. I would like to call the Adobe Reader 9 ActiveX control to print some PDFs. I have added the ActiveX control to the VS toolbox (the dll is AcroPDF.dll, the COM name "Adobe PDF Reader". After some experiment the following code works.

    Dim files As String() = Directory.GetFiles(TextBoxPath.Text, "*.pdf", SearchOption.TopDirectoryOnly)
    
    Using ActiveXPDF As New AxAcroPDFLib.AxAcroPDF
    
        Me.Controls.Add(ActiveXPDF)
        ActiveXPDF.Hide()
    
        For Each filename As String In files
    
            ActiveXPDF.LoadFile(filename)
            ActiveXPDF.printAll()
    
            'Begin Yukky Hack    '
    
    
            Dim endTime As Date = DateAdd(DateInterval.Second, 20, Now)
            Do While Now < endTime
                My.Application.DoEvents()
            Loop
    
            'End Yuk   '
    
        Next
    
    End Using
    

    Without the Yuk bit this will only print some of the PDFs, it seems that the End Using statement is calling dispose on the control before it has finished printing.

    Therefore it seems the call to printAll is non-blocking but I can't find a callback or status property I can query to see if the print spooling has been completed. I am missing a property/method or is there a more elegant (and more responsive) work around?

  • Christopher Edwards
    Christopher Edwards about 15 years
    +1 But that's almost as horrible hack as my 'just wait for a bit' hack! I wonder why it's such a pita. I have decided just not call call Dispose, which I suppose is even worse...
  • statenjason
    statenjason over 14 years
    The question is about how to print PDFs, not open them. I understand they could click "print" within the new Adobe Reader instance, but that's a usability nightmare. Also, swallowing exceptions is bad practice.