#include "wx/process.h"
#include "wx/thread.h"
#include "wx/apptrait.h"
+#include "wx/evtloop.h"
#include "wx/vector.h"
protected:
HANDLE m_hInput;
- DECLARE_NO_COPY_CLASS(wxPipeInputStream)
+ wxDECLARE_NO_COPY_CLASS(wxPipeInputStream);
};
class wxPipeOutputStream: public wxOutputStream
protected:
HANDLE m_hOutput;
- DECLARE_NO_COPY_CLASS(wxPipeOutputStream)
+ wxDECLARE_NO_COPY_CLASS(wxPipeOutputStream);
};
// define this to let wxexec.cpp know that we know what we're doing
bool wxPipeInputStream::CanRead() const
{
+ // we can read if there's something in the put back buffer
+ // even pipe is closed
+ if ( m_wbacksize > m_wbackcur )
+ return true;
+
+ wxPipeInputStream * const self = wxConstCast(this, wxPipeInputStream);
+
if ( !IsOpened() )
+ {
+ // set back to mark Eof as it may have been unset by Ungetch()
+ self->m_lasterror = wxSTREAM_EOF;
return false;
+ }
DWORD nAvailable;
// it had been closed
::CloseHandle(m_hInput);
- wxPipeInputStream *self = wxConstCast(this, wxPipeInputStream);
-
self->m_hInput = INVALID_HANDLE_VALUE;
self->m_lasterror = wxSTREAM_EOF;
{
// may be NULL or not
data->handler = handler;
+
+ if (handler)
+ handler->SetPid(pi.dwProcessId);
}
DWORD tid;
while ( data->state )
{
#if wxUSE_STREAMS && !defined(__WXWINCE__)
- bufOut.Update();
- bufErr.Update();
+ if ( !bufOut.Update() && !bufErr.Update() )
#endif // wxUSE_STREAMS
+ {
+ // don't eat 100% of the CPU -- ugly but anything else requires
+ // real async IO which we don't have for the moment
+ ::Sleep(50);
+ }
- // don't eat 100% of the CPU -- ugly but anything else requires
- // real async IO which we don't have for the moment
- ::Sleep(50);
+ // we must always process messages for our hidden window or we'd never
+ // get wxWM_PROC_TERMINATED and so this loop would never terminate
+ MSG msg;
+ ::PeekMessage(&msg, data->hWnd, 0, 0, PM_REMOVE);
- // we must process messages or we'd never get wxWM_PROC_TERMINATED
- traits->AlwaysYield();
+ // we may also need to process messages for all the other application
+ // windows
+ if ( !(flags & wxEXEC_NOEVENTS) )
+ {
+ wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
+ if ( loop )
+ loop->Yield();
+ }
}
if ( !(flags & wxEXEC_NODISABLE) )
return dwExitCode;
}
-long wxExecute(wxChar **argv, int flags, wxProcess *handler)
+template <typename CharType>
+long wxExecuteImpl(CharType **argv, int flags, wxProcess *handler)
{
wxString command;
+ command.reserve(1024);
+ wxString arg;
for ( ;; )
{
- command += *argv++;
+ arg = *argv++;
+
+ bool quote;
+ if ( arg.empty() )
+ {
+ // we need to quote empty arguments, otherwise they'd just
+ // disappear
+ quote = true;
+ }
+ else // non-empty
+ {
+ // escape any quotes present in the string to avoid interfering
+ // with the command line parsing in the child process
+ arg.Replace("\"", "\\\"", true /* replace all */);
+
+ // and quote any arguments containing the spaces to prevent them from
+ // being broken down
+ quote = arg.find_first_of(" \t") != wxString::npos;
+ }
+
+ if ( quote )
+ command += '\"' + arg + '\"';
+ else
+ command += arg;
+
if ( !*argv )
break;
- command += _T(' ');
+ command += ' ';
}
return wxExecute(command, flags, handler);
}
+
+long wxExecute(char **argv, int flags, wxProcess *handler)
+{
+ return wxExecuteImpl(argv, flags, handler);
+}
+
+#if wxUSE_UNICODE
+
+long wxExecute(wchar_t **argv, int flags, wxProcess *handler)
+{
+ return wxExecuteImpl(argv, flags, handler);
+}
+
+#endif // wxUSE_UNICODE