On Sat, 28 Jul 2007, Robert May wrote: > Here's what happens - the call to system, or using backticks, makes a > request to the OS to find the program associated with *.html files, > launch it (if it isn't already running) and ask it to open the html > file. > > As part of the process of finding out if there is already a running > program of the right type the OS may attempt (depending on the program > and it's associated registry values) to use a technique called DDE - > if it does try this mechanism, the in broadcasts a WM_DDE_INITIATE > message to every top-level window in the system, and waits for each > one to reply. In this case we have a top-level window ($main), and so > the system sends this message to our top level window, but because we > are not in a message loop we never respond, and the system has to wait > for a timeout (typically about 30 seconds). > > The code in perl behind the system call *should* be handling > WM_DDE_INITIATE messages, but is not (at least not in the version of > perl you are running) > > There are 2 ways that I can see to resolve this for now. > (1) As I already suggested do 'undef $main' before making the shell > call - this destroys our window so we no longer have a top level > window. > (2) Use ShellExecute, which spins its own internal message loop until > the DDE initialisation is complete. Something like this: > $main->ShellExecute("", "temp.html", "", "", SW_SHOW);
On 28/07/07, Jan Dubois <[EMAIL PROTECTED]> wrote: > This does not sound plausible to me: system("start foo.html") will > end up calling CreateProcess() on command.com/cmd.exe because start > is an intrinsic shell command and will not be found on the PATH. On Win98 it's not a shell buit-in, it's a command called start.exe. I'm not sure this affects things though. > CreateProcess() will return and not wait for command.com/cmd.exe to > initialize. Upon return win32_spawnvp() will call win32_msgwait(), > which should continue to pump the message loop until the external > process ends. That's what's supposed to happen, but in AS build 819 on win98 (that's all I have access to this weekend), I have to change the flags to MsgWaitForMultipleObjects from QS_ALLEVENTS to QS_ALLEVENTS|QS_SENDMESSAGE to get it to pump the sent WM_DDE_INITIATE message. Further to this, in bleed and AS build 820 we changed the flags to MsgWaitForMultipleObjects from QS_ALLEVENTS to QS_POSTMESSAGE|QS_TIMER. This won't have improved things. Here's what I think happens: (1) the 'system' call results in a new process being started (either start.exe or cmd.exe depending on OS). The new process is not initialised by the time CreateProcess returns. (2) When CreateProcess returns win32_spawnvp calls into win32_msgwait to wait for the external command to finish. (3) the external command (whether start.exe or cmd.exe's builtin) passes what it has been asked to start - in this case something.html - to ShellExeculte() which in turn looks up the class key for .html in the registry. There it finds a ddeexec key, and so starts a DDE conversation. The first part of the DDE conversation is to broadcast a WM_DDE_INITIATE message to all top-level windows (As far as I can tell this is done with something like SendMessageTimeout(HWND_BROADCAST, ..... )) (4) If our process has a top level window, then that top level window is sent a WM_DDE_INITIATE message by the new external process, but win32_msgwait() is not pumping sent messages, and so our process does not respond, and there is a delay while the external process times out waiting for us. The worst thing about this is that if we are in a long-running "system" call, and have a top-level window, then we will cause delays to *any* other DDE communications. Try running this: #!perl -w use strict; use warnings; use Win32::GUI(); my $mw = Win32::GUI::Window->new; system "notepad.exe"; And while notepad is still open, double-click an html file on your desktop - you'll get a 30 second delay before your browser shows the page. > But even if it didn't, the "start" command is just a commandline > interface to the ShellExecuteEx() function called from cmd.exe, > so it wouldn't be any different from your solution (2) above. It is different. ShellExecute spins a message-loop in the thread from which it is called. In the case of using the start command the ShellExecuteEx() is called in the context on the newly created process, and spins a message loop in the newly started thread. In my example the call to ShellExecute() is in the perl process, and so spins it's message loop within the perl main thread, which is where we need a message loop to pump the received WM_DDE_INITIATE message. I'm at a bit of a disadvantage not having a Win2K machine to hand to check this thoroughly (I'll try to do that on Monday or Tuesday). I'm not sure that I entirely understand the implication of adding QS_SENDMESSAGE to win32_msgwait. I think it only affects cross-process and cross-thread sent messages (as all intra-process sent messages get dispatched directly to the windproc for the window). Regards, Rob. ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ Perl-Win32-GUI-Users mailing list Perl-Win32-GUI-Users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/perl-win32-gui-users http://perl-win32-gui.sourceforge.net/