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"
39 #include "wx/stream.h"
40 #include "wx/process.h"
43 #include "wx/msw/private.h"
47 #if !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__SALFORDC__) && !defined(__WXMICROWIN__)
54 #if defined(__GNUWIN32__) && !defined(__TWIN32__)
55 #include <sys/unistd.h>
59 #if defined(__WIN32__) && !defined(__WXWINE__) && !defined(__WXMICROWIN__)
71 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
78 #include "wx/dde.h" // for WX_DDE hack in wxExecute
81 // ----------------------------------------------------------------------------
83 // ----------------------------------------------------------------------------
85 // this message is sent when the process we're waiting for terminates
86 #define wxWM_PROC_TERMINATED (WM_USER + 10000)
88 // ----------------------------------------------------------------------------
89 // this module globals
90 // ----------------------------------------------------------------------------
92 // we need to create a hidden window to receive the process termination
93 // notifications and for this we need a (Win) class name for it which we will
94 // register the first time it's needed
95 static const wxChar
*gs_classForHiddenWindow
= NULL
;
97 // ----------------------------------------------------------------------------
99 // ----------------------------------------------------------------------------
101 // structure describing the process we're being waiting for
108 if ( !::CloseHandle(hProcess
) )
110 wxLogLastError(wxT("CloseHandle(hProcess)"));
115 HWND hWnd
; // window to send wxWM_PROC_TERMINATED to
116 HANDLE hProcess
; // handle of the process
117 DWORD dwProcessId
; // pid of the process
119 DWORD dwExitCode
; // the exit code of the process
120 bool state
; // set to FALSE when the process finishes
123 #if defined(__WIN32__) && wxUSE_STREAMS
125 // ----------------------------------------------------------------------------
127 // ----------------------------------------------------------------------------
129 class wxPipeInputStream
: public wxInputStream
132 wxPipeInputStream(HANDLE hInput
);
133 virtual ~wxPipeInputStream();
135 // returns TRUE if the pipe is still opened
136 bool IsOpened() const { return m_hInput
!= INVALID_HANDLE_VALUE
; }
138 // returns TRUE if there is any data to be read from the pipe
139 bool IsAvailable() const;
142 size_t OnSysRead(void *buffer
, size_t len
);
148 class wxPipeOutputStream
: public wxOutputStream
151 wxPipeOutputStream(HANDLE hOutput
);
152 virtual ~wxPipeOutputStream();
155 size_t OnSysWrite(const void *buffer
, size_t len
);
161 // define this to let wxexec.cpp know that we know what we're doing
162 #define _WX_USED_BY_WXEXECUTE_
163 #include "../common/execcmn.cpp"
165 // ----------------------------------------------------------------------------
166 // wxPipe represents a Win32 anonymous pipe
167 // ----------------------------------------------------------------------------
172 // the symbolic names for the pipe ends
179 // default ctor doesn't do anything
180 wxPipe() { m_handles
[Read
] = m_handles
[Write
] = INVALID_HANDLE_VALUE
; }
182 // create the pipe, return TRUE if ok, FALSE on error
185 // default secutiry attributes
186 SECURITY_ATTRIBUTES security
;
188 security
.nLength
= sizeof(security
);
189 security
.lpSecurityDescriptor
= NULL
;
190 security
.bInheritHandle
= TRUE
; // to pass it to the child
192 if ( !::CreatePipe(&m_handles
[0], &m_handles
[1], &security
, 0) )
194 wxLogSysError(_("Failed to create an anonymous pipe"));
202 // return TRUE if we were created successfully
203 bool IsOk() const { return m_handles
[Read
] != INVALID_HANDLE_VALUE
; }
205 // return the descriptor for one of the pipe ends
206 HANDLE
operator[](Direction which
) const
208 wxASSERT_MSG( which
>= 0 && (size_t)which
< WXSIZEOF(m_handles
),
209 _T("invalid pipe index") );
211 return m_handles
[which
];
214 // detach a descriptor, meaning that the pipe dtor won't close it, and
216 HANDLE
Detach(Direction which
)
218 wxASSERT_MSG( which
>= 0 && (size_t)which
< WXSIZEOF(m_handles
),
219 _T("invalid pipe index") );
221 HANDLE handle
= m_handles
[which
];
222 m_handles
[which
] = INVALID_HANDLE_VALUE
;
227 // close the pipe descriptors
230 for ( size_t n
= 0; n
< WXSIZEOF(m_handles
); n
++ )
232 if ( m_handles
[n
] != INVALID_HANDLE_VALUE
)
234 ::CloseHandle(m_handles
[n
]);
235 m_handles
[n
] = INVALID_HANDLE_VALUE
;
240 // dtor closes the pipe descriptors
241 ~wxPipe() { Close(); }
247 #endif // wxUSE_STREAMS
249 // ============================================================================
251 // ============================================================================
255 // ----------------------------------------------------------------------------
256 // process termination detecting support
257 // ----------------------------------------------------------------------------
259 // thread function for the thread monitoring the process termination
260 static DWORD __stdcall
wxExecuteThread(void *arg
)
262 wxExecuteData
*data
= (wxExecuteData
*)arg
;
264 if ( ::WaitForSingleObject(data
->hProcess
, INFINITE
) != WAIT_OBJECT_0
)
266 wxLogDebug(_T("Waiting for the process termination failed!"));
270 if ( !::GetExitCodeProcess(data
->hProcess
, &data
->dwExitCode
) )
272 wxLogLastError(wxT("GetExitCodeProcess"));
275 wxASSERT_MSG( data
->dwExitCode
!= STILL_ACTIVE
,
276 wxT("process should have terminated") );
278 // send a message indicating process termination to the window
279 ::SendMessage(data
->hWnd
, wxWM_PROC_TERMINATED
, 0, (LPARAM
)data
);
284 // window procedure of a hidden window which is created just to receive
285 // the notification message when a process exits
286 LRESULT APIENTRY _EXPORT
wxExecuteWindowCbk(HWND hWnd
, UINT message
,
287 WPARAM wParam
, LPARAM lParam
)
289 if ( message
== wxWM_PROC_TERMINATED
)
291 DestroyWindow(hWnd
); // we don't need it any more
293 wxExecuteData
*data
= (wxExecuteData
*)lParam
;
296 data
->handler
->OnTerminate((int)data
->dwProcessId
,
297 (int)data
->dwExitCode
);
302 // we're executing synchronously, tell the waiting thread
303 // that the process finished
308 // asynchronous execution - we should do the clean up
316 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
320 // ============================================================================
321 // implementation of IO redirection support classes
322 // ============================================================================
326 // ----------------------------------------------------------------------------
327 // wxPipeInputStreams
328 // ----------------------------------------------------------------------------
330 wxPipeInputStream::wxPipeInputStream(HANDLE hInput
)
335 wxPipeInputStream::~wxPipeInputStream()
337 if ( m_hInput
!= INVALID_HANDLE_VALUE
)
338 ::CloseHandle(m_hInput
);
341 bool wxPipeInputStream::IsAvailable() const
352 // function name is misleading, it works with anon pipes as well
353 DWORD rc
= ::PeekNamedPipe
356 NULL
, 0, // ptr to buffer and its size
357 NULL
, // [out] bytes read
358 &nAvailable
, // [out] bytes available
359 NULL
// [out] bytes left
364 if ( ::GetLastError() != ERROR_BROKEN_PIPE
)
367 wxLogLastError(_T("PeekNamedPipe"));
370 // don't try to continue reading from a pipe if an error occured or if
371 // it had been closed
372 ::CloseHandle(m_hInput
);
374 wxConstCast(this, wxPipeInputStream
)->m_hInput
= INVALID_HANDLE_VALUE
;
379 return nAvailable
!= 0;
383 size_t wxPipeInputStream::OnSysRead(void *buffer
, size_t len
)
385 // reading from a pipe may block if there is no more data, always check for
387 if ( !IsAvailable() )
389 m_lasterror
= wxSTREAM_EOF
;
394 m_lasterror
= wxSTREAM_NOERROR
;
397 if ( !::ReadFile(m_hInput
, buffer
, len
, &bytesRead
, NULL
) )
399 if ( ::GetLastError() == ERROR_BROKEN_PIPE
)
400 m_lasterror
= wxSTREAM_EOF
;
402 m_lasterror
= wxSTREAM_READ_ERROR
;
408 // ----------------------------------------------------------------------------
409 // wxPipeOutputStream
410 // ----------------------------------------------------------------------------
412 wxPipeOutputStream::wxPipeOutputStream(HANDLE hOutput
)
417 wxPipeOutputStream::~wxPipeOutputStream()
419 ::CloseHandle(m_hOutput
);
422 size_t wxPipeOutputStream::OnSysWrite(const void *buffer
, size_t len
)
426 m_lasterror
= wxSTREAM_NOERROR
;
427 if ( !::WriteFile(m_hOutput
, buffer
, len
, &bytesRead
, NULL
) )
429 if ( ::GetLastError() == ERROR_BROKEN_PIPE
)
430 m_lasterror
= wxSTREAM_EOF
;
432 m_lasterror
= wxSTREAM_READ_ERROR
;
438 #endif // wxUSE_STREAMS
442 // ============================================================================
443 // wxExecute functions family
444 // ============================================================================
448 // connect to the given server via DDE and ask it to execute the command
449 static bool wxExecuteDDE(const wxString
& ddeServer
,
450 const wxString
& ddeTopic
,
451 const wxString
& ddeCommand
)
456 wxConnectionBase
*conn
= client
.MakeConnection(_T(""),
463 else // connected to DDE server
465 // the added complication here is that although most
466 // programs use XTYP_EXECUTE for their DDE API, some
467 // important ones - like IE and other MS stuff - use
470 // so we try it first and then the other one if it
474 ok
= conn
->Request(ddeCommand
) != NULL
;
479 // now try execute - but show the errors
480 ok
= conn
->Execute(ddeCommand
);
489 long wxExecute(const wxString
& cmd
, int flags
, wxProcess
*handler
)
491 wxCHECK_MSG( !!cmd
, 0, wxT("empty command in wxExecute") );
496 // DDE hack: this is really not pretty, but we need to allow this for
497 // transparent handling of DDE servers in wxMimeTypesManager. Usually it
498 // returns the command which should be run to view/open/... a file of the
499 // given type. Sometimes, however, this command just launches the server
500 // and an additional DDE request must be made to really open the file. To
501 // keep all this well hidden from the application, we allow a special form
502 // of command: WX_DDE#<command>#DDE_SERVER#DDE_TOPIC#DDE_COMMAND in which
503 // case we execute just <command> and process the rest below
504 wxString ddeServer
, ddeTopic
, ddeCommand
;
505 static const size_t lenDdePrefix
= 7; // strlen("WX_DDE:")
506 if ( cmd
.Left(lenDdePrefix
) == _T("WX_DDE#") )
508 // speed up the concatenations below
509 ddeServer
.reserve(256);
510 ddeTopic
.reserve(256);
511 ddeCommand
.reserve(256);
513 const wxChar
*p
= cmd
.c_str() + 7;
514 while ( *p
&& *p
!= _T('#') )
526 wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
529 while ( *p
&& *p
!= _T('#') )
541 wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
544 while ( *p
&& *p
!= _T('#') )
556 wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
564 // if we want to just launch the program and not wait for its
565 // termination, try to execute DDE command right now, it can succeed if
566 // the process is already running - but as it fails if it's not
567 // running, suppress any errors it might generate
568 if ( !(flags
& wxEXEC_SYNC
) )
571 if ( wxExecuteDDE(ddeServer
, ddeTopic
, ddeCommand
) )
573 // a dummy PID - this is a hack, of course, but it's well worth
574 // it as we don't open a new server each time we're called
575 // which would be quite bad
587 #if defined(__WIN32__) && !defined(__TWIN32__)
589 // the IO redirection is only supported with wxUSE_STREAMS
590 BOOL redirect
= FALSE
;
593 wxPipe pipeIn
, pipeOut
, pipeErr
;
595 // we'll save here the copy of pipeIn[Write]
596 HANDLE hpipeStdinWrite
= INVALID_HANDLE_VALUE
;
598 // open the pipes to which child process IO will be redirected if needed
599 if ( handler
&& handler
->IsRedirected() )
601 // create pipes for redirecting stdin, stdout and stderr
602 if ( !pipeIn
.Create() || !pipeOut
.Create() || !pipeErr
.Create() )
604 wxLogSysError(_("Failed to redirect the child process IO"));
606 // indicate failure: we need to return different error code
607 // depending on the sync flag
608 return flags
& wxEXEC_SYNC
? -1 : 0;
613 #endif // wxUSE_STREAMS
615 // create the process
623 si
.dwFlags
= STARTF_USESTDHANDLES
;
625 si
.hStdInput
= pipeIn
[wxPipe::Read
];
626 si
.hStdOutput
= pipeOut
[wxPipe::Write
];
627 si
.hStdError
= pipeErr
[wxPipe::Write
];
629 // when the std IO is redirected, we don't show the (console) process
630 // window by default, but this can be overridden by the caller by
631 // specifying wxEXEC_NOHIDE flag
632 if ( !(flags
& wxEXEC_NOHIDE
) )
634 si
.dwFlags
|= STARTF_USESHOWWINDOW
;
635 si
.wShowWindow
= SW_HIDE
;
638 // we must duplicate the handle to the write side of stdin pipe to make
639 // it non inheritable: indeed, we must close the writing end of pipeIn
640 // before launching the child process as otherwise this handle will be
641 // inherited by the child which will never close it and so the pipe
642 // will never be closed and the child will be left stuck in ReadFile()
643 HANDLE pipeInWrite
= pipeIn
.Detach(wxPipe::Write
);
644 if ( !::DuplicateHandle
646 ::GetCurrentProcess(),
648 ::GetCurrentProcess(),
650 0, // desired access: unused here
651 FALSE
, // not inherited
652 DUPLICATE_SAME_ACCESS
// same access as for src handle
655 wxLogLastError(_T("DuplicateHandle"));
658 ::CloseHandle(pipeInWrite
);
660 #endif // wxUSE_STREAMS
662 PROCESS_INFORMATION pi
;
663 DWORD dwFlags
= CREATE_DEFAULT_ERROR_MODE
| CREATE_SUSPENDED
;
665 bool ok
= ::CreateProcess
667 NULL
, // application name (use only cmd line)
669 command
.c_str(), // full command line
670 NULL
, // security attributes: defaults for both
671 NULL
, // the process and its main thread
672 redirect
, // inherit handles if we use pipes
673 dwFlags
, // process creation flags
674 NULL
, // environment (use the same)
675 NULL
, // current directory (use the same)
676 &si
, // startup info (unused here)
681 // we can close the pipe ends used by child anyhow
684 ::CloseHandle(pipeIn
.Detach(wxPipe::Read
));
685 ::CloseHandle(pipeOut
.Detach(wxPipe::Write
));
686 ::CloseHandle(pipeErr
.Detach(wxPipe::Write
));
688 #endif // wxUSE_STREAMS
693 // close the other handles too
696 ::CloseHandle(pipeOut
.Detach(wxPipe::Read
));
697 ::CloseHandle(pipeErr
.Detach(wxPipe::Read
));
699 #endif // wxUSE_STREAMS
701 wxLogSysError(_("Execution of command '%s' failed"), command
.c_str());
703 return flags
& wxEXEC_SYNC
? -1 : 0;
707 // the input buffer bufOut is connected to stdout, this is why it is
708 // called bufOut and not bufIn
709 wxStreamTempInputBuffer bufOut
,
714 // We can now initialize the wxStreams
716 outStream
= new wxPipeInputStream(pipeOut
.Detach(wxPipe::Read
));
718 errStream
= new wxPipeInputStream(pipeErr
.Detach(wxPipe::Read
));
720 inStream
= new wxPipeOutputStream(hpipeStdinWrite
);
722 handler
->SetPipeStreams(outStream
, inStream
, errStream
);
724 bufOut
.Init(outStream
);
725 bufErr
.Init(errStream
);
727 #endif // wxUSE_STREAMS
729 // register the class for the hidden window used for the notifications
730 if ( !gs_classForHiddenWindow
)
732 gs_classForHiddenWindow
= _T("wxHiddenWindow");
735 wxZeroMemory(wndclass
);
736 wndclass
.lpfnWndProc
= (WNDPROC
)wxExecuteWindowCbk
;
737 wndclass
.hInstance
= wxGetInstance();
738 wndclass
.lpszClassName
= gs_classForHiddenWindow
;
740 if ( !::RegisterClass(&wndclass
) )
742 wxLogLastError(wxT("RegisterClass(hidden window)"));
746 // create a hidden window to receive notification about process
748 HWND hwnd
= ::CreateWindow(gs_classForHiddenWindow
, NULL
,
751 (HMENU
)NULL
, wxGetInstance(), 0);
752 wxASSERT_MSG( hwnd
, wxT("can't create a hidden window for wxExecute") );
755 wxExecuteData
*data
= new wxExecuteData
;
756 data
->hProcess
= pi
.hProcess
;
757 data
->dwProcessId
= pi
.dwProcessId
;
759 data
->state
= (flags
& wxEXEC_SYNC
) != 0;
760 if ( flags
& wxEXEC_SYNC
)
762 // handler may be !NULL for capturing program output, but we don't use
763 // it wxExecuteData struct in this case
764 data
->handler
= NULL
;
768 // may be NULL or not
769 data
->handler
= handler
;
773 HANDLE hThread
= ::CreateThread(NULL
,
780 // resume process we created now - whether the thread creation succeeded or
782 if ( ::ResumeThread(pi
.hThread
) == (DWORD
)-1 )
784 // ignore it - what can we do?
785 wxLogLastError(wxT("ResumeThread in wxExecute"));
788 // close unneeded handle
789 if ( !::CloseHandle(pi
.hThread
) )
790 wxLogLastError(wxT("CloseHandle(hThread)"));
794 wxLogLastError(wxT("CreateThread in wxExecute"));
799 // the process still started up successfully...
800 return pi
.dwProcessId
;
803 ::CloseHandle(hThread
);
806 // second part of DDE hack: now establish the DDE conversation with the
807 // just launched process
808 if ( !ddeServer
.empty() )
812 // give the process the time to init itself
814 // we use a very big timeout hoping that WaitForInputIdle() will return
815 // much sooner, but not INFINITE just in case the process hangs
816 // completely - like this we will regain control sooner or later
817 switch ( ::WaitForInputIdle(pi
.hProcess
, 10000 /* 10 seconds */) )
820 wxFAIL_MSG( _T("unexpected WaitForInputIdle() return code") );
824 wxLogLastError(_T("WaitForInputIdle() in wxExecute"));
827 wxLogDebug(_T("Timeout too small in WaitForInputIdle"));
833 // ok, process ready to accept DDE requests
834 ok
= wxExecuteDDE(ddeServer
, ddeTopic
, ddeCommand
);
839 if ( !(flags
& wxEXEC_SYNC
) )
841 // clean up will be done when the process terminates
844 return pi
.dwProcessId
;
847 // disable all app windows while waiting for the child process to finish
851 We use a dirty hack here to disable all application windows (which we
852 must do because otherwise the calls to wxYield() could lead to some very
853 unexpected reentrancies in the users code) but to avoid losing
854 focus/activation entirely when the child process terminates which would
855 happen if we simply disabled everything using wxWindowDisabler. Indeed,
856 remember that Windows will never activate a disabled window and when the
857 last childs window is closed and Windows looks for a window to activate
858 all our windows are still disabled. There is no way to enable them in
859 time because we don't know when the childs windows are going to be
860 closed, so the solution we use here is to keep one special tiny frame
861 enabled all the time. Then when the child terminates it will get
862 activated and when we close it below -- after reenabling all the other
863 windows! -- the previously active window becomes activated again and
870 // first disable all existing windows
873 // then create an "invisible" frame: it has minimal size, is positioned
874 // (hopefully) outside the screen and doesn't appear on the taskbar
875 winActive
= new wxFrame
877 wxTheApp
->GetTopWindow(),
880 wxPoint(32600, 32600),
882 wxDEFAULT_FRAME_STYLE
| wxFRAME_NO_TASKBAR
887 // wait until the child process terminates
888 while ( data
->state
)
893 #endif // wxUSE_STREAMS
895 // don't eat 100% of the CPU -- ugly but anything else requires
896 // real async IO which we don't have for the moment
906 // finally delete the dummy frame and, as wd has been already destroyed and
907 // the other windows reenabled, the activation is going to return to the
908 // window which had it before
909 winActive
->Destroy();
912 DWORD dwExitCode
= data
->dwExitCode
;
915 // return the exit code
918 long instanceID
= WinExec((LPCSTR
) WXSTRINGCAST command
, SW_SHOW
);
920 return flags
& wxEXEC_SYNC
? -1 : 0;
922 if ( flags
& wxEXEC_SYNC
)
928 running
= GetModuleUsage((HINSTANCE
)instanceID
);
936 long wxExecute(wxChar
**argv
, int flags
, wxProcess
*handler
)
949 return wxExecute(command
, flags
, handler
);