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();
Comments:
- The $do_not_prompt option was included to allow for better exploration of the timing issues.
- 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.
- 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.
- 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.
- 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.