current preferred method of executing async sub-processes Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
User avatar
bsenftner
Experienced Solver
Experienced Solver
Posts: 79
Joined: Thu May 26, 2016 9:19 pm

current preferred method of executing async sub-processes

Post by bsenftner » Thu Aug 31, 2017 12:42 am

Seems like this should be easy with wxExecute() and/or wxProcess(), but that does not seem to be the case...

I have a enterprise software product with a new data exporting facility. One of the exporting features is an ability to use middleware executables in command lines and execute them to complete an export. The idea being our export system generates data in arbitrary text formats, and for those organizations who need their exported data in proprietary binary formats, the ability to export text command lines to an external executable is the method for generating these externally controlled binary data blobs. (Yes, we realize this could be a security exploit. This feature is wrapped up with multiple security checks.)

I have been trying WxExecute() and wxProcess() (as well as platform specific variations for over a day) and so far I have zilch results. Sometimes my virus software (Malwarebytes) quarantines the executable at launch, but most often it runs without error, but generates no output from the launched program. (Yes, I am attempting these launches from the main thread.)

In my test logic, my test command lines typically contain IO redirection, something like this:

Code: Select all

c:\MachineId.exe > c:\ExportComm\bsjnk.txt
I have read in forum comments that wxExecute() is only intended for executable files, and does not work for system commands or command lines with pipes or command lines with IO redirection or background suspension.

Is it correct to say the logic will need to look at the command line, and if any shell commands, piping, or IO redirection is taking place, the logic needs to call wxShell()? (Interesting, my test use of wxShell() with the above line generates an assert() inside wWidgets.)

Likewise, it is correct to say the logic will need to look at the command line, and if it passed the above checks, but I see background suspension (the & character at the end) then that & character needs to be striped off? (Because i'm running these async anyway?)

I'm seeing recent forum posts saying wExecute() works, but I've not got it to work once yet... Below are some attempts.
(BTW: compiling on Win10, using Visual Studio 2013, i7 with 32 gigs RAM (if that matters))

Code: Select all

		  // event.GetString() contains the cmd line delivered here from another thread

		  // generates no output, and no error return value:
			msg = event.GetString(); 
			cx_int ret = wxExecute( msg, wxEXEC_ASYNC | wxEXEC_HIDE_CONSOLE );
			if (ret == 0)
			{
			  msg = wxString::Format("Export Connector Exec: failure to execute external program."); 
				ReportLog(msg);
			} /**/

		  /* this triggers an assert() inside wShell():
			msg = wxString::Format("c:\\windows\\sysWOW64\\cmd.exe /c start %s &", event.GetString());
			cx_int ret = wxShell( msg );
			if (ret != 0)
			{
			  msg = wxString::Format("Export Connector Exec: failure to execute external program."); 
				ReportLog(msg);
			} /**/

			/* generates no output, and no error return value:
			msg = wxString::Format("c:\\windows\\sysWOW64\\cmd.exe /C /D /F:ON start %s", event.GetString()); 
			cx_int ret = wxExecute( msg, wxEXEC_ASYNC | wxEXEC_HIDE_CONSOLE );
			if (ret == 0)
			{
			  msg = wxString::Format("Export Connector Exec: failure to execute external program."); 
				ReportLog(msg);
			} /**/

iwbnwif
Super wx Problem Solver
Super wx Problem Solver
Posts: 274
Joined: Tue Mar 19, 2013 8:52 pm

Re: current preferred method of executing async sub-processes

Post by iwbnwif » Thu Aug 31, 2017 12:47 pm

The following works for me on Windows 10 using the latest development version of wxWidgets from GitHub.

Code: Select all

    wxShell("echo. 2> test.docx");
    wxExecute("C:\\Program Files (x86)\\Microsoft Office\\root\\Office16\\WINWORD.EXE /t test.docx", wxEXEC_ASYNC);
You might like to try these and see if you still get the assert.
msg = wxString::Format("c:\\windows\\sysWOW64\\cmd.exe /c start %s &", event.GetString());
Sorry if I have misunderstood, but why do you want to create another command shell inside the wxShell?

Finally, I think you have a parameter missing from your start command. The first parameter is for the name of the terminal window, the second is for the program to run.

This also works, but I am not sure it has much point!

Code: Select all

    wxShell("start \"Word in a terminal\" \"C:\\Program Files (x86)\\Microsoft Office\\root\\Office16\\WINWORD.EXE\"");
wxWidgets 3.1.2, MinGW64 8.1.0, g++ 8.1.0, Ubuntu 19.04, Windows 10, CodeLite + wxCrafter
Some people, when confronted with a GUI problem, think "I know, I'll use Eclipse RCP". Now they have two problems.

User avatar
bsenftner
Experienced Solver
Experienced Solver
Posts: 79
Joined: Thu May 26, 2016 9:19 pm

Re: current preferred method of executing async sub-processes

Post by bsenftner » Sat Sep 02, 2017 1:40 pm

Thanks, you're working example got mine working. I'd been trying variations, and that wxShell launching cmd.exe was an extreme attempt to see if that was needed. The code I posted with commented out examples was abbreviated from more trials.

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2293
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Re: current preferred method of executing async sub-processes

Post by evstevemd » Sat Sep 02, 2017 5:18 pm

bsenftner wrote: I have been trying WxExecute() and wxProcess() (as well as platform specific variations for over a day) and so far I have zilch results. Sometimes my virus software (Malwarebytes) quarantines the executable at launch, but most often it runs without error, but generates no output from the launched program. (Yes, I am attempting these launches from the main thread.)
How do you actually do it? I suspect MB quarantines your app due to the behavior of the exe behavior and might have nothing to do with wxExecute itself.

Posting minimal code will help understand your problem better

bsenftner wrote: In my test logic, my test command lines typically contain IO redirection, something like this:

Code: Select all

c:\MachineId.exe > c:\ExportComm\bsjnk.txt
Though am not sure, isn't the name itself suspicious? It looks like common virii name. As your exe trying to write to file system with suspicious name, the guess goes, MB quarantines it.

bsenftner wrote: I have read in forum comments that wxExecute() is only intended for executable files, and does not work for system commands or command lines with pipes or command lines with IO redirection or background suspension.
Wrong. I use wxExecute for both system commands and calling exe's. Only thing is, you must wrap your commands around shell (sh or cmd) something similar to how CodeLite does it

Code: Select all

void WrapInShell(wxString &cmd)
{
    wxString command;
#ifdef __WXMSW__
    wxChar *shell = wxGetenv(wxT("COMSPEC"));
    if(!shell)
        shell = (wxChar *)wxT("CMD.EXE");
    command << shell << wxT(" /C ");
#if 0
    command << "\"" << cmd << "\"";
#else
    if(cmd.StartsWith("\"") && !cmd.EndsWith("\""))
    {
        command << "\"" << cmd << "\"";
    }
    else
    {
        command << cmd;
    }
#endif

    cmd = command;
#else
    command << wxT("/bin/sh -c '");
    // escape any single quoutes
    cmd.Replace("'", "\\'");
    command << cmd << wxT("'");
    cmd = command;
#endif
}
Then you can easily use it like

Code: Select all

wxString command = "/path/to/your/exe arg1 arg2";
WrapInShell(command);
//call wxExecute with command
//.....
bsenftner wrote:Is it correct to say the logic will need to look at the command line, and if any shell commands, piping, or IO redirection is taking place, the logic needs to call wxShell()?
wxShell is blocking call so your app will freeze until task is finished/terminated

Check this thread for more details

HTH,
Stefano
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

Post Reply