none
How to read output of a console application launched by a windows service RRS feed

  • 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?


    Monday, October 28, 2019 1:07 AM

Answers

  •       FALSE,                                          // inherit handles
    Change inherit handles parameter in CreateProcessAsUser to TRUE.
    • Marked as answer by jkschan Tuesday, October 29, 2019 1:27 AM
    Monday, October 28, 2019 9:09 AM

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.


    Monday, October 28, 2019 2:03 AM
  • 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;
                    }
                }

    Monday, October 28, 2019 2:31 AM
  •       FALSE,                                          // inherit handles
    Change inherit handles parameter in CreateProcessAsUser to TRUE.
    • Marked as answer by jkschan Tuesday, October 29, 2019 1:27 AM
    Monday, October 28, 2019 9:09 AM
  • Hi RLWA32, thank you for your answer. It solves my problem.


    Tuesday, October 29, 2019 1:38 AM