PIProcess windows works

This commit is contained in:
2025-08-13 21:36:13 +03:00
parent 3625afa783
commit d6a0ae6106
2 changed files with 50 additions and 22 deletions

View File

@@ -23,6 +23,7 @@
# include "piincludes_p.h" # include "piincludes_p.h"
# include "piliterals_bytes.h" # include "piliterals_bytes.h"
# include "piprocess.h" # include "piprocess.h"
# include "pitranslator.h"
# ifndef WINDOWS # ifndef WINDOWS
# include <csignal> # include <csignal>
# include <sys/wait.h> # include <sys/wait.h>
@@ -89,13 +90,12 @@ using PipeHandleType = int;
# endif # endif
# ifdef WINDOWS # ifdef WINDOWS
const char * convertWindowsCmd(PIStringList sl) { PIString convertWindowsCmd(PIStringList sl) {
for (int i = 0; i < sl.size_s(); ++i) { if (sl.isNotEmpty()) {
sl[i].push_front('"'); sl[0].replaceAll('/', '\\');
sl[i].push_back('"'); sl[0].quote();
} }
PIString s = sl.join(' '); return sl.join(' ');
return s.data();
} }
# else # else
char * const * convertToCharArrays(const PIStringList & sl) { char * const * convertToCharArrays(const PIStringList & sl) {
@@ -144,7 +144,7 @@ PRIVATE_DEFINITION_START(PIProcess)
SECURITY_ATTRIBUTES saAttr; SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE; saAttr.bInheritHandle = TRUE;
satrueAttr.lpSecurityDescriptor = NULL; saAttr.lpSecurityDescriptor = NULL;
if (!CreatePipe(&(pipes[pt][PipeRead]), &(pipes[pt][PipeWrite]), &saAttr, 0)) return false; if (!CreatePipe(&(pipes[pt][PipeRead]), &(pipes[pt][PipeWrite]), &saAttr, 0)) return false;
return true; return true;
# else # else
@@ -167,6 +167,11 @@ PRIVATE_DEFINITION_START(PIProcess)
} }
} }
} }
# ifdef WINDOWS
if (grab[StdIn]) SetHandleInformation(pipes[StdIn][PipeWrite], HANDLE_FLAG_INHERIT, 0);
if (grab[StdOut]) SetHandleInformation(pipes[StdOut][PipeRead], HANDLE_FLAG_INHERIT, 0);
if (grab[StdErr]) SetHandleInformation(pipes[StdErr][PipeRead], HANDLE_FLAG_INHERIT, 0);
# endif
return true; return true;
} }
@@ -178,7 +183,7 @@ PRIVATE_DEFINITION_START(PIProcess)
void closePipe(PipeHandleType & hpipe) { void closePipe(PipeHandleType & hpipe) {
# ifdef WINDOWS # ifdef WINDOWS
if (hpipe] != 0) { if (hpipe != 0) {
CloseHandle(hpipe); CloseHandle(hpipe);
hpipe = 0; hpipe = 0;
} }
@@ -205,12 +210,24 @@ PRIVATE_DEFINITION_START(PIProcess)
size_t offset = 0; size_t offset = 0;
while (1) { while (1) {
# ifdef WINDOWS # ifdef WINDOWS
BOOL ok = ReadFile(pipes[pipe_type][PipeRead], read_buffer.data(offset), read_buffer.size() - offset, &bytes_read, NULL); DWORD available = 0;
BOOL ok = PeekNamedPipe(pipes[pipe_type][PipeRead], nullptr, 0, nullptr, &available, nullptr);
// piCout << "ReadFile" << available;
if (available == 0) {
read_buffer.resize(offset);
break;
}
ok = ReadFile(pipes[pipe_type][PipeRead],
read_buffer.data(offset),
piMini(available, read_buffer.size() - offset),
&bytes_read,
nullptr);
// piCout << "ReadFile" << ok;
if (!ok) bytes_read = 0; if (!ok) bytes_read = 0;
# else # else
bytes_read = ::read(pipes[pipe_type][PipeRead], read_buffer.data(offset), read_buffer.size() - offset); bytes_read = ::read(pipes[pipe_type][PipeRead], read_buffer.data(offset), read_buffer.size() - offset);
# endif # endif
piCout << "readed" << bytes_read; // piCout << "readed" << bytes_read;
if (bytes_read > 0) { if (bytes_read > 0) {
offset += bytes_read; offset += bytes_read;
read_buffer.resize(offset + read_buffer_size); read_buffer.resize(offset + read_buffer_size);
@@ -219,7 +236,7 @@ PRIVATE_DEFINITION_START(PIProcess)
break; break;
} }
} }
piCout << "readPipe" << read_buffer.toHex(); // piCout << "readPipe" << PIString::fromConsole(read_buffer);
return read_buffer; return read_buffer;
} }
@@ -232,7 +249,7 @@ PRIVATE_DEFINITION_START(PIProcess)
# else # else
sz = ::write(pipes[StdIn][PipeWrite], data.data(), data.size()); sz = ::write(pipes[StdIn][PipeWrite], data.data(), data.size());
# endif # endif
piCout << "writePipe" << sz; // piCout << "writePipe" << sz;
return sz == data.size_s(); return sz == data.size_s();
} }
@@ -274,23 +291,26 @@ void PIProcess::startProc(bool detached) {
if (!PRIVATE->createPipes()) return; if (!PRIVATE->createPipes()) return;
# ifdef WINDOWS # ifdef WINDOWS
STARTUPINFOA si; STARTUPINFOA si;
piZeroMemory(pi); piZeroMemory(si);
si.cb = sizeof(STARTUPINFOA); si.cb = sizeof(STARTUPINFOA);
if (PRIVATE->grab[StdIn]) si.hStdInput = PRIVATE->pipes[StdIn][PipeRead]; if (PRIVATE->grab[StdIn]) si.hStdInput = PRIVATE->pipes[StdIn][PipeRead];
if (PRIVATE->grab[StdOut]) si.hStdOutput = PRIVATE->pipes[StdOut][PipeWrite]; if (PRIVATE->grab[StdOut]) si.hStdOutput = PRIVATE->pipes[StdOut][PipeWrite];
if (PRIVATE->grab[StdErr]) si.hStdError = PRIVATE->pipes[StdErr][PipeWrite]; if (PRIVATE->grab[StdErr]) si.hStdError = PRIVATE->pipes[StdErr][PipeWrite];
si.dwFlags |= STARTF_USESTDHANDLES; si.dwFlags |= STARTF_USESTDHANDLES;
const auto cmd = convertWindowsCmd(args);
// piCout << cmd;
if (CreateProcessA(0, // No module name (use command line) if (CreateProcessA(0, // No module name (use command line)
convertWindowsCmd(args), // Command line (LPSTR)cmd.data(), // Command line
0, // Process handle not inheritable 0, // Process handle not inheritable
0, // Thread handle not inheritable 0, // Thread handle not inheritable
false, // Set handle inheritance to FALSE true, // Set handle inheritance to FALSE
detached ? DETACHED_PROCESS /*CREATE_NEW_CONSOLE*/ : 0, // Creation flags detached ? DETACHED_PROCESS /*CREATE_NEW_CONSOLE*/ : 0, // Creation flags
0, // Use environment 0, // Use environment
wd.isEmpty() ? 0 : wd.data(), // Use working directory wd.isEmpty() ? 0 : wd.data(), // Use working directory
&si, // Pointer to STARTUPINFO structure &si, // Pointer to STARTUPINFO structure
&(PRIVATE->pi))) // Pointer to PROCESS_INFORMATION structure &(PRIVATE->pi))) // Pointer to PROCESS_INFORMATION structure
{ {
// piCout << "started";
exec_start = true; exec_start = true;
if (!detached) { if (!detached) {
WaitForSingleObject(PRIVATE->pi.hProcess, INFINITE); WaitForSingleObject(PRIVATE->pi.hProcess, INFINITE);
@@ -397,7 +417,12 @@ bool PIProcess::writeInput(const PIByteArray & data) {
void PIProcess::closeInput() { void PIProcess::closeInput() {
if (PRIVATE->grab[StdIn]) PRIVATE->closePipe(StdIn, PipeWrite); if (PRIVATE->grab[StdIn]) {
# ifdef WINDOWS
// PRIVATE->writePipe({0x1A});
# endif
PRIVATE->closePipe(StdIn, PipeWrite);
}
} }

View File

@@ -9,7 +9,7 @@ protected:
PIProcess launcher; PIProcess launcher;
const PIString command = const PIString command =
#ifdef _WIN32 #ifdef _WIN32
"cmd.exe"; "C:/Windows/System32/cmd.exe";
#else #else
"/bin/sh"; "/bin/sh";
#endif #endif
@@ -61,7 +61,7 @@ TEST_F(ProcessTest, Output) {
TEST_F(ProcessTest, Input) { TEST_F(ProcessTest, Input) {
#ifdef _WIN32 #ifdef _WIN32
const PIStringList args = {"/c", "set /p input= && echo %input%"}; const PIStringList args = {"/c", "more"};
#else #else
const PIStringList args = {"-c", "read input; echo $input"}; const PIStringList args = {"-c", "read input; echo $input"};
#endif #endif
@@ -73,7 +73,10 @@ TEST_F(ProcessTest, Input) {
EXPECT_TRUE(launcher.isExecStarted()); EXPECT_TRUE(launcher.isExecStarted());
EXPECT_TRUE(!launcher.isExecFinished()); EXPECT_TRUE(!launcher.isExecFinished());
const PIString test_input = "Test input string\n"; PIString test_input = "Test input string\n";
#ifdef WINDOWS
test_input += (char)0x1A;
#endif
EXPECT_TRUE(launcher.writeInput(test_input.toAscii())); EXPECT_TRUE(launcher.writeInput(test_input.toAscii()));
launcher.closeInput(); launcher.closeInput();
@@ -91,5 +94,5 @@ TEST_F(ProcessTest, NonexistentCommand) {
launcher.exec(command); launcher.exec(command);
ASSERT_TRUE(launcher.isRunning()); ASSERT_TRUE(launcher.isRunning());
ASSERT_TRUE(launcher.waitForFinish()); ASSERT_TRUE(launcher.waitForFinish());
EXPECT_FALSE(!launcher.isExecFinished()); EXPECT_FALSE(launcher.isExecFinished());
} }