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(__SALFORDC__) && !defined(__WXMICROWIN__)
57 #if defined(__GNUWIN32__) && !defined(__TWIN32__)
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") );
498 // DDE hack: this is really not pretty, but we need to allow this for
499 // transparent handling of DDE servers in wxMimeTypesManager. Usually it
500 // returns the command which should be run to view/open/... a file of the
501 // given type. Sometimes, however, this command just launches the server
502 // and an additional DDE request must be made to really open the file. To
503 // keep all this well hidden from the application, we allow a special form
504 // of command: WX_DDE#<command>#DDE_SERVER#DDE_TOPIC#DDE_COMMAND in which
505 // case we execute just <command> and process the rest below
506 wxString ddeServer
, ddeTopic
, ddeCommand
;
507 static const size_t lenDdePrefix
= 7; // strlen("WX_DDE:")
508 if ( cmd
.Left(lenDdePrefix
) == _T("WX_DDE#") )
510 // speed up the concatenations below
511 ddeServer
.reserve(256);
512 ddeTopic
.reserve(256);
513 ddeCommand
.reserve(256);
515 const wxChar
*p
= cmd
.c_str() + 7;
516 while ( *p
&& *p
!= _T('#') )
528 wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
531 while ( *p
&& *p
!= _T('#') )
543 wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
546 while ( *p
&& *p
!= _T('#') )
558 wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
566 // if we want to just launch the program and not wait for its
567 // termination, try to execute DDE command right now, it can succeed if
568 // the process is already running - but as it fails if it's not
569 // running, suppress any errors it might generate
570 if ( !(flags
& wxEXEC_SYNC
) )
573 if ( wxExecuteDDE(ddeServer
, ddeTopic
, ddeCommand
) )
575 // a dummy PID - this is a hack, of course, but it's well worth
576 // it as we don't open a new server each time we're called
577 // which would be quite bad
589 #if defined(__WIN32__) && !defined(__TWIN32__)
591 // the IO redirection is only supported with wxUSE_STREAMS
592 BOOL redirect
= FALSE
;
595 wxPipe pipeIn
, pipeOut
, pipeErr
;
597 // we'll save here the copy of pipeIn[Write]
598 HANDLE hpipeStdinWrite
= INVALID_HANDLE_VALUE
;
600 // open the pipes to which child process IO will be redirected if needed
601 if ( handler
&& handler
->IsRedirected() )
603 // create pipes for redirecting stdin, stdout and stderr
604 if ( !pipeIn
.Create() || !pipeOut
.Create() || !pipeErr
.Create() )
606 wxLogSysError(_("Failed to redirect the child process IO"));
608 // indicate failure: we need to return different error code
609 // depending on the sync flag
610 return flags
& wxEXEC_SYNC
? -1 : 0;
615 #endif // wxUSE_STREAMS
617 // create the process
625 si
.dwFlags
= STARTF_USESTDHANDLES
;
627 si
.hStdInput
= pipeIn
[wxPipe::Read
];
628 si
.hStdOutput
= pipeOut
[wxPipe::Write
];
629 si
.hStdError
= pipeErr
[wxPipe::Write
];
631 // when the std IO is redirected, we don't show the (console) process
632 // window by default, but this can be overridden by the caller by
633 // specifying wxEXEC_NOHIDE flag
634 if ( !(flags
& wxEXEC_NOHIDE
) )
636 si
.dwFlags
|= STARTF_USESHOWWINDOW
;
637 si
.wShowWindow
= SW_HIDE
;
640 // we must duplicate the handle to the write side of stdin pipe to make
641 // it non inheritable: indeed, we must close the writing end of pipeIn
642 // before launching the child process as otherwise this handle will be
643 // inherited by the child which will never close it and so the pipe
644 // will never be closed and the child will be left stuck in ReadFile()
645 HANDLE pipeInWrite
= pipeIn
.Detach(wxPipe::Write
);
646 if ( !::DuplicateHandle
648 ::GetCurrentProcess(),
650 ::GetCurrentProcess(),
652 0, // desired access: unused here
653 FALSE
, // not inherited
654 DUPLICATE_SAME_ACCESS
// same access as for src handle
657 wxLogLastError(_T("DuplicateHandle"));
660 ::CloseHandle(pipeInWrite
);
662 #endif // wxUSE_STREAMS
664 PROCESS_INFORMATION pi
;
665 DWORD dwFlags
= CREATE_DEFAULT_ERROR_MODE
| CREATE_SUSPENDED
;
667 bool ok
= ::CreateProcess
669 NULL
, // application name (use only cmd line)
671 command
.c_str(), // full command line
672 NULL
, // security attributes: defaults for both
673 NULL
, // the process and its main thread
674 redirect
, // inherit handles if we use pipes
675 dwFlags
, // process creation flags
676 NULL
, // environment (use the same)
677 NULL
, // current directory (use the same)
678 &si
, // startup info (unused here)
683 // we can close the pipe ends used by child anyhow
686 ::CloseHandle(pipeIn
.Detach(wxPipe::Read
));
687 ::CloseHandle(pipeOut
.Detach(wxPipe::Write
));
688 ::CloseHandle(pipeErr
.Detach(wxPipe::Write
));
690 #endif // wxUSE_STREAMS
695 // close the other handles too
698 ::CloseHandle(pipeOut
.Detach(wxPipe::Read
));
699 ::CloseHandle(pipeErr
.Detach(wxPipe::Read
));
701 #endif // wxUSE_STREAMS
703 wxLogSysError(_("Execution of command '%s' failed"), command
.c_str());
705 return flags
& wxEXEC_SYNC
? -1 : 0;
709 // the input buffer bufOut is connected to stdout, this is why it is
710 // called bufOut and not bufIn
711 wxStreamTempInputBuffer bufOut
,
716 // We can now initialize the wxStreams
718 outStream
= new wxPipeInputStream(pipeOut
.Detach(wxPipe::Read
));
720 errStream
= new wxPipeInputStream(pipeErr
.Detach(wxPipe::Read
));
722 inStream
= new wxPipeOutputStream(hpipeStdinWrite
);
724 handler
->SetPipeStreams(outStream
, inStream
, errStream
);
726 bufOut
.Init(outStream
);
727 bufErr
.Init(errStream
);
729 #endif // wxUSE_STREAMS
731 // register the class for the hidden window used for the notifications
732 if ( !gs_classForHiddenWindow
)
734 gs_classForHiddenWindow
= _T("wxHiddenWindow");
737 wxZeroMemory(wndclass
);
738 wndclass
.lpfnWndProc
= (WNDPROC
)wxExecuteWindowCbk
;
739 wndclass
.hInstance
= wxGetInstance();
740 wndclass
.lpszClassName
= gs_classForHiddenWindow
;
742 if ( !::RegisterClass(&wndclass
) )
744 wxLogLastError(wxT("RegisterClass(hidden window)"));
748 // create a hidden window to receive notification about process
750 HWND hwnd
= ::CreateWindow(gs_classForHiddenWindow
, NULL
,
753 (HMENU
)NULL
, wxGetInstance(), 0);
754 wxASSERT_MSG( hwnd
, wxT("can't create a hidden window for wxExecute") );
757 wxExecuteData
*data
= new wxExecuteData
;
758 data
->hProcess
= pi
.hProcess
;
759 data
->dwProcessId
= pi
.dwProcessId
;
761 data
->state
= (flags
& wxEXEC_SYNC
) != 0;
762 if ( flags
& wxEXEC_SYNC
)
764 // handler may be !NULL for capturing program output, but we don't use
765 // it wxExecuteData struct in this case
766 data
->handler
= NULL
;
770 // may be NULL or not
771 data
->handler
= handler
;
775 HANDLE hThread
= ::CreateThread(NULL
,
782 // resume process we created now - whether the thread creation succeeded or
784 if ( ::ResumeThread(pi
.hThread
) == (DWORD
)-1 )
786 // ignore it - what can we do?
787 wxLogLastError(wxT("ResumeThread in wxExecute"));
790 // close unneeded handle
791 if ( !::CloseHandle(pi
.hThread
) )
792 wxLogLastError(wxT("CloseHandle(hThread)"));
796 wxLogLastError(wxT("CreateThread in wxExecute"));
801 // the process still started up successfully...
802 return pi
.dwProcessId
;
805 ::CloseHandle(hThread
);
808 // second part of DDE hack: now establish the DDE conversation with the
809 // just launched process
810 if ( !ddeServer
.empty() )
814 // give the process the time to init itself
816 // we use a very big timeout hoping that WaitForInputIdle() will return
817 // much sooner, but not INFINITE just in case the process hangs
818 // completely - like this we will regain control sooner or later
819 switch ( ::WaitForInputIdle(pi
.hProcess
, 10000 /* 10 seconds */) )
822 wxFAIL_MSG( _T("unexpected WaitForInputIdle() return code") );
826 wxLogLastError(_T("WaitForInputIdle() in wxExecute"));
829 wxLogDebug(_T("Timeout too small in WaitForInputIdle"));
835 // ok, process ready to accept DDE requests
836 ok
= wxExecuteDDE(ddeServer
, ddeTopic
, ddeCommand
);
841 if ( !(flags
& wxEXEC_SYNC
) )
843 // clean up will be done when the process terminates
846 return pi
.dwProcessId
;
849 // disable all app windows while waiting for the child process to finish
853 We use a dirty hack here to disable all application windows (which we
854 must do because otherwise the calls to wxYield() could lead to some very
855 unexpected reentrancies in the users code) but to avoid losing
856 focus/activation entirely when the child process terminates which would
857 happen if we simply disabled everything using wxWindowDisabler. Indeed,
858 remember that Windows will never activate a disabled window and when the
859 last childs window is closed and Windows looks for a window to activate
860 all our windows are still disabled. There is no way to enable them in
861 time because we don't know when the childs windows are going to be
862 closed, so the solution we use here is to keep one special tiny frame
863 enabled all the time. Then when the child terminates it will get
864 activated and when we close it below -- after reenabling all the other
865 windows! -- the previously active window becomes activated again and
872 // first disable all existing windows
875 // then create an "invisible" frame: it has minimal size, is positioned
876 // (hopefully) outside the screen and doesn't appear on the taskbar
877 winActive
= new wxFrame
879 wxTheApp
->GetTopWindow(),
882 wxPoint(32600, 32600),
884 wxDEFAULT_FRAME_STYLE
| wxFRAME_NO_TASKBAR
889 // wait until the child process terminates
890 while ( data
->state
)
895 #endif // wxUSE_STREAMS
897 // don't eat 100% of the CPU -- ugly but anything else requires
898 // real async IO which we don't have for the moment
905 // dispatch the messages to the hidden window so that it could
906 // process the wxWM_PROC_TERMINATED notification
908 ::PeekMessage(&msg
, hwnd
, 0, 0, PM_REMOVE
);
915 // finally delete the dummy frame and, as wd has been already destroyed and
916 // the other windows reenabled, the activation is going to return to the
917 // window which had it before
918 winActive
->Destroy();
921 DWORD dwExitCode
= data
->dwExitCode
;
924 // return the exit code
927 long instanceID
= WinExec((LPCSTR
) WXSTRINGCAST command
, SW_SHOW
);
929 return flags
& wxEXEC_SYNC
? -1 : 0;
931 if ( flags
& wxEXEC_SYNC
)
937 running
= GetModuleUsage((HINSTANCE
)instanceID
);
945 long wxExecute(wxChar
**argv
, int flags
, wxProcess
*handler
)
958 return wxExecute(command
, flags
, handler
);