Split OS::execute into two methods
1. execute(): Executes a command and returns the results. 2. create_process(): Creates a new process and returns the new process' id.
This commit is contained in:
@ -410,24 +410,23 @@ String OS_Windows::_quote_command_line_argument(const String &p_text) const {
|
||||
return p_text;
|
||||
}
|
||||
|
||||
Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
|
||||
Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
|
||||
String path = p_path.replace("/", "\\");
|
||||
String command = _quote_command_line_argument(path);
|
||||
for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
|
||||
command += " " + _quote_command_line_argument(E->get());
|
||||
}
|
||||
|
||||
if (p_blocking && r_pipe) {
|
||||
String argss = _quote_command_line_argument(path);
|
||||
for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
|
||||
argss += " " + _quote_command_line_argument(E->get());
|
||||
}
|
||||
|
||||
if (r_pipe) {
|
||||
if (read_stderr) {
|
||||
argss += " 2>&1"; // Read stderr too
|
||||
command += " 2>&1"; // Include stderr
|
||||
}
|
||||
// Note: _wpopen is calling command as "cmd.exe /c argss", instead of executing it directly, add extra quotes around full command, to prevent it from stripping quotes in the command.
|
||||
argss = _quote_command_line_argument(argss);
|
||||
|
||||
FILE *f = _wpopen((LPCWSTR)(argss.utf16().get_data()), L"r");
|
||||
ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
|
||||
// Add extra quotes around the full command, to prevent it from stripping quotes in the command,
|
||||
// because _wpopen calls command as "cmd.exe /c command", instead of executing it directly
|
||||
command = _quote_command_line_argument(command);
|
||||
|
||||
FILE *f = _wpopen((LPCWSTR)(command.utf16().get_data()), L"r");
|
||||
ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot create pipe from command: " + command);
|
||||
char buf[65535];
|
||||
while (fgets(buf, 65535, f)) {
|
||||
if (p_pipe_mutex) {
|
||||
@ -438,49 +437,57 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
|
||||
p_pipe_mutex->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
int rv = _pclose(f);
|
||||
|
||||
if (r_exitcode) {
|
||||
*r_exitcode = rv;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
String cmdline = _quote_command_line_argument(path);
|
||||
const List<String>::Element *I = p_arguments.front();
|
||||
while (I) {
|
||||
cmdline += " " + _quote_command_line_argument(I->get());
|
||||
I = I->next();
|
||||
}
|
||||
|
||||
ProcessInfo pi;
|
||||
ZeroMemory(&pi.si, sizeof(pi.si));
|
||||
pi.si.cb = sizeof(pi.si);
|
||||
ZeroMemory(&pi.pi, sizeof(pi.pi));
|
||||
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
|
||||
|
||||
Char16String modstr = cmdline.utf16(); // Windows wants to change this no idea why.
|
||||
int ret = CreateProcessW(nullptr, (LPWSTR)(modstr.ptrw()), nullptr, nullptr, 0, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi);
|
||||
ERR_FAIL_COND_V(ret == 0, ERR_CANT_FORK);
|
||||
int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi);
|
||||
ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command);
|
||||
|
||||
if (p_blocking) {
|
||||
WaitForSingleObject(pi.pi.hProcess, INFINITE);
|
||||
if (r_exitcode) {
|
||||
DWORD ret2;
|
||||
GetExitCodeProcess(pi.pi.hProcess, &ret2);
|
||||
*r_exitcode = ret2;
|
||||
}
|
||||
|
||||
CloseHandle(pi.pi.hProcess);
|
||||
CloseHandle(pi.pi.hThread);
|
||||
} else {
|
||||
ProcessID pid = pi.pi.dwProcessId;
|
||||
if (r_child_id) {
|
||||
*r_child_id = pid;
|
||||
}
|
||||
process_map->insert(pid, pi);
|
||||
WaitForSingleObject(pi.pi.hProcess, INFINITE);
|
||||
if (r_exitcode) {
|
||||
DWORD ret2;
|
||||
GetExitCodeProcess(pi.pi.hProcess, &ret2);
|
||||
*r_exitcode = ret2;
|
||||
}
|
||||
CloseHandle(pi.pi.hProcess);
|
||||
CloseHandle(pi.pi.hThread);
|
||||
|
||||
return OK;
|
||||
};
|
||||
|
||||
Error OS_Windows::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id) {
|
||||
String path = p_path.replace("/", "\\");
|
||||
String command = _quote_command_line_argument(path);
|
||||
for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
|
||||
command += " " + _quote_command_line_argument(E->get());
|
||||
}
|
||||
|
||||
ProcessInfo pi;
|
||||
ZeroMemory(&pi.si, sizeof(pi.si));
|
||||
pi.si.cb = sizeof(pi.si);
|
||||
ZeroMemory(&pi.pi, sizeof(pi.pi));
|
||||
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
|
||||
|
||||
int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi);
|
||||
ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command);
|
||||
|
||||
ProcessID pid = pi.pi.dwProcessId;
|
||||
if (r_child_id) {
|
||||
*r_child_id = pid;
|
||||
}
|
||||
process_map->insert(pid, pi);
|
||||
|
||||
return OK;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user