OS.Execute() will not run composite commands

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By MRimmer

So I’m trying to run a command using OS.execute (CMD) which will write the output of a command to a file. i.e:

var commandString = str("g++ -g ", fileString, " -o ", execString, " 1> ", outString, " 2>&1")

OS.execute("CMD.exe", ["/C", commandString], true, output1)

However, when I try to do this I get the follow error from the CMD:

The system cannot find the path specified.

Despite the fact when commandString is printed to console and copied, g++ runs fine.

I went to the official documentation looking for answers and the 3rd code snippet they display:

OS.execute("CMD.exe", ["/C", "cd %TEMP% && dir"], true, output)

Returns this error from CMD:

The filename, directory name, or volume label syntax is incorrect.

Despite cd %TEMP% && dir working fine when I run it manually.

Am I doing something wrong or is something else going on here?

What exactly should the fully-constructed command look like if you were to type it in a command terminal (including any/all quotes and spaces)? Generally, I’d guess that some of the things you’ve included as part of the command string itself (like the redirects) should, instead, be included as additional elements in the arguments array passed to OS.execute.

jgodfrey | 2020-11-13 14:47

The command should look something like this, fully constructed:

g++ -g %USERDATAPATH%/code.cpp -o %USERDATAPATH%/code.exe 1> %USERDATAPATH%/output.txt 2>&1

%USERDATAPATH% being the user:// path, constructed using OS.get_user_data_dir()

While putting elements in arguments works when I don’t use 1> or 2>&1, when I do include them, it throws up this:

g++: error: 1>: Invalid argument
g++: error: 2>&1: Invalid argument

As they’re passed to g++ as arguments, when they’re supposed to be redirections.

MRimmer | 2020-11-13 15:46

Yeah, looking at the source, this just calls Win32 CreateProcessW() under the covers, and the arguments array is used to construct args for the called EXE - just as you noted.

So, I’m actually not sure how to do what you’re need here (or, if it’s even possible ATM).

As a potential work around… Maybe you could write your command string to a temporary batch file and call that via OS.execute()?

jgodfrey | 2020-11-13 19:38

I came to the same sort of conclusion. I appreciate you having a look around for me.

Batch files would provide a workaround, which I will probably use if I can’t find an alternative.

What I was trying to do essentially, was find a way to record the output of a command without halting execution of Godot, as blocking blocks all execution. Writing to a file and then getting that file’s contents every few seconds means I can get the output but also have no execution.

Is there any other way in engine to get the output of a command without halting Godot? I’m trying to make an IDE type thing, and as such I need the output of the compilers, with a tailing log.

MRimmer | 2020-11-13 20:27