1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Various utilities
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
33 #include "wx/process.h"
36 #include "wx/msw/private.h"
42 #if !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__SALFORDC__)
51 #include <sys/unistd.h>
56 #if defined(__WIN32__) && !defined(__WXWINE__)
68 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
74 // this message is sent when the process we're waiting for terminates
75 #define wxWM_PROC_TERMINATED (WM_USER + 10000)
77 // structure describing the process we're being waiting for
84 if ( !::CloseHandle(hProcess
) )
86 wxLogLastError("CloseHandle(hProcess)");
91 HWND hWnd
; // window to send wxWM_PROC_TERMINATED to
92 HANDLE hProcess
; // handle of the process
93 DWORD dwProcessId
; // pid of the process
95 DWORD dwExitCode
; // the exit code of the process
96 bool state
; // set to FALSE when the process finishes
101 static DWORD
wxExecuteThread(wxExecuteData
*data
)
103 WaitForSingleObject(data
->hProcess
, INFINITE
);
106 if ( !GetExitCodeProcess(data
->hProcess
, &data
->dwExitCode
) )
108 wxLogLastError("GetExitCodeProcess");
111 wxASSERT_MSG( data
->dwExitCode
!= STILL_ACTIVE
,
112 T("process should have terminated") );
114 // send a message indicating process termination to the window
115 SendMessage(data
->hWnd
, wxWM_PROC_TERMINATED
, 0, (LPARAM
)data
);
120 // window procedure of a hidden window which is created just to receive
121 // the notification message when a process exits
122 LRESULT APIENTRY _EXPORT
wxExecuteWindowCbk(HWND hWnd
, UINT message
,
123 WPARAM wParam
, LPARAM lParam
)
125 if ( message
== wxWM_PROC_TERMINATED
)
127 DestroyWindow(hWnd
); // we don't need it any more
129 wxExecuteData
*data
= (wxExecuteData
*)lParam
;
132 data
->handler
->OnTerminate((int)data
->dwProcessId
,
133 (int)data
->dwExitCode
);
138 // we're executing synchronously, tell the waiting thread
139 // that the process finished
144 // asynchronous execution - we should do the clean up
153 extern wxChar wxPanelClassName
[];
155 long wxExecute(const wxString
& command
, bool sync
, wxProcess
*handler
)
157 wxCHECK_MSG( !!command
, 0, T("empty command in wxExecute") );
159 #if defined(__WIN32__) && !defined(__TWIN32__)
160 // the old code is disabled because we really need a process handle
161 // if we want to execute it asynchronously or even just get its
162 // return code and for this we must use CreateProcess() and not
165 // isolate command and arguments
166 wxString commandName
;
167 bool insideQuotes
= FALSE
;
169 for ( pc
= command
.c_str(); *pc
!= '\0'; pc
++ )
180 insideQuotes
= !insideQuotes
;
185 continue; // skip the next break
188 // only reached for space not inside quotes
192 wxString commandArgs
= pc
;
194 wxWindow
*winTop
= wxTheApp
->GetTopWindow();
195 HWND hwndTop
= (HWND
)(winTop
? winTop
->GetHWND() : 0);
199 result
= ShellExecute(hwndTop
,
200 (const wchar_t)"open",
201 (const wchar_t)commandName
,
202 (const wchar_t)commandArgs
,
206 result
= ShellExecute(hwndTop
, "open", commandName
,
207 commandArgs
, NULL
, SW_SHOWNORMAL
);
210 if ( ((long)result
) <= 32 )
211 wxLogSysError(_("Can't execute command '%s'"), command
.c_str());
215 // create the process
218 memset(&si
, 0, sizeof(si
));
220 ::ZeroMemory(&si
, sizeof(si
));
225 PROCESS_INFORMATION pi
;
227 if ( ::CreateProcess(
228 NULL
, // application name (use only cmd line)
229 (wxChar
*)command
.c_str(), // full command line
230 NULL
, // security attributes: defaults for both
231 NULL
, // the process and its main thread
232 FALSE
, // don't inherit handles
233 CREATE_DEFAULT_ERROR_MODE
, // flags
234 NULL
, // environment (use the same)
235 NULL
, // current directory (use the same)
236 &si
, // startup info (unused here)
240 wxLogSysError(_("Execution of command '%s' failed"), command
.c_str());
245 // close unneeded handle
246 if ( !::CloseHandle(pi
.hThread
) )
247 wxLogLastError("CloseHandle(hThread)");
249 // create a hidden window to receive notification about process
251 HWND hwnd
= ::CreateWindow(wxPanelClassName
, NULL
, 0, 0, 0, 0, 0, NULL
,
252 (HMENU
)NULL
, wxGetInstance(), 0);
253 wxASSERT_MSG( hwnd
, T("can't create a hidden window for wxExecute") );
255 FARPROC ExecuteWindowInstance
= MakeProcInstance((FARPROC
)wxExecuteWindowCbk
,
258 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
) ExecuteWindowInstance
);
261 wxExecuteData
*data
= new wxExecuteData
;
262 data
->hProcess
= pi
.hProcess
;
263 data
->dwProcessId
= pi
.dwProcessId
;
268 wxASSERT_MSG( !handler
, T("wxProcess param ignored for sync execution") );
270 data
->handler
= NULL
;
274 // may be NULL or not
275 data
->handler
= handler
;
279 HANDLE hThread
= ::CreateThread(NULL
,
281 (LPTHREAD_START_ROUTINE
)wxExecuteThread
,
288 wxLogLastError("CreateThread in wxExecute");
293 // the process still started up successfully...
294 return pi
.dwProcessId
;
299 // clean up will be done when the process terminates
302 return pi
.dwProcessId
;
305 // waiting until command executed
306 while ( data
->state
)
309 DWORD dwExitCode
= data
->dwExitCode
;
312 // return the exit code
316 long instanceID
= WinExec((LPCSTR
) WXSTRINGCAST command
, SW_SHOW
);
317 if (instanceID
< 32) return(0);
323 running
= GetModuleUsage((HINSTANCE
)instanceID
);
331 long wxExecute(char **argv
, bool sync
, wxProcess
*handler
)
335 while ( *argv
!= NULL
)
337 command
<< *argv
++ << ' ';
340 command
.RemoveLast();
342 return wxExecute(command
, sync
, handler
);
345 bool wxGetFullHostName(wxChar
*buf
, int maxSize
)
347 #if defined(__WIN32__) && !defined(__TWIN32__)
348 DWORD nSize
= maxSize
;
349 if ( !::GetComputerName(buf
, &nSize
) )
351 wxLogLastError("GetComputerName");
357 const char *default_host
= "noname";
358 static const char WX_SECTION
[] = "wxWindows";
359 static const char eHOSTNAME
[] = "HostName";
361 if ((sysname
= getenv("SYSTEM_NAME")) == NULL
) {
362 GetProfileString(WX_SECTION
, eHOSTNAME
, default_host
, buf
, maxSize
- 1);
364 strncpy(buf
, sysname
, maxSize
- 1);
368 wxLogLastError("GetComputerName");