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

Hi monks,

I wrote a snippet in perl for Web automation:

use warnings; use strict; use Win32::IEAutomation; use Win32::IEAutomation::WinClicker; if(fork()){ #part one my $clicker = Win32::IEAutomation::WinClicker->new(); $clicker->push_button_save("File Download",50); $clicker->push_button_save("Save As",50); $clicker->push_button_yes("Save As", 50); $clicker->push_confirm_button_cancle("Download Complete",20); } else{ #part 2 Creating new instance of Internet Explorer my $ie = Win32::IEAutomation->new( visible => 1, maximize => 1); # Site navigation $ie->gotoURL('http://xxx.xxx.xxx.com/'); $ie->getTextBox('name:', "USERNAME")->SetValue("xxx"); $ie->getTextBox('name:', "PASSWORD")->SetValue("xxx"); $ie->getButton('name:', "OK")->Click; $ie->getButton('name:', "FINDBUTTON")->Click; $ie->getButton('name:', "BTNEXCEL")->Click; $ie->WaitforDone; # we will wait here for complete load }
Win32::IEAutomation::WinClicker is a wrap of autoit. I found it can't catch the window before it correctly. I trid to split above code to 2 parts and run them separately, it works fine.
but it will throw" can't open IE through OLE" when I use fork to connect them.

Any thoughts?





I am trying to improve my English skills, if you see a mistake please feel free to reply or /msg me a correction

Replies are listed 'Best First'.
Re: fork cant support Win32::OLE ?
by Corion (Patriarch) on Feb 10, 2010 at 16:38 UTC

    fork is emulated barely enough for certain use cases. Sharing resources across that emulation, such as Win32::OLE objects, is not implemented and thus does not work. But as you only want to run two programs in parallel anyway, just use system:

    system('start "Program 1" perl -w program1.pl') == 0 or die "Couldn't launch program1: $!/$?"; system('start "Program 2" perl -w program2.pl') or die "Couldn't launch program2: $!/$?";

    Alternatively, you can use the following form:

    system(1,"perl -w program1.pl") or die "Couldn't launch program1: $!/$?";

    to launch a program without waiting for it.

    Maybe you want to look at WWW::Mechanize and/or WWW::Mechanize::Firefox, which give you more control over what happens?

    UpdateFixed quotes, thanks ikegami!

      The thing is, OLE and Win32::OLE do support multi-threading, and Win32::IEAutomation is pretty straightforward. I think there's more to this story.

      fyi, the problem I have when I run it is a seg fault.

      Thanks for your reply.
      WWW::Mechanize is also the one of my favorite modules. but the web site I want to crawl include javascript heavily. Considering the platform, Win32::IEAutomation should be the best, I think.




      I am trying to improve my English skills, if you see a mistake please feel free to reply or /msg me a correction

      Can I think threads is only/stable way to implement multi-processes snippet in Windows? and I can use threads to connect my snippet above even pass some info between them?




      I am trying to improve my English skills, if you see a mistake please feel free to reply or /msg me a correction

        Yes, but again, sharing (Win32::OLE) resources across threads is not easy. But sharing information between threads is very easy if you use Thread::Queue to send information back and forth, for example. The best is to use OLE objects only in one thread. Also read the section on Win32::OLE->Initialize() and ->SpinMessageLoop documentation.

        Can I think threads is only/stable way to implement multi-processes snippet in Windows?

        No, it's not the only one. In fact, it's not even one of them. Threads don't create processes.

        Neither does fork in Windows. It creates threads to emulate unix's fork.

        I can use threads to connect my snippet above even pass some info between them?

        Yes, through shared variables, pipes, sockets, files, etc. Thread::Queue is very useful if you're making worker threads.

        Considering the platform,

        Considering the platform, don't use fork. Windows doesn't support fork, so it's emulated. If you want to created threads, use threads instead.

        use warnings; use strict; use threads; use Win32::IEAutomation; use Win32::IEAutomation::WinClicker; async { my $clicker = Win32::IEAutomation::WinClicker->new(); # ... }; async { my $ie = Win32::IEAutomation->new( visible => 1, maximize => 1); # ... }; $_->join() for threads->list();

        Note that the above still suffers from your original problem. It's apparently related to threads, not just the fork emulation. (No surprise there.)