added and documented (and using in the sample) wxProcess::CloseOutput()

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_2_BRANCH@7497 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2000-05-26 15:18:07 +00:00
parent bbc7adbd09
commit 5fff5f8a27
4 changed files with 105 additions and 10 deletions

View File

@@ -62,6 +62,15 @@ macro in the event table of the parent to handle it) with the given {\it id}.
Destroys the wxProcess object. Destroys the wxProcess object.
\membersection{wxProcess::CloseOutput}\label{wxprocesscloseoutput}
\func{void}{CloseOutput}{\void}
Closes the output stream (the one connected to the stdin of the child
process). This function can be used to indicate to the child process that
there is no more data to be read - usually, a filter program will only
terminate when the input stream is closed.
\membersection{wxProcess::Detach}\label{wxprocessdetach} \membersection{wxProcess::Detach}\label{wxprocessdetach}
\func{void}{Detach}{\void} \func{void}{Detach}{\void}

View File

@@ -81,6 +81,9 @@ public:
wxInputStream *GetErrorStream() const { return m_errorStream; } wxInputStream *GetErrorStream() const { return m_errorStream; }
wxOutputStream *GetOutputStream() const { return m_outputStream; } wxOutputStream *GetOutputStream() const { return m_outputStream; }
// close the output stream indicating that nothing more will be written
void CloseOutput() { delete m_outputStream; m_outputStream = NULL; }
// implementation only (for wxExecute) // implementation only (for wxExecute)
void SetPipeStreams(wxInputStream *inStream, void SetPipeStreams(wxInputStream *inStream,
wxOutputStream *outStream, wxOutputStream *outStream,

View File

@@ -86,6 +86,8 @@ public:
void OnAsyncExec(wxCommandEvent& event); void OnAsyncExec(wxCommandEvent& event);
void OnShell(wxCommandEvent& event); void OnShell(wxCommandEvent& event);
void OnExecWithRedirect(wxCommandEvent& event); void OnExecWithRedirect(wxCommandEvent& event);
void OnExecWithPipe(wxCommandEvent& event);
void OnDDEExec(wxCommandEvent& event); void OnDDEExec(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event); void OnAbout(wxCommandEvent& event);
@@ -144,7 +146,23 @@ public:
virtual void OnTerminate(int pid, int status); virtual void OnTerminate(int pid, int status);
bool HasInput(); virtual bool HasInput();
};
// A version of MyPipedProcess which also sends input to the stdin of the
// child process
class MyPipedProcess2 : public MyPipedProcess
{
public:
MyPipedProcess2(MyFrame *parent, const wxString& cmd, const wxString& input)
: MyPipedProcess(parent, cmd), m_input(input)
{
}
virtual bool HasInput();
private:
wxString m_input;
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -162,6 +180,7 @@ enum
Exec_Shell, Exec_Shell,
Exec_DDEExec, Exec_DDEExec,
Exec_Redirect, Exec_Redirect,
Exec_Pipe,
Exec_About = 300 Exec_About = 300
}; };
@@ -182,6 +201,8 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(Exec_AsyncExec, MyFrame::OnAsyncExec) EVT_MENU(Exec_AsyncExec, MyFrame::OnAsyncExec)
EVT_MENU(Exec_Shell, MyFrame::OnShell) EVT_MENU(Exec_Shell, MyFrame::OnShell)
EVT_MENU(Exec_Redirect, MyFrame::OnExecWithRedirect) EVT_MENU(Exec_Redirect, MyFrame::OnExecWithRedirect)
EVT_MENU(Exec_Pipe, MyFrame::OnExecWithPipe)
EVT_MENU(Exec_DDEExec, MyFrame::OnDDEExec) EVT_MENU(Exec_DDEExec, MyFrame::OnDDEExec)
EVT_MENU(Exec_About, MyFrame::OnAbout) EVT_MENU(Exec_About, MyFrame::OnAbout)
@@ -249,8 +270,11 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
_T("Launch a program and return immediately")); _T("Launch a program and return immediately"));
execMenu->Append(Exec_Shell, _T("Execute &shell command...\tCtrl-S"), execMenu->Append(Exec_Shell, _T("Execute &shell command...\tCtrl-S"),
_T("Launch a shell and execute a command in it")); _T("Launch a shell and execute a command in it"));
execMenu->AppendSeparator();
execMenu->Append(Exec_Redirect, _T("Capture command &output...\tCtrl-O"), execMenu->Append(Exec_Redirect, _T("Capture command &output...\tCtrl-O"),
_T("Launch a program and capture its output")); _T("Launch a program and capture its output"));
execMenu->Append(Exec_Pipe, _T("&Pipe through command...\tCtrl-P"),
_T("Pipe a string through a filter"));
#ifdef __WINDOWS__ #ifdef __WINDOWS__
execMenu->AppendSeparator(); execMenu->AppendSeparator();
@@ -386,7 +410,7 @@ void MyFrame::OnExecWithRedirect(wxCommandEvent& WXUNUSED(event))
if ( sync ) if ( sync )
{ {
wxArrayString output, errors; wxArrayString output, errors;
int code = wxExecute(cmd, output); int code = wxExecute(cmd, output, errors);
wxLogStatus(_T("command '%s' terminated with exit code %d."), wxLogStatus(_T("command '%s' terminated with exit code %d."),
cmd.c_str(), code); cmd.c_str(), code);
@@ -414,6 +438,42 @@ void MyFrame::OnExecWithRedirect(wxCommandEvent& WXUNUSED(event))
m_cmdLast = cmd; m_cmdLast = cmd;
} }
void MyFrame::OnExecWithPipe(wxCommandEvent& WXUNUSED(event))
{
if ( !m_cmdLast )
m_cmdLast = _T("tr [a-z] [A-Z]");
wxString cmd = wxGetTextFromUser(_T("Enter the command: "),
DIALOG_TITLE,
m_cmdLast);
if ( !cmd )
return;
wxString input = wxGetTextFromUser(_T("Enter the string to send to it: "),
DIALOG_TITLE);
if ( !input )
return;
// always execute the filter asynchronously
MyPipedProcess2 *process = new MyPipedProcess2(this, cmd, input);
int pid = wxExecute(cmd, FALSE /* async */, process);
if ( pid )
{
wxLogStatus(_T("Process %ld (%s) launched."), pid, cmd.c_str());
m_running.Add(process);
}
else
{
wxLogError(_T("Execution of '%s' failed."), cmd.c_str());
delete process;
}
m_cmdLast = cmd;
}
void MyFrame::OnDDEExec(wxCommandEvent& WXUNUSED(event)) void MyFrame::OnDDEExec(wxCommandEvent& WXUNUSED(event))
{ {
#ifdef __WINDOWS__ #ifdef __WINDOWS__
@@ -556,3 +616,24 @@ void MyPipedProcess::OnTerminate(int pid, int status)
MyProcess::OnTerminate(pid, status); MyProcess::OnTerminate(pid, status);
} }
// ----------------------------------------------------------------------------
// MyPipedProcess2
// ----------------------------------------------------------------------------
bool MyPipedProcess2::HasInput()
{
if ( !!m_input )
{
wxTextOutputStream os(*GetOutputStream());
os.WriteString(m_input);
CloseOutput();
m_input.clear();
// call us once again - may be we'll have output
return TRUE;
}
return MyPipedProcess::HasInput();
}

View File

@@ -397,7 +397,11 @@ long wxExecute(wxChar **argv,
bool sync, bool sync,
wxProcess *process) wxProcess *process)
{ {
wxCHECK_MSG( *argv, 0, wxT("can't exec empty command") ); // for the sync execution, we return -1 to indicate failure, but for async
// cse we return 0 which is never a valid PID
long errorRetCode = sync ? -1 : 0;
wxCHECK_MSG( *argv, errorRetCode, wxT("can't exec empty command") );
#if wxUSE_UNICODE #if wxUSE_UNICODE
int mb_argc = 0; int mb_argc = 0;
@@ -432,7 +436,7 @@ long wxExecute(wxChar **argv,
ARGS_CLEANUP; ARGS_CLEANUP;
return 0; return errorRetCode;
} }
#endif // wxUSE_GUI #endif // wxUSE_GUI
@@ -460,7 +464,7 @@ long wxExecute(wxChar **argv,
ARGS_CLEANUP; ARGS_CLEANUP;
return 0; return errorRetCode;
} }
} }
@@ -488,7 +492,7 @@ long wxExecute(wxChar **argv,
ARGS_CLEANUP; ARGS_CLEANUP;
return 0; return errorRetCode;
} }
else if ( pid == 0 ) // we're in child else if ( pid == 0 ) // we're in child
{ {
@@ -612,11 +616,9 @@ long wxExecute(wxChar **argv,
return exitcode; return exitcode;
#endif // wxUSE_GUI #endif // wxUSE_GUI
} }
}
return 0;
#undef ARGS_CLEANUP #undef ARGS_CLEANUP
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// file and directory functions // file and directory functions