-3

I have tried to use this example to run an external program using CreateProcessW() in C++, however, when I use multiple arguments this code seems to not work.

In my case, I pass the following path:

std::string pathToExe = "C:\\Users\\Aitor - ST\\Documents\\QtProjects\\ErgoEvalPlatform\\ErgonomicEvaluationPlatform\\FACTS\\xsim-runner.exe"

and the following arguments:

std::string arguments = "--model=facts_input.xml --output_xml=something.xml"

These parameters work from cmd, but they seem to not give any output (an xml should appear in the same folder) when I use them from C++.

Is there something I might be missing?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
txapulin
  • 3
  • 1
  • 2
  • 1
    Replace those `\ ` with `\\ ` cause a single `\ ` represents a character escape sequence. Also don't use hardcoded path – Asesh Jul 15 '19 at 09:08
  • I assume your problem is hard to reproduce, since it could be caused by the internals of `xsim-runner.exe` which we are not familiar with. I recommend, writing a 5 LOC .exe, which just prints out the flags i.e. arguments it had been called with. If you see a difference, we know better where to start. – Superlokkus Jul 15 '19 at 09:09
  • Hi, sure I don't know why it didn't paste properly, but I used \\ in the path:std::string pathToExe = "C:\\Users\\Aitor - ST\\Documents\\QtProjects\\ErgoEvalPlatform\\ErgonomicEvaluationPlatform\\FACTS\\xsim-runner.exe"; Also, I hard coded it just to use it as an example. – txapulin Jul 15 '19 at 09:30
  • Also, the xsim-runner program works as expected when I use the following bat file, so there should be no difference. Bat file: cd C:\Users\Aitor - ST\Documents\QtProjects\ErgoEvalPlatform\ErgonomicEvaluationPlatform\FACTS xsim-runner.exe --model=facts_input.xml --output_xml=something.xml – txapulin Jul 15 '19 at 09:32
  • Check [this](https://stackoverflow.com/questions/49652210/kill-my-process-if-the-other-process-is-killed/49652550#49652550) – Victor Gubin Jul 15 '19 at 11:43
  • 1
    "*Is there something I might be missing?*" - yes, showing your actual code that is trying to call `CreateProcessW()`. Please provide a [mcve] showing YOUR code, don't just provide a link to SOMEONE ELSE'S code. – Remy Lebeau Jul 15 '19 at 15:33
  • Maybe I didn't explain myself good enough, but I literally copied the class of the example and gave the two strings I wrote as arguments. I did nothing else so that I did not feel the need to add a minimal reproducible example since the minimal reproducible example is as it is in the link. – txapulin Jul 16 '19 at 11:16

3 Answers3

0

There's two potential problems I can infer from the code you're showing.

Space before the arguments

Depending on how you're concatenating the arguments string to the executable string, you may miss a space before the arguments. Without the code, it's impossible to tell, but try changing the arguments string like this :

std::string arguments = " --model=facts_input.xml --output_xml=something.xml;"

Current directory

CreateProcess spawns a child process that inherits the current directory from it's parent process. The XML files you specify on the arguments use relative paths.

Try specifying the full path of the XML files you're passing in the arguments, something like this :

std::string arguments = " --model=\"C:\\Users\\Aitor - ST\\Documents\\QtProjects\\ErgoEvalPlatform\\ErgonomicEvaluationPlatform\\FACTS\\facts_input.xml\" --output_xml=\"C:\\Users\\Aitor - ST\\Documents\\QtProjects\\ErgoEvalPlatform\\ErgonomicEvaluationPlatform\\FACTS\\something.xml\"";
MartinVeronneau
  • 1,296
  • 7
  • 24
0

The following is an example for showing "How to run an exe with multiple arguments with CreateProcessW in C++". You can check if it helps.

The launcher application (a console app):

#include <iostream>
#include <windows.h>

int main()
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi; // The function returns this
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    CONST wchar_t* commandLine = TEXT("arg1 arg2 arg3");

    // Start the child process.
    if (!CreateProcessW(
        L"D:\\Win32-Cases\\TestTargetApp\\Debug\\TestTargetApp.exe",      // app path
        (LPWSTR)commandLine,     // Command line 
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        FALSE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory
        &si,            // Pointer to STARTUPINFO structure
        &pi)           // Pointer to PROCESS_INFORMATION structure
        )
    {
        printf("CreateProcess failed (%d).\n", GetLastError());
        throw std::exception("Could not create child process");
    }
    else
    {
        std::cout << "[          ] Successfully launched child process" << std::endl;
    }
}

The target application (another console app) that will be launched:

#include <iostream>
#include <windows.h>

int main(int argc, char *argv[])
{
    if (argc > 0)
    {
        for (int index = 0; index < argc; index++)
        {
            std::cout << argv[index] << std::endl;
        }
    }

    return 1;
}

enter image description here

Rita Han
  • 9,574
  • 1
  • 11
  • 24
  • Very helpful answer, I have found out that the problem comes from how the other exe files process the arguments. Thanks to your example I have been working around it and I will solve it soon. Thanks! – txapulin Jul 16 '19 at 11:30
  • You write in the comment for 2nd `CreateProcess` argument _"needs to include app path as first argument"_, but you don't even do it yourself. – zett42 Jul 18 '19 at 19:48
  • @zett42 Thanks for pointing out. That needed only when the `lpApplicationName` parameter is NULL. – Rita Han Jul 19 '19 at 08:58
  • If you control the code of the app to be started, this may be true. For reliably launching 3rd-party apps with arguments, it is necessary that the first argument is always the application path. When evaluating arguments, many (most?) apps will skip the first argument as they expect it to be the application path. – zett42 Jul 19 '19 at 09:57
-1

You have to pass the complete command line in the arguments as under:

std::string arguments = "C:\\Users\\Aitor-ST\\Documents\\QtProjects\\ErgoEvalPlatform\\ErgonomicEvaluationPlatform\\FACTS\\xsim-runner.exe --model=facts_input.xml --output_xml=something.xml"

The second parameter of CreateProcessW requires complete command line and not just arguments. It passes this to the process and if the target process is a C program taking agrs, then as usual the first parameter will be module name and others that follow will be args.

Hope this helps

ritesh sangani
  • 280
  • 3
  • 8
  • Hi, in the example class it already concatenates both strings to build a string with path + arguments (https://stackoverflow.com/a/46831649/11785474) you can see it here: std::wstring input = app_w + L" " + arg_w; wchar_t* arg_concat = const_cast( input.c_str() ); Thank you :) – txapulin Jul 15 '19 at 10:38
  • @txapulin then there could be some issue with file write permissions. Please run the code under administrator to rule out this issue – ritesh sangani Jul 15 '19 at 10:44
  • I would say that it seems to run xsim-runner.exe, however, it does not provide the proper arguments for it to generate any file. I have tested the code with another exe file that does not require any argument and it opens the program. – txapulin Jul 15 '19 at 11:35
  • Your command-line is wrong as you didn't quote the executable path, which contains whitespace. – zett42 Jul 15 '19 at 19:17