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

Hello all, I have written a perl::tk script and I'm having some problems with one (relatively minor) portion of it. The app browses through a bunch of text files and looks for anything that starts with http://, if it finds it, it will add the line to a new Toplevel listwindow. On click of that line, I want to launch IE and go to the link that was found. This is all working fine, the problem occurs when you click a second link while the first launched instance of IE is still up (regardless of what else you have done in the meantime - typically have killed the toplevel window. At that point, the app hangs until you close IE. Then it proceeds to go ahead and launch a new instance of IE with the second clicked on link. Here's the code snippet..

sub launchie{ $link = $linklistbox->get($linklistbox->curselection()); open (IE,"|c:/progra~1/intern~1/iexplore.exe $link") || die "Could + not open $link $1"; }

So, what have I done wrong?

Replies are listed 'Best First'.
(jcwren) RE: Launch and forget
by jcwren (Prior) on Sep 02, 2000 at 10:39 UTC
    The problem is that open() is waiting for the process to finish, before returning control to your program. There is an easy solution to what you're trying to do. Check out (jcwren) RE: loading.

    Update: perlwin32faq5 talks about what functions are not supported in the Win32 environment. Here's a link to the FAQ (which for some reason, I can't find on the ActiveState site...). Also, the ORA 'Learning Perl on Win32 Systems' book doesn't not mention fork() anywhere in it.

    --Chris

    e-mail jcwren
      Thank you, this seems to work. I don't know why I didn't think of "start" before. I had played around with cmd.exe and launching it using different tags..

      At the same time, open was not actually waiting for the process. After the first open call, my program was still functional etc, it was not until after the second open call (to the same FH) that the program would hang.

      For example, using the code above, I was able to make it work using a horrible kludge, simply call the FH the $link. so..
      open ($link,"|pathtoie $link") || die "Could not launch $!";
      I'm curious though, why this works. I was able to open 2 instances of IE using the same $link for the filehandle. Yet, I was unable to do it using just "IE" for the filehandle name.
Re: Launch and forget
by Shendal (Hermit) on Sep 05, 2000 at 22:19 UTC
    Use Win32::Process. It's the only way I've found to reliably do this. You can check my script, Perl/Tk Chatterbox Client, which employs this technique. Essentially, you create a new detached process. For example,
    use Win32::Process; Win32::Process::Create($Process, "c:\\winnt\\system32\\notepad.exe", "notepad", 0, DETACHED_PROCESS, ".") || die "Create: $!";

    Cheers,
    Shendal
RE: Launch and forget
by the_slycer (Chaplain) on Sep 02, 2000 at 09:08 UTC
    Uh-oh..
    I think I just realized what I've done wrong here..
    It's got to do with the filehandle right? Can't open the same one twice.. doh!
    So, how do I solve this then? I was using backquotes to lauch IE before, but that was worse, it would hang the app until you closed IE.. I would rather not add any more modules to the prog because I am using perl2exe, and currently my 5k program is at 1.8 meg when compiled. Note, I am using perl2exe so that I can distribute this without having to install perl on ~80 machines.

    Any ideas?
      Perhaps something like this:
      { defined(my $kid = fork) or die "Cannot fork kid: $!"; unless ($kid) { exec "/path/to/ie", "param1", "param2" or die "Cannot exec ie: $!" +; } }
      If your Tk program runs for a long time, you should "double fork" to make IE the grandkid, and then wait for the kid, or else invoke waitpid from time to time to ensure that the kid process gets reaped occasionally.

      -- Randal L. Schwartz, Perl hacker

        I tried this, and it crashes my program on windows. :-(