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 licence
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(__SALFORDC__) && !defined(__WXMICROWIN__)
57 #if defined(__GNUWIN32__)
58 #include <sys/unistd.h>
62 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
76 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
83 #include "wx/dde.h" // for WX_DDE hack in wxExecute
86 // ----------------------------------------------------------------------------
88 // ----------------------------------------------------------------------------
90 // this message is sent when the process we're waiting for terminates
91 #define wxWM_PROC_TERMINATED (WM_USER + 10000)
93 // ----------------------------------------------------------------------------
94 // this module globals
95 // ----------------------------------------------------------------------------
97 // we need to create a hidden window to receive the process termination
98 // notifications and for this we need a (Win) class name for it which we will
99 // register the first time it's needed
100 static const wxChar
*gs_classForHiddenWindow
= NULL
;
102 // ----------------------------------------------------------------------------
104 // ----------------------------------------------------------------------------
106 // structure describing the process we're being waiting for
113 if ( !::CloseHandle(hProcess
) )
115 wxLogLastError(wxT("CloseHandle(hProcess)"));
120 HWND hWnd
; // window to send wxWM_PROC_TERMINATED to
121 HANDLE hProcess
; // handle of the process
122 DWORD dwProcessId
; // pid of the process
124 DWORD dwExitCode
; // the exit code of the process
125 bool state
; // set to FALSE when the process finishes
128 #if defined(__WIN32__) && wxUSE_STREAMS
130 // ----------------------------------------------------------------------------
132 // ----------------------------------------------------------------------------
134 class wxPipeInputStream
: public wxInputStream
137 wxPipeInputStream(HANDLE hInput
);
138 virtual ~wxPipeInputStream();
140 // returns TRUE if the pipe is still opened
141 bool IsOpened() const { return m_hInput
!= INVALID_HANDLE_VALUE
; }
143 // returns TRUE if there is any data to be read from the pipe
144 virtual bool CanRead() const;
147 size_t OnSysRead(void *buffer
, size_t len
);
152 DECLARE_NO_COPY_CLASS(wxPipeInputStream
)
155 class wxPipeOutputStream
: public wxOutputStream
158 wxPipeOutputStream(HANDLE hOutput
);
159 virtual ~wxPipeOutputStream();
162 size_t OnSysWrite(const void *buffer
, size_t len
);
167 DECLARE_NO_COPY_CLASS(wxPipeOutputStream
)
170 // define this to let wxexec.cpp know that we know what we're doing
171 #define _WX_USED_BY_WXEXECUTE_
172 #include "../common/execcmn.cpp"
174 // ----------------------------------------------------------------------------
175 // wxPipe represents a Win32 anonymous pipe
176 // ----------------------------------------------------------------------------
181 // the symbolic names for the pipe ends
188 // default ctor doesn't do anything
189 wxPipe() { m_handles
[Read
] = m_handles
[Write
] = INVALID_HANDLE_VALUE
; }
191 // create the pipe, return TRUE if ok, FALSE on error
194 // default secutiry attributes
195 SECURITY_ATTRIBUTES security
;
197 security
.nLength
= sizeof(security
);
198 security
.lpSecurityDescriptor
= NULL
;
199 security
.bInheritHandle
= TRUE
; // to pass it to the child
201 if ( !::CreatePipe(&m_handles
[0], &m_handles
[1], &security
, 0) )
203 wxLogSysError(_("Failed to create an anonymous pipe"));
211 // return TRUE if we were created successfully
212 bool IsOk() const { return m_handles
[Read
] != INVALID_HANDLE_VALUE
; }
214 // return the descriptor for one of the pipe ends
215 HANDLE
operator[](Direction which
) const
217 wxASSERT_MSG( which
>= 0 && (size_t)which
< WXSIZEOF(m_handles
),
218 _T("invalid pipe index") );
220 return m_handles
[which
];
223 // detach a descriptor, meaning that the pipe dtor won't close it, and
225 HANDLE
Detach(Direction which
)
227 wxASSERT_MSG( which
>= 0 && (size_t)which
< WXSIZEOF(m_handles
),
228 _T("invalid pipe index") );
230 HANDLE handle
= m_handles
[which
];
231 m_handles
[which
] = INVALID_HANDLE_VALUE
;
236 // close the pipe descriptors
239 for ( size_t n
= 0; n
< WXSIZEOF(m_handles
); n
++ )
241 if ( m_handles
[n
] != INVALID_HANDLE_VALUE
)
243 ::CloseHandle(m_handles
[n
]);
244 m_handles
[n
] = INVALID_HANDLE_VALUE
;
249 // dtor closes the pipe descriptors
250 ~wxPipe() { Close(); }
256 #endif // wxUSE_STREAMS
258 // ============================================================================
260 // ============================================================================
264 // ----------------------------------------------------------------------------
265 // process termination detecting support
266 // ----------------------------------------------------------------------------
268 // thread function for the thread monitoring the process termination
269 static DWORD __stdcall
wxExecuteThread(void *arg
)
271 wxExecuteData
* const data
= (wxExecuteData
*)arg
;
273 if ( ::WaitForSingleObject(data
->hProcess
, INFINITE
) != WAIT_OBJECT_0
)
275 wxLogDebug(_T("Waiting for the process termination failed!"));
279 if ( !::GetExitCodeProcess(data
->hProcess
, &data
->dwExitCode
) )
281 wxLogLastError(wxT("GetExitCodeProcess"));
284 wxASSERT_MSG( data
->dwExitCode
!= STILL_ACTIVE
,
285 wxT("process should have terminated") );
287 // send a message indicating process termination to the window
288 ::SendMessage(data
->hWnd
, wxWM_PROC_TERMINATED
, 0, (LPARAM
)data
);
293 // window procedure of a hidden window which is created just to receive
294 // the notification message when a process exits
295 LRESULT APIENTRY _EXPORT
wxExecuteWindowCbk(HWND hWnd
, UINT message
,
296 WPARAM wParam
, LPARAM lParam
)
298 if ( message
== wxWM_PROC_TERMINATED
)
300 DestroyWindow(hWnd
); // we don't need it any more
302 wxExecuteData
* const data
= (wxExecuteData
*)lParam
;
305 data
->handler
->OnTerminate((int)data
->dwProcessId
,
306 (int)data
->dwExitCode
);
311 // we're executing synchronously, tell the waiting thread
312 // that the process finished
317 // asynchronous execution - we should do the clean up
325 return ::DefWindowProc(hWnd
, message
, wParam
, lParam
);
329 // ============================================================================
330 // implementation of IO redirection support classes
331 // ============================================================================
335 // ----------------------------------------------------------------------------
336 // wxPipeInputStreams
337 // ----------------------------------------------------------------------------
339 wxPipeInputStream::wxPipeInputStream(HANDLE hInput
)
344 wxPipeInputStream::~wxPipeInputStream()
346 if ( m_hInput
!= INVALID_HANDLE_VALUE
)
347 ::CloseHandle(m_hInput
);
350 bool wxPipeInputStream::CanRead() const
357 // function name is misleading, it works with anon pipes as well
358 DWORD rc
= ::PeekNamedPipe
361 NULL
, 0, // ptr to buffer and its size
362 NULL
, // [out] bytes read
363 &nAvailable
, // [out] bytes available
364 NULL
// [out] bytes left
369 if ( ::GetLastError() != ERROR_BROKEN_PIPE
)
372 wxLogLastError(_T("PeekNamedPipe"));
375 // don't try to continue reading from a pipe if an error occured or if
376 // it had been closed
377 ::CloseHandle(m_hInput
);
379 wxPipeInputStream
*self
= wxConstCast(this, wxPipeInputStream
);
381 self
->m_hInput
= INVALID_HANDLE_VALUE
;
382 self
->m_lasterror
= wxSTREAM_EOF
;
387 return nAvailable
!= 0;
390 size_t wxPipeInputStream::OnSysRead(void *buffer
, size_t len
)
394 m_lasterror
= wxSTREAM_EOF
;
400 if ( !::ReadFile(m_hInput
, buffer
, len
, &bytesRead
, NULL
) )
402 m_lasterror
= ::GetLastError() == ERROR_BROKEN_PIPE
404 : wxSTREAM_READ_ERROR
;
407 // bytesRead is set to 0, as desired, if an error occured
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_NO_ERROR
;
430 if ( !::WriteFile(m_hOutput
, buffer
, len
, &bytesWritten
, NULL
) )
432 m_lasterror
= ::GetLastError() == ERROR_BROKEN_PIPE
434 : wxSTREAM_WRITE_ERROR
;
440 #endif // wxUSE_STREAMS
444 // ============================================================================
445 // wxExecute functions family
446 // ============================================================================
450 // connect to the given server via DDE and ask it to execute the command
451 static bool wxExecuteDDE(const wxString
& ddeServer
,
452 const wxString
& ddeTopic
,
453 const wxString
& ddeCommand
)
458 wxConnectionBase
*conn
= client
.MakeConnection(_T(""),
465 else // connected to DDE server
467 // the added complication here is that although most
468 // programs use XTYP_EXECUTE for their DDE API, some
469 // important ones - like IE and other MS stuff - use
472 // so we try one first and then the other one if it
476 ok
= conn
->Execute(ddeCommand
);
481 // now try request - but show the errors
482 ok
= conn
->Request(ddeCommand
) != NULL
;
491 long wxExecute(const wxString
& cmd
, int flags
, wxProcess
*handler
)
493 wxCHECK_MSG( !!cmd
, 0, wxT("empty command in wxExecute") );
496 // for many reasons, the code below breaks down if it's called from another
497 // thread -- this could be fixed, but as Unix versions don't support this
498 // neither I don't want to waste time on this now
499 wxASSERT_MSG( wxThread::IsMain(),
500 _T("wxExecute() can be called only from the main thread") );
501 #endif // wxUSE_THREADS
506 // DDE hack: this is really not pretty, but we need to allow this for
507 // transparent handling of DDE servers in wxMimeTypesManager. Usually it
508 // returns the command which should be run to view/open/... a file of the
509 // given type. Sometimes, however, this command just launches the server
510 // and an additional DDE request must be made to really open the file. To
511 // keep all this well hidden from the application, we allow a special form
512 // of command: WX_DDE#<command>#DDE_SERVER#DDE_TOPIC#DDE_COMMAND in which
513 // case we execute just <command> and process the rest below
514 wxString ddeServer
, ddeTopic
, ddeCommand
;
515 static const size_t lenDdePrefix
= 7; // strlen("WX_DDE:")
516 if ( cmd
.Left(lenDdePrefix
) == _T("WX_DDE#") )
518 // speed up the concatenations below
519 ddeServer
.reserve(256);
520 ddeTopic
.reserve(256);
521 ddeCommand
.reserve(256);
523 const wxChar
*p
= cmd
.c_str() + 7;
524 while ( *p
&& *p
!= _T('#') )
536 wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
539 while ( *p
&& *p
!= _T('#') )
551 wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
554 while ( *p
&& *p
!= _T('#') )
566 wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
574 // if we want to just launch the program and not wait for its
575 // termination, try to execute DDE command right now, it can succeed if
576 // the process is already running - but as it fails if it's not
577 // running, suppress any errors it might generate
578 if ( !(flags
& wxEXEC_SYNC
) )
581 if ( wxExecuteDDE(ddeServer
, ddeTopic
, ddeCommand
) )
583 // a dummy PID - this is a hack, of course, but it's well worth
584 // it as we don't open a new server each time we're called
585 // which would be quite bad
597 #if defined(__WIN32__)
599 // the IO redirection is only supported with wxUSE_STREAMS
600 BOOL redirect
= FALSE
;
603 wxPipe pipeIn
, pipeOut
, pipeErr
;
605 // we'll save here the copy of pipeIn[Write]
606 HANDLE hpipeStdinWrite
= INVALID_HANDLE_VALUE
;
608 // open the pipes to which child process IO will be redirected if needed
609 if ( handler
&& handler
->IsRedirected() )
611 // create pipes for redirecting stdin, stdout and stderr
612 if ( !pipeIn
.Create() || !pipeOut
.Create() || !pipeErr
.Create() )
614 wxLogSysError(_("Failed to redirect the child process IO"));
616 // indicate failure: we need to return different error code
617 // depending on the sync flag
618 return flags
& wxEXEC_SYNC
? -1 : 0;
623 #endif // wxUSE_STREAMS
625 // create the process
633 si
.dwFlags
= STARTF_USESTDHANDLES
;
635 si
.hStdInput
= pipeIn
[wxPipe::Read
];
636 si
.hStdOutput
= pipeOut
[wxPipe::Write
];
637 si
.hStdError
= pipeErr
[wxPipe::Write
];
639 // when the std IO is redirected, we don't show the (console) process
640 // window by default, but this can be overridden by the caller by
641 // specifying wxEXEC_NOHIDE flag
642 if ( !(flags
& wxEXEC_NOHIDE
) )
644 si
.dwFlags
|= STARTF_USESHOWWINDOW
;
645 si
.wShowWindow
= SW_HIDE
;
648 // we must duplicate the handle to the write side of stdin pipe to make
649 // it non inheritable: indeed, we must close the writing end of pipeIn
650 // before launching the child process as otherwise this handle will be
651 // inherited by the child which will never close it and so the pipe
652 // will never be closed and the child will be left stuck in ReadFile()
653 HANDLE pipeInWrite
= pipeIn
.Detach(wxPipe::Write
);
654 if ( !::DuplicateHandle
656 ::GetCurrentProcess(),
658 ::GetCurrentProcess(),
660 0, // desired access: unused here
661 FALSE
, // not inherited
662 DUPLICATE_SAME_ACCESS
// same access as for src handle
665 wxLogLastError(_T("DuplicateHandle"));
668 ::CloseHandle(pipeInWrite
);
670 #endif // wxUSE_STREAMS
672 PROCESS_INFORMATION pi
;
673 DWORD dwFlags
= CREATE_DEFAULT_ERROR_MODE
| CREATE_SUSPENDED
;
675 bool ok
= ::CreateProcess
677 NULL
, // application name (use only cmd line)
679 command
.c_str(), // full command line
680 NULL
, // security attributes: defaults for both
681 NULL
, // the process and its main thread
682 redirect
, // inherit handles if we use pipes
683 dwFlags
, // process creation flags
684 NULL
, // environment (use the same)
685 NULL
, // current directory (use the same)
686 &si
, // startup info (unused here)
691 // we can close the pipe ends used by child anyhow
694 ::CloseHandle(pipeIn
.Detach(wxPipe::Read
));
695 ::CloseHandle(pipeOut
.Detach(wxPipe::Write
));
696 ::CloseHandle(pipeErr
.Detach(wxPipe::Write
));
698 #endif // wxUSE_STREAMS
703 // close the other handles too
706 ::CloseHandle(pipeOut
.Detach(wxPipe::Read
));
707 ::CloseHandle(pipeErr
.Detach(wxPipe::Read
));
709 #endif // wxUSE_STREAMS
711 wxLogSysError(_("Execution of command '%s' failed"), command
.c_str());
713 return flags
& wxEXEC_SYNC
? -1 : 0;
717 // the input buffer bufOut is connected to stdout, this is why it is
718 // called bufOut and not bufIn
719 wxStreamTempInputBuffer bufOut
,
724 // We can now initialize the wxStreams
726 outStream
= new wxPipeInputStream(pipeOut
.Detach(wxPipe::Read
));
728 errStream
= new wxPipeInputStream(pipeErr
.Detach(wxPipe::Read
));
730 inStream
= new wxPipeOutputStream(hpipeStdinWrite
);
732 handler
->SetPipeStreams(outStream
, inStream
, errStream
);
734 bufOut
.Init(outStream
);
735 bufErr
.Init(errStream
);
737 #endif // wxUSE_STREAMS
739 // register the class for the hidden window used for the notifications
740 if ( !gs_classForHiddenWindow
)
742 gs_classForHiddenWindow
= _T("wxHiddenWindow");
745 wxZeroMemory(wndclass
);
746 wndclass
.lpfnWndProc
= (WNDPROC
)wxExecuteWindowCbk
;
747 wndclass
.hInstance
= wxGetInstance();
748 wndclass
.lpszClassName
= gs_classForHiddenWindow
;
750 if ( !::RegisterClass(&wndclass
) )
752 wxLogLastError(wxT("RegisterClass(hidden window)"));
756 // create a hidden window to receive notification about process
758 HWND hwnd
= ::CreateWindow(gs_classForHiddenWindow
, NULL
,
761 (HMENU
)NULL
, wxGetInstance(), 0);
762 wxASSERT_MSG( hwnd
, wxT("can't create a hidden window for wxExecute") );
765 wxExecuteData
*data
= new wxExecuteData
;
766 data
->hProcess
= pi
.hProcess
;
767 data
->dwProcessId
= pi
.dwProcessId
;
769 data
->state
= (flags
& wxEXEC_SYNC
) != 0;
770 if ( flags
& wxEXEC_SYNC
)
772 // handler may be !NULL for capturing program output, but we don't use
773 // it wxExecuteData struct in this case
774 data
->handler
= NULL
;
778 // may be NULL or not
779 data
->handler
= handler
;
783 HANDLE hThread
= ::CreateThread(NULL
,
790 // resume process we created now - whether the thread creation succeeded or
792 if ( ::ResumeThread(pi
.hThread
) == (DWORD
)-1 )
794 // ignore it - what can we do?
795 wxLogLastError(wxT("ResumeThread in wxExecute"));
798 // close unneeded handle
799 if ( !::CloseHandle(pi
.hThread
) )
800 wxLogLastError(wxT("CloseHandle(hThread)"));
804 wxLogLastError(wxT("CreateThread in wxExecute"));
809 // the process still started up successfully...
810 return pi
.dwProcessId
;
813 ::CloseHandle(hThread
);
816 // second part of DDE hack: now establish the DDE conversation with the
817 // just launched process
818 if ( !ddeServer
.empty() )
822 // give the process the time to init itself
824 // we use a very big timeout hoping that WaitForInputIdle() will return
825 // much sooner, but not INFINITE just in case the process hangs
826 // completely - like this we will regain control sooner or later
827 switch ( ::WaitForInputIdle(pi
.hProcess
, 10000 /* 10 seconds */) )
830 wxFAIL_MSG( _T("unexpected WaitForInputIdle() return code") );
834 wxLogLastError(_T("WaitForInputIdle() in wxExecute"));
837 wxLogDebug(_T("Timeout too small in WaitForInputIdle"));
843 // ok, process ready to accept DDE requests
844 ok
= wxExecuteDDE(ddeServer
, ddeTopic
, ddeCommand
);
849 if ( !(flags
& wxEXEC_SYNC
) )
851 // clean up will be done when the process terminates
854 return pi
.dwProcessId
;
857 // disable all app windows while waiting for the child process to finish
861 We use a dirty hack here to disable all application windows (which we
862 must do because otherwise the calls to wxYield() could lead to some very
863 unexpected reentrancies in the users code) but to avoid losing
864 focus/activation entirely when the child process terminates which would
865 happen if we simply disabled everything using wxWindowDisabler. Indeed,
866 remember that Windows will never activate a disabled window and when the
867 last childs window is closed and Windows looks for a window to activate
868 all our windows are still disabled. There is no way to enable them in
869 time because we don't know when the childs windows are going to be
870 closed, so the solution we use here is to keep one special tiny frame
871 enabled all the time. Then when the child terminates it will get
872 activated and when we close it below -- after reenabling all the other
873 windows! -- the previously active window becomes activated again and
880 // first disable all existing windows
883 // then create an "invisible" frame: it has minimal size, is positioned
884 // (hopefully) outside the screen and doesn't appear on the taskbar
885 winActive
= new wxFrame
887 wxTheApp
->GetTopWindow(),
890 wxPoint(32600, 32600),
892 wxDEFAULT_FRAME_STYLE
| wxFRAME_NO_TASKBAR
897 // wait until the child process terminates
898 while ( data
->state
)
903 #endif // wxUSE_STREAMS
905 // don't eat 100% of the CPU -- ugly but anything else requires
906 // real async IO which we don't have for the moment
913 // dispatch the messages to the hidden window so that it could
914 // process the wxWM_PROC_TERMINATED notification
916 ::PeekMessage(&msg
, hwnd
, 0, 0, PM_REMOVE
);
923 // finally delete the dummy frame and, as wd has been already destroyed and
924 // the other windows reenabled, the activation is going to return to the
925 // window which had it before
926 winActive
->Destroy();
929 DWORD dwExitCode
= data
->dwExitCode
;
932 // return the exit code
935 long instanceID
= WinExec((LPCSTR
) WXSTRINGCAST command
, SW_SHOW
);
937 return flags
& wxEXEC_SYNC
? -1 : 0;
939 if ( flags
& wxEXEC_SYNC
)
945 running
= GetModuleUsage((HINSTANCE
)instanceID
);
953 long wxExecute(wxChar
**argv
, int flags
, wxProcess
*handler
)
966 return wxExecute(command
, flags
, handler
);