Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

Win32::OLE printing

by ixo111 (Acolyte)
on Mar 21, 2004 at 19:31 UTC ( [id://338506]=perlquestion: print w/replies, xml ) Need Help??

ixo111 has asked for the wisdom of the Perl Monks concerning the following question:

venerable monk-folk,

i'm trying to fast-track an application that will require printing of forms. i'm pretty new to Win32 development ( native *nix by preference ) and am not sure where to go to find good info on OLE automation.

What i'm trying to do is open up an instance of InternetExplorer.Application, then use the Navigate method to a pre-defined location ( the location of the generated document to be printed ) and then open up the Print dialog. This would be more easily done using microsoft word, probably, but it is more likely to find IE on any given machine than Word and i'd like to stick to the lowest common denominator as much as possible.

Having created a new instance of InternetExplorer.Application, I browse through the tree of constants and find OLECMDID_PRINT == 6 .. i note that there is an ExecWB method that seems to be being used in other languages to do this very thing.

my question is, how do i properly invoke the command? .. my ( not working ) code so far :

use warnings; use strict; use Win32::OLE; use Win32::OLE::Const; { my $IE = Win32::OLE->new( 'InternetExplorer.Application' ); my $ie_const = Win32::OLE::Const->Load( $IE ); $IE->Navigate( "C:\\tmp\\somefile.html" ); # at this point IE opens up and properly displays the page, but he +re is where i get lost .. my best guess is - $IE->ExecWB( ${ $ie_const }{ 'OLECMDID_PRINT'} } ); }

( very ) obviously i'm missing somthing, particularly with regards to ExecWB. I also tried to follow a direct ( supposedly working ) example of python using the same commands via :

$IE->ExecWB( ${ $ie_const }{ 'OLECMDID_PRINT' }, ${ $ie_const }{ 'O +LECMDID_PROMPTUSER' } );

which results in an error of : "Trying to revoke a drop target that has not been registered". Looking in to this error shows that its possible that the browser may not be ready. The suggested method was to use the QueryStatusWB method until it returned OLECMDF_SUPPORTED + OLECMDF_ENABLED ( which should be a total of 3 ) .. putting this code in to a loop which queries the status continues to return 0 well after the page has loaded.

I've read through the Activestate documentation on OLE and their examples are pretty good so long as you have the Office suite installed ;) .. what i'm really after is how to execute arbitrary commands available via the constants defined by a given instance of an OLE object. My suspicion ( loosely founded ) is that $IE in the above case is not the object i need to be dealing with - possibly i need to create another object derived from $IE, such as :

my $automater = $IE->Automation()

or something along those lines?

any help / pointers Greatly appreciated!

Replies are listed 'Best First'.
Re: Win32::OLE printing
by maa (Pilgrim) on Mar 21, 2004 at 19:43 UTC

    I've never needed to use this but MSDN has a couple of articles about it here and here.

    This node suggests $ie->ExecWB(6,2);

Re: Win32::OLE printing
by tachyon (Chancellor) on Mar 21, 2004 at 20:41 UTC

    Here is how to print out of Word. Re: Changing the STDOUT Font for word, which while it is not exactly what you want probably indicates how you approach it in general using Win32::OLE



      jah :) .. Word has a direct PrintOut method - IE doesn't allow for such directly ( or so says MSDN ) so you have to use the ExecWB function ..

      after tinkering around a bit i was able to Almost get it to work using the following code :

      $IE->ExecWB( 23, 1 ); sleep ( 1 ); $IE->ExecWB( 6, 1, 1 );

      thanks to you both for your replies! .. i'll try the ( 6, 2 ) and see if that bears any fruit :)
Re: Win32::OLE printing
by CountZero (Bishop) on Mar 21, 2004 at 23:16 UTC
    My naive suggestion would be to send a "Ctrl+P" followed by "CR" (or whatever code is issued by pressing the "Enter"-key) to IE and see if it starts printing.

    Warning: Untried suggestion, use at your own risk, YMMV.


    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Win32::OLE printing
by Util (Priest) on Mar 22, 2004 at 21:42 UTC
    Working, tested code:
    #!/usr/bin/perl use strict; use warnings 'all'; use Win32::OLE; use Win32::OLE::Const 'Microsoft Internet Controls'; use Win32::OLE::Variant; # From Vc7/PlatformSDK/Include/MsHtmHst.h : use constant PRINT_DONTBOTHERUSER => 0x01; use constant PRINT_WAITFORCOMPLETION => 0x02; my $file = "C:\\test.html"; my $do_not_prompt = 0; my $nCmdID = OLECMDID_PRINT; my $nCmdExecOpt = OLECMDEXECOPT_PROMPTUSER; my $pvaIn = PRINT_WAITFORCOMPLETION; my $pvaOut = 0; if ($do_not_prompt) { $nCmdExecOpt = OLECMDEXECOPT_DONTPROMPTUSER; $pvaIn |= PRINT_DONTBOTHERUSER; } my $IE = Win32::OLE->new('InternetExplorer.Application') or die; #$IE->{'Visible'} = 1; $IE->Navigate( $file ); sleep 1 while $IE->{Busy}; $IE->ExecWB($nCmdID, $nCmdExecOpt, Variant(VT_I2,$pvaIn), $pvaOut); $IE->Quit();
    1. The $do_not_prompt option was included to allow for better exploration of the timing issues.
    2. The error  "Trying to revoke a drop target that has not been registered" is indeed caused by MSIE not being ready. The QueryStatusWB method that you mentioned might work fine. I originally used sleep 1 while $IE->{ReadyState} != READYSTATE_COMPLETE, but found that the $IE->{Busy} method also worked, and was more concise.
    3. None of those methods work to delay the end of the ExecWB call, because the printing happens in the background. If we don't PRINT_WAITFORCOMPLETION, (or sleep($hope_it_never_takes_longer_than_this)), then MSIE will often exit before the printing begins.
    4. When ExecWB is called with OLECMDID_PRINT, the third parameter is overloaded by Variant type (VT_BSTR, VT_I2, or VT_ARRAY). If I just passed $pvaIn directly, then it would have been converted to the default numeric Variant type (VT_I4), which would then be disregarded! I had to build the specific Variant that OLECMDID_PRINT wants, to make it work. See the MSDN page for details.
    5. In your second section of code, ${ $ie_const }{ 'OLECMDID_PROMPTUSER' } will not be defined.
      The constant you wanted was OLECMDEXECOPT_PROMPTUSER. If you import the constants, as I have done in my code, then this kind of error will be caught at compile time. As a guideline, I import when using constants as individual values, and only use the Win32::OLE::Const->Load() form when iterating through sets of constants.

      I think ExecWB has been altered to make printing from it impossible.

      "you can no longer use ExecWB to print Hypertext Markup Language (HTML) documents with print templates in Visual Basic or Visual C++. In addition, this problem occurs with Internet Explorer 5.5 SP1 after you install the security update that is available in the following Microsoft Knowledge Base article:"

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://338506]
Approved by ybiC
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (4)
As of 2024-06-23 07:59 GMT
Find Nodes?
    Voting Booth?

    No recent polls found

    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.