1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/utilsexec.cpp
3 // Purpose: wxExecute implementation for MSW
4 // Author: Julian Smart
8 // Copyright: (c) 1998-2002 wxWindows dev team
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
36 #if wxUSE_GUI // See 'dirty hack' below.
42 #include "wx/stream.h"
43 #include "wx/process.h"
46 #include "wx/msw/private.h"
50 #if !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__SALFORDC__) && !defined(__WXMICROWIN__)
57 #if defined(__GNUWIN32__) && !defined(__TWIN32__)
58 #include <sys/unistd.h>
62 #if defined(__WIN32__) && !defined(__WXWINE__) && !defined(__WXMICROWIN__)
74 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
81 #include "wx/dde.h" // for WX_DDE hack in wxExecute
84 // ----------------------------------------------------------------------------
86 // ----------------------------------------------------------------------------
88 // this message is sent when the process we're waiting for terminates
89 #define wxWM_PROC_TERMINATED (WM_USER + 10000)
91 // ----------------------------------------------------------------------------
92 // this module globals
93 // ----------------------------------------------------------------------------
95 // we need to create a hidden window to receive the process termination
96 // notifications and for this we need a (Win) class name for it which we will
97 // register the first time it's needed
98 static const wxChar
*gs_classForHiddenWindow
= NULL
;
100 // ----------------------------------------------------------------------------
102 // ----------------------------------------------------------------------------
104 // structure describing the process we're being waiting for
111 if ( !::CloseHandle(hProcess
) )
113 wxLogLastError(wxT("CloseHandle(hProcess)"));
118 HWND hWnd
; // window to send wxWM_PROC_TERMINATED to
119 HANDLE hProcess
; // handle of the process
120 DWORD dwProcessId
; // pid of the process
122 DWORD dwExitCode
; // the exit code of the process
123 bool state
; // set to FALSE when the process finishes
126 #if defined(__WIN32__) && wxUSE_STREAMS
128 // ----------------------------------------------------------------------------
130 // ----------------------------------------------------------------------------
132 class wxPipeInputStream
: public wxInputStream
135 wxPipeInputStream(HANDLE hInput
);
136 virtual ~wxPipeInputStream();
138 // returns TRUE if the pipe is still opened
139 bool IsOpened() const { return m_hInput
!= INVALID_HANDLE_VALUE
; }
141 // returns TRUE if there is any data to be read from the pipe
142 bool IsAvailable() const;
145 size_t OnSysRead(void *buffer
, size_t len
);
151 class wxPipeOutputStream
: public wxOutputStream
154 wxPipeOutputStream(HANDLE hOutput
);
155 virtual ~wxPipeOutputStream();
158 size_t OnSysWrite(const void *buffer
, size_t len
);
164 // define this to let wxexec.cpp know that we know what we're doing
165 #define _WX_USED_BY_WXEXECUTE_
166 #include "../common/execcmn.cpp"
168 // ----------------------------------------------------------------------------
169 // wxPipe represents a Win32 anonymous pipe
170 // ----------------------------------------------------------------------------
175 // the symbolic names for the pipe ends
182 // default ctor doesn't do anything
183 wxPipe() { m_handles
[Read
] = m_handles
[Write
] = INVALID_HANDLE_VALUE
; }
185 // create the pipe, return TRUE if ok, FALSE on error
188 // default secutiry attributes
189 SECURITY_ATTRIBUTES security
;
191 security
.nLength
= sizeof(security
);
192 security
.lpSecurityDescriptor
= NULL
;
193 security
.bInheritHandle
= TRUE
; // to pass it to the child
195 if ( !::CreatePipe(&m_handles
[0], &m_handles
[1], &security
, 0) )
197 wxLogSysError(_("Failed to create an anonymous pipe"));
205 // return TRUE if we were created successfully
206 bool IsOk() const { return m_handles
[Read
] != INVALID_HANDLE_VALUE
; }
208 // return the descriptor for one of the pipe ends
209 HANDLE
operator[](Direction which
) const
211 wxASSERT_MSG( which
>= 0 && (size_t)which
< WXSIZEOF(m_handles
),
212 _T("invalid pipe index") );
214 return m_handles
[which
];
217 // detach a descriptor, meaning that the pipe dtor won't close it, and
219 HANDLE
Detach(Direction which
)
221 wxASSERT_MSG( which
>= 0 && (size_t)which
< WXSIZEOF(m_handles
),
222 _T("invalid pipe index") );
224 HANDLE handle
= m_handles
[which
];
225 m_handles
[which
] = INVALID_HANDLE_VALUE
;
230 // close the pipe descriptors
233 for ( size_t n
= 0; n
< WXSIZEOF(m_handles
); n
++ )
235 if ( m_handles
[n
] != INVALID_HANDLE_VALUE
)
237 ::CloseHandle(m_handles
[n
]);
238 m_handles
[n
] = INVALID_HANDLE_VALUE
;
243 // dtor closes the pipe descriptors
244 ~wxPipe() { Close(); }
250 #endif // wxUSE_STREAMS
252 // ============================================================================
254 // ============================================================================
258 // ----------------------------------------------------------------------------
259 // process termination detecting support
260 // ----------------------------------------------------------------------------
262 // thread function for the thread monitoring the process termination
263 static DWORD __stdcall
wxExecuteThread(void *arg
)
265 wxExecuteData
* const data
= (wxExecuteData
*)arg
;
267 if ( ::WaitForSingleObject(data
->hProcess
, INFINITE
) != WAIT_OBJECT_0
)
269 wxLogDebug(_T("Waiting for the process termination failed!"));
273 if ( !::GetExitCodeProcess(data
->hProcess
, &data
->dwExitCode
) )
275 wxLogLastError(wxT("GetExitCodeProcess"));
278 wxASSERT_MSG( data
->dwExitCode
!= STILL_ACTIVE
,
279 wxT("process should have terminated") );
281 // send a message indicating process termination to the window
282 ::SendMessage(data
->hWnd
, wxWM_PROC_TERMINATED
, 0, (LPARAM
)data
);
287 // window procedure of a hidden window which is created just to receive
288 // the notification message when a process exits
289 LRESULT APIENTRY _EXPORT
wxExecuteWindowCbk(HWND hWnd
, UINT message
,
290 WPARAM wParam
, LPARAM lParam
)
292 if ( message
== wxWM_PROC_TERMINATED
)
294 DestroyWindow(hWnd
); // we don't need it any more
296 wxExecuteData
* const data
= (wxExecuteData
*)lParam
;
299 data
->handler
->OnTerminate((int)data
->dwProcessId
,
300 (int)data
->dwExitCode
);
305 // we're executing synchronously, tell the waiting thread
306 // that the process finished
311 // asynchronous execution - we should do the clean up
319 return ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
323 // ============================================================================
324 // implementation of IO redirection support classes
325 // ============================================================================
329 // ----------------------------------------------------------------------------
330 // wxPipeInputStreams
331 // ----------------------------------------------------------------------------
333 wxPipeInputStream::wxPipeInputStream(HANDLE hInput
)
338 wxPipeInputStream::~wxPipeInputStream()
340 if ( m_hInput
!= INVALID_HANDLE_VALUE
)
341 ::CloseHandle(m_hInput
);
344 bool wxPipeInputStream::IsAvailable() const
355 // function name is misleading, it works with anon pipes as well
356 DWORD rc
= ::PeekNamedPipe
359 NULL
, 0, // ptr to buffer and its size
360 NULL
, // [out] bytes read
361 &nAvailable
, // [out] bytes available
362 NULL
// [out] bytes left
367 if ( ::GetLastError() != ERROR_BROKEN_PIPE
)
370 wxLogLastError(_T("PeekNamedPipe"));
373 // don't try to continue reading from a pipe if an error occured or if
374 // it had been closed
375 ::CloseHandle(m_hInput
);
377 wxConstCast(this, wxPipeInputStream
)->m_hInput
= INVALID_HANDLE_VALUE
;
382 return nAvailable
!= 0;
386 size_t wxPipeInputStream::OnSysRead(void *buffer
, size_t len
)
388 // reading from a pipe may block if there is no more data, always check for
390 if ( !IsAvailable() )
392 m_lasterror
= wxSTREAM_EOF
;
397 m_lasterror
= wxSTREAM_NOERROR
;
400 if ( !::ReadFile(m_hInput
, buffer
, len
, &bytesRead
, NULL
) )
402 if ( ::GetLastError() == ERROR_BROKEN_PIPE
)
403 m_lasterror
= wxSTREAM_EOF
;
405 m_lasterror
= wxSTREAM_READ_ERROR
;
411 // ----------------------------------------------------------------------------
412 // wxPipeOutputStream
413 // ----------------------------------------------------------------------------
415 wxPipeOutputStream::wxPipeOutputStream(HANDLE hOutput
)
420 wxPipeOutputStream::~wxPipeOutputStream()
422 ::CloseHandle(m_hOutput
);
425 size_t wxPipeOutputStream::OnSysWrite(const void *buffer
, size_t len
)
429 m_lasterror
= wxSTREAM_NOERROR
;
430 if ( !::WriteFile(m_hOutput
, buffer
, len
, &bytesRead
, NULL
) )
432 if ( ::GetLastError() == ERROR_BROKEN_PIPE
)
433 m_lasterror
= wxSTREAM_EOF
;
435 m_lasterror
= wxSTREAM_READ_ERROR
;
441 #endif // wxUSE_STREAMS
445 // ============================================================================
446 // wxExecute functions family
447 // ============================================================================
451 // connect to the given server via DDE and ask it to execute the command
452 static bool wxExecuteDDE(const wxString
& ddeServer
,
453 const wxString
& ddeTopic
,
454 const wxString
& ddeCommand
)
459 wxConnectionBase
*conn
= client
.MakeConnection(_T(""),
466 else // connected to DDE server
468 // the added complication here is that although most
469 // programs use XTYP_EXECUTE for their DDE API, some
470 // important ones - like IE and other MS stuff - use
473 // so we try it first and then the other one if it
477 ok
= conn
->Request(ddeCommand
) != NULL
;
482 // now try execute - but show the errors
483 ok
= conn
->Execute(ddeCommand
);
492 long wxExecute(const wxString
& cmd
, int flags
, wxProcess
*handler
)
494 wxCHECK_MSG( !!cmd
, 0, wxT("empty command in wxExecute") );
499 // DDE hack: this is really not pretty, but we need to allow this for
500 // transparent handling of DDE servers in wxMimeTypesManager. Usually it
501 // returns the command which should be run to view/open/... a file of the
502 // given type. Sometimes, however, this command just launches the server
503 // and an additional DDE request must be made to really open the file. To
504 // keep all this well hidden from the application, we allow a special form
505 // of command: WX_DDE#<command>#DDE_SERVER#DDE_TOPIC#DDE_COMMAND in which
506 // case we execute just <command> and process the rest below
507 wxString ddeServer
, ddeTopic
, ddeCommand
;
508 static const size_t lenDdePrefix
= 7; // strlen("WX_DDE:")
509 if ( cmd
.Left(lenDdePrefix
) == _T("WX_DDE#") )
511 // speed up the concatenations below
512 ddeServer
.reserve(256);
513 ddeTopic
.reserve(256);
514 ddeCommand
.reserve(256);
516 const wxChar
*p
= cmd
.c_str() + 7;
517 while ( *p
&& *p
!= _T('#') )
529 wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
532 while ( *p
&& *p
!= _T('#') )
544 wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
547 while ( *p
&& *p
!= _T('#') )
559 wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
567 // if we want to just launch the program and not wait for its
568 // termination, try to execute DDE command right now, it can succeed if
569 // the process is already running - but as it fails if it's not
570 // running, suppress any errors it might generate
571 if ( !(flags
& wxEXEC_SYNC
) )
574 if ( wxExecuteDDE(ddeServer
, ddeTopic
, ddeCommand
) )
576 // a dummy PID - this is a hack, of course, but it's well worth
577 // it as we don't open a new server each time we're called
578 // which would be quite bad
590 #if defined(__WIN32__) && !defined(__TWIN32__)
592 // the IO redirection is only supported with wxUSE_STREAMS
593 BOOL redirect
= FALSE
;
596 wxPipe pipeIn
, pipeOut
, pipeErr
;
598 // we'll save here the copy of pipeIn[Write]
599 HANDLE hpipeStdinWrite
= INVALID_HANDLE_VALUE
;
601 // open the pipes to which child process IO will be redirected if needed
602 if ( handler
&& handler
->IsRedirected() )
604 // create pipes for redirecting stdin, stdout and stderr
605 if ( !pipeIn
.Create() || !pipeOut
.Create() || !pipeErr
.Create() )
607 wxLogSysError(_("Failed to redirect the child process IO"));
609 // indicate failure: we need to return different error code
610 // depending on the sync flag
611 return flags
& wxEXEC_SYNC
? -1 : 0;
616 #endif // wxUSE_STREAMS
618 // create the process
626 si
.dwFlags
= STARTF_USESTDHANDLES
;
628 si
.hStdInput
= pipeIn
[wxPipe::Read
];
629 si
.hStdOutput
= pipeOut
[wxPipe::Write
];
630 si
.hStdError
= pipeErr
[wxPipe::Write
];
632 // when the std IO is redirected, we don't show the (console) process
633 // window by default, but this can be overridden by the caller by
634 // specifying wxEXEC_NOHIDE flag
635 if ( !(flags
& wxEXEC_NOHIDE
) )
637 si
.dwFlags
|= STARTF_USESHOWWINDOW
;
638 si
.wShowWindow
= SW_HIDE
;
641 // we must duplicate the handle to the write side of stdin pipe to make
642 // it non inheritable: indeed, we must close the writing end of pipeIn
643 // before launching the child process as otherwise this handle will be
644 // inherited by the child which will never close it and so the pipe
645 // will never be closed and the child will be left stuck in ReadFile()
646 HANDLE pipeInWrite
= pipeIn
.Detach(wxPipe::Write
);
647 if ( !::DuplicateHandle
649 ::GetCurrentProcess(),
651 ::GetCurrentProcess(),
653 0, // desired access: unused here
654 FALSE
, // not inherited
655 DUPLICATE_SAME_ACCESS
// same access as for src handle
658 wxLogLastError(_T("DuplicateHandle"));
661 ::CloseHandle(pipeInWrite
);
663 #endif // wxUSE_STREAMS
665 PROCESS_INFORMATION pi
;
666 DWORD dwFlags
= CREATE_DEFAULT_ERROR_MODE
| CREATE_SUSPENDED
;
668 bool ok
= ::CreateProcess
670 NULL
, // application name (use only cmd line)
672 command
.c_str(), // full command line
673 NULL
, // security attributes: defaults for both
674 NULL
, // the process and its main thread
675 redirect
, // inherit handles if we use pipes
676 dwFlags
, // process creation flags
677 NULL
, // environment (use the same)
678 NULL
, // current directory (use the same)
679 &si
, // startup info (unused here)
684 // we can close the pipe ends used by child anyhow
687 ::CloseHandle(pipeIn
.Detach(wxPipe::Read
));
688 ::CloseHandle(pipeOut
.Detach(wxPipe::Write
));
689 ::CloseHandle(pipeErr
.Detach(wxPipe::Write
));
691 #endif // wxUSE_STREAMS
696 // close the other handles too
699 ::CloseHandle(pipeOut
.Detach(wxPipe::Read
));
700 ::CloseHandle(pipeErr
.Detach(wxPipe::Read
));
702 #endif // wxUSE_STREAMS
704 wxLogSysError(_("Execution of command '%s' failed"), command
.c_str());
706 return flags
& wxEXEC_SYNC
? -1 : 0;
710 // the input buffer bufOut is connected to stdout, this is why it is
711 // called bufOut and not bufIn
712 wxStreamTempInputBuffer bufOut
,
717 // We can now initialize the wxStreams
719 outStream
= new wxPipeInputStream(pipeOut
.Detach(wxPipe::Read
));
721 errStream
= new wxPipeInputStream(pipeErr
.Detach(wxPipe::Read
));
723 inStream
= new wxPipeOutputStream(hpipeStdinWrite
);
725 handler
->SetPipeStreams(outStream
, inStream
, errStream
);
727 bufOut
.Init(outStream
);
728 bufErr
.Init(errStream
);
730 #endif // wxUSE_STREAMS
732 // register the class for the hidden window used for the notifications
733 if ( !gs_classForHiddenWindow
)
735 gs_classForHiddenWindow
= _T("wxHiddenWindow");
738 wxZeroMemory(wndclass
);
739 wndclass
.lpfnWndProc
= (WNDPROC
)wxExecuteWindowCbk
;
740 wndclass
.hInstance
= wxGetInstance();
741 wndclass
.lpszClassName
= gs_classForHiddenWindow
;
743 if ( !::RegisterClass(&wndclass
) )
745 wxLogLastError(wxT("RegisterClass(hidden window)"));
749 // create a hidden window to receive notification about process
751 HWND hwnd
= ::CreateWindow(gs_classForHiddenWindow
, NULL
,
754 (HMENU
)NULL
, wxGetInstance(), 0);
755 wxASSERT_MSG( hwnd
, wxT("can't create a hidden window for wxExecute") );
758 wxExecuteData
*data
= new wxExecuteData
;
759 data
->hProcess
= pi
.hProcess
;
760 data
->dwProcessId
= pi
.dwProcessId
;
762 data
->state
= (flags
& wxEXEC_SYNC
) != 0;
763 if ( flags
& wxEXEC_SYNC
)
765 // handler may be !NULL for capturing program output, but we don't use
766 // it wxExecuteData struct in this case
767 data
->handler
= NULL
;
771 // may be NULL or not
772 data
->handler
= handler
;
776 HANDLE hThread
= ::CreateThread(NULL
,
783 // resume process we created now - whether the thread creation succeeded or
785 if ( ::ResumeThread(pi
.hThread
) == (DWORD
)-1 )
787 // ignore it - what can we do?
788 wxLogLastError(wxT("ResumeThread in wxExecute"));
791 // close unneeded handle
792 if ( !::CloseHandle(pi
.hThread
) )
793 wxLogLastError(wxT("CloseHandle(hThread)"));
797 wxLogLastError(wxT("CreateThread in wxExecute"));
802 // the process still started up successfully...
803 return pi
.dwProcessId
;
806 ::CloseHandle(hThread
);
809 // second part of DDE hack: now establish the DDE conversation with the
810 // just launched process
811 if ( !ddeServer
.empty() )
815 // give the process the time to init itself
817 // we use a very big timeout hoping that WaitForInputIdle() will return
818 // much sooner, but not INFINITE just in case the process hangs
819 // completely - like this we will regain control sooner or later
820 switch ( ::WaitForInputIdle(pi
.hProcess
, 10000 /* 10 seconds */) )
823 wxFAIL_MSG( _T("unexpected WaitForInputIdle() return code") );
827 wxLogLastError(_T("WaitForInputIdle() in wxExecute"));
830 wxLogDebug(_T("Timeout too small in WaitForInputIdle"));
836 // ok, process ready to accept DDE requests
837 ok
= wxExecuteDDE(ddeServer
, ddeTopic
, ddeCommand
);
842 if ( !(flags
& wxEXEC_SYNC
) )
844 // clean up will be done when the process terminates
847 return pi
.dwProcessId
;
850 // disable all app windows while waiting for the child process to finish
854 We use a dirty hack here to disable all application windows (which we
855 must do because otherwise the calls to wxYield() could lead to some very
856 unexpected reentrancies in the users code) but to avoid losing
857 focus/activation entirely when the child process terminates which would
858 happen if we simply disabled everything using wxWindowDisabler. Indeed,
859 remember that Windows will never activate a disabled window and when the
860 last childs window is closed and Windows looks for a window to activate
861 all our windows are still disabled. There is no way to enable them in
862 time because we don't know when the childs windows are going to be
863 closed, so the solution we use here is to keep one special tiny frame
864 enabled all the time. Then when the child terminates it will get
865 activated and when we close it below -- after reenabling all the other
866 windows! -- the previously active window becomes activated again and
873 // first disable all existing windows
876 // then create an "invisible" frame: it has minimal size, is positioned
877 // (hopefully) outside the screen and doesn't appear on the taskbar
878 winActive
= new wxFrame
880 wxTheApp
->GetTopWindow(),
883 wxPoint(32600, 32600),
885 wxDEFAULT_FRAME_STYLE
| wxFRAME_NO_TASKBAR
890 // wait until the child process terminates
891 while ( data
->state
)
896 #endif // wxUSE_STREAMS
898 // don't eat 100% of the CPU -- ugly but anything else requires
899 // real async IO which we don't have for the moment
906 // dispatch the messages to the hidden window so that it could
907 // process the wxWM_PROC_TERMINATED notification
909 ::PeekMessage(&msg
, hwnd
, 0, 0, PM_REMOVE
);
916 // finally delete the dummy frame and, as wd has been already destroyed and
917 // the other windows reenabled, the activation is going to return to the
918 // window which had it before
919 winActive
->Destroy();
922 DWORD dwExitCode
= data
->dwExitCode
;
925 // return the exit code
928 long instanceID
= WinExec((LPCSTR
) WXSTRINGCAST command
, SW_SHOW
);
930 return flags
& wxEXEC_SYNC
? -1 : 0;
932 if ( flags
& wxEXEC_SYNC
)
938 running
= GetModuleUsage((HINSTANCE
)instanceID
);
946 long wxExecute(wxChar
**argv
, int flags
, wxProcess
*handler
)
959 return wxExecute(command
, flags
, handler
);