PIProcess windows works
This commit is contained in:
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user