#if !defined(__GNUWIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
#include <direct.h>
-#ifndef __MWERKS__
#include <dos.h>
#endif
-#endif
#if defined(__GNUWIN32__)
#include <sys/unistd.h>
#include "wx/dde.h" // for WX_DDE hack in wxExecute
#endif // wxUSE_IPC
-// implemented in utils.cpp
-extern "C" WXDLLIMPEXP_BASE HWND
-wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc);
+#include "wx/msw/private/hiddenwin.h"
// ----------------------------------------------------------------------------
// constants
#endif // wxUSE_IPC
-long wxExecute(const wxString& cmd, int flags, wxProcess *handler)
+long wxExecute(const wxString& cmd, int flags, wxProcess *handler,
+ const wxExecuteEnv *env)
{
wxCHECK_MSG( !cmd.empty(), 0, wxT("empty command in wxExecute") );
si.hStdOutput = pipeOut[wxPipe::Write];
si.hStdError = pipeErr[wxPipe::Write];
- // when the std IO is redirected, we don't show the (console) process
- // window by default, but this can be overridden by the caller by
- // specifying wxEXEC_NOHIDE flag
- if ( !(flags & wxEXEC_NOHIDE) )
- {
- si.dwFlags |= STARTF_USESHOWWINDOW;
- si.wShowWindow = SW_HIDE;
- }
-
// we must duplicate the handle to the write side of stdin pipe to make
// it non inheritable: indeed, we must close the writing end of pipeIn
// before launching the child process as otherwise this handle will be
}
#endif // wxUSE_STREAMS
+ // The default logic for showing the console is to show it only if the IO
+ // is not redirected however wxEXEC_{SHOW,HIDE}_CONSOLE flags can be
+ // explicitly specified to change it.
+ if ( (flags & wxEXEC_HIDE_CONSOLE) ||
+ (redirect && !(flags & wxEXEC_SHOW_CONSOLE)) )
+ {
+ si.dwFlags |= STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_HIDE;
+ }
+
+
PROCESS_INFORMATION pi;
DWORD dwFlags = CREATE_SUSPENDED;
#ifndef __WXWINCE__
+ if ( (flags & wxEXEC_MAKE_GROUP_LEADER) &&
+ (wxGetOsVersion() == wxOS_WINDOWS_NT) )
+ dwFlags |= CREATE_NEW_PROCESS_GROUP;
+
dwFlags |= CREATE_DEFAULT_ERROR_MODE ;
#else
// we are assuming commands without spaces for now
wxString arguments = command.AfterFirst(wxT(' '));
#endif
+ wxWxCharBuffer envBuffer;
+ bool useCwd = false;
+ if ( env )
+ {
+ useCwd = !env->cwd.empty();
+
+ // Translate environment variable map into NUL-terminated list of
+ // NUL-terminated strings.
+ if ( !env->env.empty() )
+ {
+#if wxUSE_UNICODE
+ // Environment variables can contain non-ASCII characters. We could
+ // check for it and not use this flag if everything is really ASCII
+ // only but there doesn't seem to be any reason to do it so just
+ // assume Unicode by default.
+ dwFlags |= CREATE_UNICODE_ENVIRONMENT;
+#endif // wxUSE_UNICODE
+
+ wxEnvVariableHashMap::const_iterator it;
+
+ size_t envSz = 1; // ending '\0'
+ for ( it = env->env.begin(); it != env->env.end(); ++it )
+ {
+ // Add size of env variable name and value, and '=' char and
+ // ending '\0'
+ envSz += it->first.length() + it->second.length() + 2;
+ }
+
+ envBuffer.extend(envSz);
+
+ wxChar *p = envBuffer.data();
+ for ( it = env->env.begin(); it != env->env.end(); ++it )
+ {
+ const wxString line = it->first + wxS("=") + it->second;
+
+ // Include the trailing NUL which will always terminate the
+ // buffer returned by t_str().
+ const size_t len = line.length() + 1;
+
+ wxTmemcpy(p, line.t_str(), len);
+
+ p += len;
+ }
+
+ // And another NUL to terminate the list of NUL-terminated strings.
+ *p = 0;
+ }
+ }
+
bool ok = ::CreateProcess
(
// WinCE requires appname to be non null
NULL, // the process and its main thread
redirect, // inherit handles if we use pipes
dwFlags, // process creation flags
- NULL, // environment (use the same)
- NULL, // current directory (use the same)
+ envBuffer.data(), // environment (may be NULL which is fine)
+ useCwd // initial working directory
+ ? const_cast<wxChar *>(env->cwd.wx_str())
+ : NULL, // (or use the same)
&si, // startup info (unused here)
&pi // process info
) != 0;
wxFAIL_MSG( wxT("unexpected WaitForInputIdle() return code") );
// fall through
- case -1:
+ case WAIT_FAILED:
wxLogLastError(wxT("WaitForInputIdle() in wxExecute"));
case WAIT_TIMEOUT:
}
template <typename CharType>
-long wxExecuteImpl(CharType **argv, int flags, wxProcess *handler)
+long wxExecuteImpl(CharType **argv, int flags, wxProcess *handler,
+ const wxExecuteEnv *env)
{
wxString command;
command.reserve(1024);
command += ' ';
}
- return wxExecute(command, flags, handler);
+ return wxExecute(command, flags, handler, env);
}
-long wxExecute(char **argv, int flags, wxProcess *handler)
+long wxExecute(char **argv, int flags, wxProcess *handler,
+ const wxExecuteEnv *env)
{
- return wxExecuteImpl(argv, flags, handler);
+ return wxExecuteImpl(argv, flags, handler, env);
}
#if wxUSE_UNICODE
-long wxExecute(wchar_t **argv, int flags, wxProcess *handler)
+long wxExecute(wchar_t **argv, int flags, wxProcess *handler,
+ const wxExecuteEnv *env)
{
- return wxExecuteImpl(argv, flags, handler);
+ return wxExecuteImpl(argv, flags, handler, env);
}
#endif // wxUSE_UNICODE