Answered by:
How to read output of a console application launched by a windows service

Question
-
I've create a windows service run in LocalSystem account. In the service, a console application is launched and I need to capture the console output of the console application inside my windows service.
In my windows service, the console application is launched using CreateProcessAsUser, using an environment created using a logged-on user's session id obtained using .
To read the console application output, a pipe is created for redirecting console window output, and the handle is passed to the STARTUPINFO for creating the console application process. After the console application is launched, the code wait for the finish of the console application and then read the console application output. The logic of reading child console application output is working if not running within windows service.
When running inside windows service, I can see that the console application is launched with text output in the console window. But after the console application finishes, no console output text is read by my windows service.
Is there anyone had successfully done before the reading child console application process output inside windows service, please kindly let me know how you did it?
Answers
All replies
-
In my windows service, the console application is launched using CreateProcessAsUser, using an environment created using a logged-on user's session id obtained using .
I assume this means that you are launching a console application in the logged-on user's interactive session under the account of that user.
When running inside windows service, I can see that the console application is launched with text output in the console window. But after the console application finishes, no console output text is read by my windows service.
If you can see text output in the console application's window then the console application's stdout has not been redirected.
Post the code you use in the service to create the pipe and start the console application with redirected output.
-
Yes, I am using logged-on user's interactive session.
Code to create pipe and launch console application below:
HANDLE hToken = NULL; bool bSuccess = (TRUE == WTSQueryUserToken(m_nSessionId, &hToken)); // calling application must be running within the context of the LocalSystem account if (bSuccess) { void* pEnvironment = nullptr; bSuccess = (TRUE == CreateEnvironmentBlock(&pEnvironment, hToken, TRUE)); if (bSuccess) { wchar_t cBuf[1024]; ZeroMemory(cBuf, sizeof(cBuf)); swprintf_s(cBuf, _countof(cBuf), strParameters.c_str()); // Create security attributes to create pipe. SECURITY_ATTRIBUTES oSecurity = { sizeof(SECURITY_ATTRIBUTES) }; oSecurity.bInheritHandle = TRUE; // Set the bInheritHandle flag so pipe handles are inherited by child process. Required. oSecurity.lpSecurityDescriptor = NULL; m_hChildStdOutRead = NULL; m_hChildStdOutWrite = NULL;; // Create a pipe to get results from child's stdout. // I'll create only 1 because I don't need to pipe to the child's stdin. bool bSuccess = (TRUE == CreatePipe(&m_hChildStdOutRead, &m_hChildStdOutWrite, &oSecurity, 0)); if (bSuccess) { ZeroMemory(&m_oStartupInfo, sizeof(m_oStartupInfo)); m_oStartupInfo.cb = sizeof(m_oStartupInfo); m_oStartupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; // STARTF_USESTDHANDLES is Required. m_oStartupInfo.hStdOutput = m_hChildStdOutWrite; // Requires STARTF_USESTDHANDLES in dwFlags. m_oStartupInfo.hStdError = m_hChildStdOutWrite; // Requires STARTF_USESTDHANDLES in dwFlags. // m_oStartupInfo.hStdInput remains null. m_oStartupInfo.wShowWindow = SW_SHOW; m_oStartupInfo.lpDesktop = L"winsta0\\default"; PROCESS_INFORMATION oProcessInfo; ZeroMemory(&oProcessInfo, sizeof(oProcessInfo)); bSuccess = (TRUE == CreateProcessAsUser(hToken, // primary token representing a user m_strFullPathExe.c_str(), // optional application name cBuf, // command line NULL, // process attributes NULL, // thread attributes FALSE, // inherit handles NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, // creation flags pEnvironment, // environment block m_strWorkingDir.c_str(), // starting directory &m_oStartupInfo, // startup info &oProcessInfo)); // process info DestroyEnvironmentBlock(pEnvironment); CloseHandle(hToken); if (bSuccess) { m_hChildProcess = oProcessInfo.hProcess; m_hChildThread = oProcessInfo.hThread; } }
-
-