Sei sulla pagina 1di 8

Using wxProcess and wxInputStream (and wxOutputStream) - wxWidge... https://forums.wxwidgets.org/viewtopic.php?

t=20651

wxWidgets Discussion Forum


Official forum for the wxWidgets Cross-Platform
GUI Toolkit

Quick links FAQ Register Login

Board index ‹ wxWidgets Programming Forums ‹ C++ Development

Using wxProcess and wxInputStream (and wxOutputStream)  [SOLVED]


Post Reply 10 posts • Page 1 of 1

Using wxProcess and wxInputStream DanL


Experienced Solver
(and wxOutputStream)
by DanL » Tue Aug 19, 2008 9:15 pm
Posts: 63
Joined: Wed Feb 14, 2007
Hi all,
7:32 pm

I'm a bit of a newb when it comes to C++ and I thought this would be simple to do
after looking at the exec example, but I still seem to be having problems. I am using
the structure provided by wxDev-C++.

Essentially, I have a frame-based program. I want to open a process once a button is


clicked on the frame, and capture the stdout and stderr from that process (it would
also be nice to be able to send to stdin).

Currently my code looks something like this:

CmdFrm.h
CODE: SELECT ALL

class CmdFrm : public wxFrame


{
private:
DECLARE_EVENT_TABLE();

public:
CmdFrm(wxWindow *parent, wxWindowID id = 1, const wxString &title
= wxT("Cmd"), const wxPoint& pos = wxDefaultPosition, const wxSize&
size = wxDefaultSize, long style = Cmd_STYLE);
virtual ~CmdFrm();
void WxButton1Click(wxCommandEvent& event);
void WxButton2Click(wxCommandEvent& event);

private:
//Do not add custom control declarations between
//GUI Control Declaration Start and GUI Control Declaration End.
//wxDev-C++ will remove them. Add custom code after the block.
////GUI Control Declaration Start
wxButton *WxButton3;
wxButton *WxButton2;
wxTextCtrl *WxMemo3;
wxTextCtrl *WxEdit1;

1 of 8 18/12/2018, 07:56
Using wxProcess and wxInputStream (and wxOutputStream) - wxWidge... https://forums.wxwidgets.org/viewtopic.php?t=20651

wxTextCtrl *WxMemo2;
wxTextCtrl *WxMemo1;
wxButton *WxButton1;
wxPanel *WxPanel1;
////GUI Control Declaration End
wxProcess *MyProcess;
....

CmdFrm.cpp
CODE: SELECT ALL

void CmdFrm::CreateGUIControls()
{
//Do not add custom code between
//GUI Items Creation Start and GUI Items Creation End
...

////GUI Items Creation End


MyProcess = new wxProcess(wxPROCESS_REDIRECT);
}
....
void CmdFrm::WxButton1Click(wxCommandEvent& event)
{
if ( WxEdit1->IsEmpty() )
return;

The problem is, while the process seems to launch OK, it is not able to connect to
stdout. The same command I run works fine with the exec example.

Any ideas?

  [SOLVED] DavidHart
Site Admin
by DavidHart » Wed Aug 20, 2008 10:24 am

Hi,
Posts: 3779
Joined: Thu Jan 12, 2006
One obvious problem with your code is that you don't seem actually to use wxExecute. 6:23 pm
AFAIK wxProcess isn't standalone, it's a helper for wxExecute. Location: IoW, UK

The 'exec' sample is rather overloaded. If you'd like to see my exec-derived code, have
a look at http://fourpane.svn.sourceforge.net/vie ... Dialog.cpp (which does what
you want without the confusion of too many extras).

(it would also be nice to be able to send to stdin).


There's similar code that does that too at http://fourpane.svn.sourceforge.net/vie ...
/Tools.cpp. This time there is a lot of extra confusing code, but look at
MyPipedProcess::SendOutput and some of the TerminalEm functions.

Regards,

David

by zeb » Wed Aug 20, 2008 1:27 pm zeb


In need of some credit

2 of 8 18/12/2018, 07:56
Using wxProcess and wxInputStream (and wxOutputStream) - wxWidge... https://forums.wxwidgets.org/viewtopic.php?t=20651

Hi,

Posts: 5
I wrote this minimal class which will output the stdout of the process. It runs the Joined: Wed Aug 20, 2008
process asynchronously, however, it blocks the window until the process is finished 1:22 pm

(still useful to follow a process being executed but having to wait for its completion).
It is certainly not very advanced (and probably it is better to use David's example) but
it is much easier to understand than the exec sample.

CODE: SELECT ALL

/*
* DisplayProcess.h
*
* Created on: 20-Aug-2008
* Author: zeb
*/

#ifndef DISPLAYPROCESS_H_
#define DISPLAYPROCESS_H_

#include "wx/wx.h"
#include "wx/process.h"
#include "wx/txtstrm.h"

CODE: SELECT ALL

/*
* DisplayProcess.cpp
*
* Created on: 20-Aug-2008
* Author: zeb
*/

#include "DisplayProcess.h"

DisplayProcess::DisplayProcess(wxTextCtrl* ctrl) : tctrl(ctrl)


{
}

void DisplayProcess::Execute(const wxString& command)


{
if (!tctrl)
{
return;
}

wxProcess *process = new wxProcess(wxPROCESS_REDIRECT);


long pid = wxExecute(command, wxEXEC_ASYNC, process);
process->Redirect();

if (process)
{
wxString log;
wxInputStream *msg = process->GetInputStream();

wxTextInputStream tStream(*msg);
while(!msg->Eof())
{
log = tStream.ReadLine();
tctrl->AppendText(log+wxT("\n"));

3 of 8 18/12/2018, 07:56
Using wxProcess and wxInputStream (and wxOutputStream) - wxWidge... https://forums.wxwidgets.org/viewtopic.php?t=20651

}
tctrl->AppendText(wxT("Finished!\n"));
} else {
tctrl->AppendText(wxT("FAIL: Command" + command + " could not be
run!\n"));
}
}

In main, it is used as simply as that:

CODE: SELECT ALL

wxTextCtrl* m_textCtrl2 = new wxTextCtrl();

//....

DisplayProcess* dp = new DisplayProcess(m_textCtrl2);


command = cygwinpath + wxString("rsync.exe -h");
dp->Execute(command);
command = cygwinpath + wxString("ls.exe");
dp->Execute(command);

m_textCtrl2->AppendText(wxT("All Finished!\n"));

delete dp;

Last edited by zeb on Thu Aug 21, 2008 8:36 am, edited 1 time in total.

by DanL » Wed Aug 20, 2008 4:08 pm DanL


Experienced Solver
Thanks guys. I changed
Posts: 63
CODE: SELECT ALL Joined: Wed Feb 14, 2007
7:32 pm
MyProcess->Open(WxEdit1->GetValue());

to
CODE: SELECT ALL

long pid = wxExecute(WxEdit1->GetValue(), wxEXEC_ASYNC, MyProcess);

and it works. Thanks for the insight on simpler ways to do this! Digging through the
exec sample is a bit tedious.

by zeb » Wed Aug 20, 2008 4:17 pm zeb


In need of some credit

DanL wrote:
Thanks guys. Posts: 5
Joined: Wed Aug 20, 2008
1:22 pm

You're welcome. As you could see in my example, I also start to experiment with this,
since I need to redirect cygwin commands to my GUI.
May I ask, in which part of your code do you append the stream text in your WxMemo1

4 of 8 18/12/2018, 07:56
Using wxProcess and wxInputStream (and wxOutputStream) - wxWidge... https://forums.wxwidgets.org/viewtopic.php?t=20651

? Could you give me an example of how you do this ?

Thanks in advance.

by DanL » Wed Aug 20, 2008 4:35 pm DanL


Experienced Solver
I use the same method as in the piped example in the exec sample. I currently just
have a button and in the event handler connect to the process and update the
Posts: 63
WxMemo. Does that make sense? Joined: Wed Feb 14, 2007
7:32 pm

I'm currently working on getting it to poll every so often with a timer.

by zeb » Thu Aug 21, 2008 8:22 am zeb


In need of some credit

DanL wrote:
I use the same method as in the piped example in the exec sample. I currently just Posts: 5
Joined: Wed Aug 20, 2008
have a button and in the event handler connect to the process and update the 1:22 pm
WxMemo. Does that make sense?

I'm currently working on getting it to poll every so often with a timer.

Alright, I'll have a deeper look to exec, thanks. Instead of a timer, you could have a
look at David "fourpan" example, who uses the fact that the process is idle to check
for the input and display it (it is still a timer though).

Last edited by zeb on Thu Aug 21, 2008 8:33 am, edited 1 time in total.

by zeb » Thu Aug 21, 2008 8:31 am zeb


In need of some credit

DavidHart wrote:
The 'exec' sample is rather overloaded. If you'd like to see my exec-derived code, Posts: 5
Joined: Wed Aug 20, 2008
have a look at http://fourpane.svn.sourceforge.net/vie ... Dialog.cpp (which does 1:22 pm
what you want without the confusion of too many extras).

David: I have some trouble trying to reuse the classes in ExecuteInDialog.cpp. Where
are AUTOCLOSE_FAILTIMEOUT and AUTOCLOSE_TIMEOUT defined ? I deactivated the
autoclose part to compile. Also I have instanciated a CommandDisplay but cannot
show it. This is an extract from main:

CODE: SELECT ALL

#include "wx/wxprec.h"
#include "ExecuteInDialog.h"
// [....]
bool MyApp::OnInit()
{
wxString cmd = "C:/cygwin/bin/ls.exe";
CommandDisplay *cd = new CommandDisplay();

5 of 8 18/12/2018, 07:56
Using wxProcess and wxInputStream (and wxOutputStream) - wxWidge... https://forums.wxwidgets.org/viewtopic.php?t=20651

cd->Show(); // nothing shows


SetTopWindow(cd);
cd->Init(cmd); //segfaults
}

What am I doing wrong?

by DavidHart » Thu Aug 21, 2008 11:49 am DavidHart


Site Admin
Hi Zeb,

Sorry, but (as you'll have noticed) the code is part of a larger project, and wasn't Posts: 3779
Joined: Thu Jan 12, 2006
really designed for easy reuse (yes I know, I should have). 6:23 pm
Location: IoW, UK
These were in a different header file:
CODE: SELECT ALL

size_t AUTOCLOSE_TIMEOUT = 2000; // How long to hold open an autoclose


dialog
size_t AUTOCLOSE_FAILTIMEOUT = 5000; // Ditto if the process failed

The way it should be used is:


CODE: SELECT ALL

CommandDisplay OutputDlg;
wxXmlResource::Get()->LoadDialog(&OutputDlg, NULL, wxT("OutputDlg"));
OutputDlg.Init( command );
OutputDlg.ShowModal();

if ( !OutputDlg.exitstatus )...

and an XRC file contains:


CODE: SELECT ALL

<object class="wxDialog" name="OutputDlg">


<title/>
<centered>1</centered>
<object class="wxBoxSizer">
<orient>wxVERTICAL</orient>
<object class="sizeritem">
<object class="wxBoxSizer">
<orient>wxHORIZONTAL</orient>
<object class="sizeritem">
<object class="wxTextCtrl" name="text">
<size>500,200</size>
<style>wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER</style>
</object>
<option>1</option>
<flag>wxEXPAND|wxALIGN_CENTRE</flag>
</object>
</object>
<option>1</option>
<flag>wxALL|wxEXPAND</flag>
<border>15</border>
</object>
<object class="sizeritem">
<object class="wxBoxSizer">

6 of 8 18/12/2018, 07:56
Using wxProcess and wxInputStream (and wxOutputStream) - wxWidge... https://forums.wxwidgets.org/viewtopic.php?t=20651

<orient>wxHORIZONTAL</orient>
<object class="sizeritem">
<object class="wxBoxSizer">
<orient>wxVERTICAL</orient>
<object class="sizeritem">
<object class="wxCheckBox" name="Autoclose">
<label>Auto-Close</label>
<checked>1</checked>
<tooltip>If checked, the dialog will automatically
close 2 seconds after the last entry is made</tooltip>
</object>
</object>
</object>
<option>1</option>

However if you aren't keen on XRC, you can make it yourself by putting a textctrl into
a dialog, so it looks like:

ATTACHMENTS

OutputDlg.jpg (10.87 KiB) Viewed 3042 times

by zeb » Thu Aug 21, 2008 12:24 pm zeb


In need of some credit

DavidHart wrote:
Hi Zeb, Posts: 5
Joined: Wed Aug 20, 2008
1:22 pm
Sorry, but (as you'll have noticed) the code is part of a larger project, and wasn't
really designed for easy reuse (yes I know, I should have).

Many thanks for this. I should be able to reuse XRC since I use (and learn)
wxFormBuilder which is particularly convenient. I am looking forward to try this.

Display posts from previous: All posts Sort by Post time Ascending Go

Post Reply 10 posts • Page 1 of 1

Return to “C++ Development”


Jump to

7 of 8 18/12/2018, 07:56
Using wxProcess and wxInputStream (and wxOutputStream) - wxWidge... https://forums.wxwidgets.org/viewtopic.php?t=20651

WHO IS ONLINE
Users browsing this forum: No registered users and 26 guests

Board index Contact us The team Delete all board cookies • All times are UTC

Powered by phpBB® Forum Software © phpBB Limited

8 of 8 18/12/2018, 07:56

Potrebbero piacerti anche