C# - 重定向子进程输入以读取win服务父进程写入的内容

时间:2016-06-09 08:47:11

标签: c# .net

我读了很多关于这个话题的内容,但我无法理解。我有一个SSCCE,其服务使用CreateProcessAsUser创建子进程。此子进程仅用于从其标准输入读取;父进程写的是什么,但是我从父母那里得不到任何东西。

家长服务代码:

    public static unsafe int WriteToHandle(byte[] buffer, int index, int count, IntPtr hStdOut)
    {
        int n = 0;
        bool cont = true;

            fixed (byte* p = buffer)
            {
               cont = WriteFile(hStdOut, p + index, count, &n, 0);

            }
        return n;
    }

    public static bool StartProcessAsCurrentUser()
    {
        var hUserToken = IntPtr.Zero;
        var sInfo = new STARTUPINFO();
        var procInfo = new PROCESS_INFORMATION();
        var pEnv = IntPtr.Zero;
        int iResultOfCreateProcessAsUser;
        string cmdLine = "ClientFormApp.exe";

        sInfo.cb = Marshal.SizeOf(typeof(STARTUPINFO));
        byte[] buffer = new byte[BUFSIZE];

        bool result = false;

        const int STARTF_USESTDHANDLES = 0x00000100;
        const int STARTF_USESHOWWINDOW = 0x00000001;
        const int WAIT_TIMEOUT = 0x102;
        const int ERROR_SUCCESS = 0x0;
        const int HANDLE_FLAG_INHERIT = 1;

        try
        {
            var tSecurity = new SECURITY_ATTRIBUTES();
            tSecurity.nLength = Marshal.SizeOf(tSecurity);
            var pSecurity = new SECURITY_ATTRIBUTES();
            pSecurity.nLength = Marshal.SizeOf(pSecurity);
            pSecurity.bInheritHandle = true; 

            IntPtr pointer = Marshal.AllocHGlobal(Marshal.SizeOf(pSecurity));
            Marshal.StructureToPtr(pSecurity, pointer, true);

            if (!CreatePipe(out hReadOut, out hWriteOut, pointer, 0)) // hReadOut -> read data from output | hWriteOut -> send data to output
                return result = false;
            if (!CreatePipe(out hReadIn, out hWriteIn, pointer, 0)) // hReadOut -> read data from output | hWriteOut -> send data to output
                return result = false;

            if (!SetHandleInformation(hWriteOut, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
                return result = false;
            if (!SetHandleInformation(hReadOut, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
                return result = false;

            if (!SetHandleInformation(hWriteIn, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
                return result = false;
            if (!SetHandleInformation(hReadIn, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
                return result = false;

            sInfo.hStdOutput = hWriteOut; 
            sInfo.hStdInput = hReadIn; 
            sInfo.hStdError = hWriteOut; 

            if (!GetSessionUserToken(ref hUserToken))
            {
                throw new Exception("StartProcessAsCurrentUser: GetSessionUserToken failed.");
            }

            uint dwCreationFlags = CREATE_UNICODE_ENVIRONMENT | (uint)CREATE_NEW_CONSOLE;
            sInfo.wShowWindow = (short)SW.SW_SHOW;
            sInfo.lpDesktop = "winsta0\\default";

            if (!CreateEnvironmentBlock(ref pEnv, hUserToken, false))
            {
                throw new Exception("StartProcessAsCurrentUser: CreateEnvironmentBlock failed.");
            }

            if (!CreateProcessAsUser(hUserToken,
                null, // Application Name
                cmdLine, // Command Line
                IntPtr.Zero,
                IntPtr.Zero,
                true,
                dwCreationFlags,
                pEnv,
                null, // Working directory
                ref sInfo,
                out procInfo))
            {
                throw new Exception("StartProcessAsCurrentUser: CreateProcessAsUser failed.\n");
            }

            iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();
            string message = "Message";
            byte[] messageByte = System.Text.Encoding.Unicode.GetBytes(message);
            int bytesWrited = WriteToHandle(messageByte, 0, messageByte.Length, hWriteIn);
        }
        finally
        {
            //Clossing handles
        }

        return true;
    }
}

我已经验证bytesWrited不是0.

关注this example,这是我的子流程:

    public static unsafe int ReadFromHandle(byte[] buffer, int index, int count, IntPtr hStdOut)
    {
        int n = 0;

        try
        {
            fixed (byte* p = buffer)
            {
                if (!ReadFile(hStdOut, p + index, count, &n, 0)) //Nothing to read from handle
                    return 0;
            }
            return n;
        }
        catch (Exception e)
        {
            return 0;
        }
    }

    private void OnNewStep()
    {
        byte[] buffer = new byte[BUFSIZE];
        const int STD_OUTPUT_HANDLE = -11;
        const int STD_INPUT_HANDLE = -10;
        const int STD_ERROR_HANDLE = -12;
        string content = "";

        hStdin = GetStdHandle(STD_INPUT_HANDLE);

        do
        {
            bytesReadOutput = ReadFromHandle(buffer, 0, buffer.Length, hStdin);
            content = content + System.Text.Encoding.Unicode.GetString(buffer, 0, bytesReadOutput);
        }
    }

bytesReadOutput始终为0.我并不真正理解第hStdin = GetStdHandle(STD_INPUT_HANDLE)行的目的。如果我没有错,当我在服务流程中创建子流程时,我在子流程中设置重定向的标准输入sInfo.hStdInput = hReadIn;hStdin = GetStdHandle(STD_INPUT_HANDLE)会得到{{1}服务句柄。但是我检查了它,hReadIn总是0。

我做错了什么?提前谢谢。

0 个答案:

没有答案