in reply to Re: Win32::OLE and timeout
in thread Win32::OLE and timeout

I had a lot of weird ideas about this code like using fork, but after looking at it for a while I settled on simply changing the following:

... my $IE; my $IETimeout = 60; my $timeAtStart; #new global var ... sub IENavigate( $ ) { my $url = shift; my $seconds = 0; $timeAtStart = time unless ($timeAtStart); print "IENavigate $url\n"; alarm $IETimeout; $IE->navigate($url); Win32::OLE->MessageLoop(); print "Finished Blocking\n"; return; } sub IEEvent(){ my ($Obj,$Event,@Args) = @_; if (($IETimeout) && ($timeAtStart) && (time > ($timeAtStart + $IET +imeout) )) {&IEAlarm(17)}; print "IEEvent '$Event' @ " . time . qq|\n|; }

Which produces, not surprisingly...

IEEvent 'StatusTextChange' @ 1131174480 IEEvent 'CommandStateChange' @ 1131174480 IEEvent 'StatusTextChange' @ 1131174480 IEEvent 'StatusTextChange' @ 1131174480 IEEvent 'CommandStateChange' @ 1131174480 IEEvent 'StatusTextChange' @ 1131174480 ... IEEvent 'CommandStateChange' @ 1131174520 IEEvent 'CommandStateChange' @ 1131174520 IEAlarm 17 IEEvent 'CommandStateChange' @ 1131174521 Finished Blocking
There are some strange things in this code like:
Use of uninitialized value in concatenation (.) or string at foo.pl li +ne 37. ... #which is ==36== my $seconds = IENavigate( $_ ); ==37== print "took $seconds\n";
when IENavigate doesn't return anything...? At any rate, if you are looking to see how long it takes to load pages, etc. wouldn't you be better served with LWP::Simple and Benchmark or something?

Celebrate Intellectual Diversity

Replies are listed 'Best First'.
Re^3: Win32::OLE and timeout
by puff (Beadle) on Nov 12, 2005 at 21:47 UTC
    I’ve been tied up for a bit and did not see this reply until today.

    The approach is interesting (hadn’t thought of this attack) but unfortunately I do not think that it will work reliably. The problem is that it assumes that events will continue to occur during the interval. While they frequently do, they do NOT ALWAYS DO so. The consequence is that you can not rely on the event routine being executed. The only thing I can find after looking at the Win32::OLE code that is guaranteed to be true is that you are in a classic and very tight Com message dispatch loop.

    Does anyone know how to start a conversation with the Win32::OLE folks? I’ve tried cpan and doing a bug report. Also sent an email to the listed author address.
Re^3: Win32::OLE and timeout
by puff (Beadle) on Nov 12, 2005 at 23:37 UTC
    BTW, I tested the proposed code and it does NOT work unless the underlying page takes more than Timeout to load and still generates events. If you test it you MUST NOT move the mouse about the IE window as that generates events that would not otherwise occur and can thus distort the results.
    #!/usr/bin/perl -w use 5.006; use strict; use warnings; use Win32::OLE qw(EVENTS); use Time::HiRes qw(gettimeofday); Win32::OLE->Option(_Unique => 1); sub IENavigate( $ ); $| = 1; # do not buffer output my $IE; my $IETimeout = 60; my $timeAtStart; #new global var my @urls = qw( http://www.google.com http://www.cnn.com/ ); # start ie, connect to events, make IE visible, connect alarm handler $IE = Win32::OLE->new("InternetExplorer.Application") || die "Could not start Internet Explorer.Application\n"; Win32::OLE->WithEvents($IE,\&IEEvent,"DWebBrowserEvents2"); $IE->{visible} = 1; $SIG{ALRM} = \&IEAlarm; # visit some URLs foreach (@urls){ print "Navigate to $_\n"; my $seconds = IENavigate( $_ ); print "took $seconds\n"; } # we're done print "Done\n"; # kill this IE $IE->Quit(); exit; # ################################################################### # sub IENavigate( $ ) { my $url = shift; my $seconds = 0; print "IENavigate $url\n"; $timeAtStart = time unless ($timeAtStart); alarm $IETimeout; $IE->navigate($url); Win32::OLE->MessageLoop(); print "Finished Blocking\n"; return; } sub IEEvent(){ my ($Obj,$Event,@Args) = @_; if (($IETimeout) && ($timeAtStart) && (time > ($timeAtStart + $IET +imeout) )) {&IEAlarm(17)}; print "IEEvent '$Event'\n"; } sub IEAlarm(){ my $sig = shift; print "IEAlarm $sig\n"; Win32::OLE->QuitMessageLoop(); }