c# - 将 createprocessasuser 的 stdout 重定向到管道在读取时挂起

标签 c# pipe createprocessasuser

我正在使用 CreateProcessAsUser 从服务运行进程,并将标准输出重定向到命名管道。但是当我尝试从命名管道中读取时,它会卡在读取上并且永远不会返回。
我在一个单独的任务中尝试了这个(目前在下面实现)并且只是在主进程中读取它。我还尝试使用 C# AnonymousPipeServerStream 类(请参阅下面注释掉的代码),但同样挂起。

任何想法我缺少什么?谢谢!

            Native.SECURITY_ATTRIBUTES sa = new Native.SECURITY_ATTRIBUTES();
            processAttributes.nLength = Marshal.SizeOf(sa);
            processAttributes.lpSecurityDescriptor = IntPtr.Zero;
            processAttributes.bInheritHandle = 0;

            //AnonymousPipeServerStream pipeServer = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable);
            IntPtr readPipe = IntPtr.Zero;
            IntPtr subProcessPipe = IntPtr.Zero;
            if(!Native.CreatePipe(out readPipe, out subProcessPipe,ref sa, 0x0001))
            {
                throw new Exception("createpipe gave error: " + Marshal.GetLastWin32Error());
            }

            log.InfoFormat("pipe created");

            Task readPipeTask = Task.Factory.StartNew(() =>
            {
                log.InfoFormat("startingtask");
                var readBuff = new byte[BufferSize];
                uint bytesRead = 0;
                bool retval;
                while (true)
                {
                    retval = Native.ReadFile(readPipe, readBuff, BufferSize, out bytesRead, IntPtr.Zero);
                    if (!retval || bytesRead == 0)
                    {
                        log.InfoFormat("finalread {0} {1}", retval, bytesRead);
                        break;
                    }
                    log.InfoFormat("after read {0} {1}", retval, bytesRead);
                }
                log.InfoFormat("endingtask");
            });

            var processInfo = new Native.ProcessInformation();
            var startInfo = new Native.StartupInfo();
            startInfo.Size = Marshal.SizeOf(startInfo);
            //startInfo.StdOutput = pipeServer.SafePipeHandle.DangerousGetHandle();
            startInfo.StdOutput = subProcessPipe;
            log.InfoFormat("calling createprocess");
            if (!Native.CreateProcessAsUser(
                UserTokenHandle,
                null,
                command,
                IntPtr.Zero,
                IntPtr.Zero,
                false,
                0x00000020 | 0x00000010 | 0x00000400,

                IntPtr.Zero,
                null,
                ref startInfo,
                out processInfo))
            {
                throw new Exception("Create process didn't work : " + Marshal.GetLastWin32Error());
            }

            log.InfoFormat("process id = {0}", processInfo.ProcessId);
            int processId = processInfo.ProcessId;


            using (var process = Process.GetProcessById(processId))
            {
                var pid = process.Id;
                log.Info("process started : " + pid);

                process.WaitForExit(ProcessTimeoutIteration);
                log.Info("process Completed");
                readPipeTask.Wait();
                log.Info("process Completedafter wait");
            }
            ////log.Info("reading pipe canread = " + pipeServer.CanRead);
            ////log.Info("reading pipe isconnected = " + pipeServer.IsConnected);

            var standardOutput = new StringBuilder(InitialBufferSize);

            //////var readBuff = new byte[BufferSize];

            //var ac = new AsyncCallback(CallBackMethod);
            ////var bytesRead = pipeServer.Read(readBuff, 0, BufferSize);

            log.Info("before first read");
            ////while (bytesRead > 0)
            ////{
            ////    //fileStream.Write(readBuff, 0, bytesRead);
            ////    standardOutput.Append(Encoding.Unicode.GetString(readBuff));
            ////    bytesRead = pipeServer.Read(readBuff, 0, BufferSize);
            ////}

最佳答案

原因很明显:

if (!Native.CreateProcessAsUser(
                UserTokenHandle,
                null,
                command,
                IntPtr.Zero,
                IntPtr.Zero,
                false,
                0x00000020 | 0x00000010 | 0x00000400,

您不会通过设置 bInheritHandles 来继承句柄为假。

关于c# - 将 createprocessasuser 的 stdout 重定向到管道在读取时挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27642419/

相关文章:

python - 如何在Windows中使用python以用户身份创建进程?

c# - Mobile Blazor Binding 是否类似于在 Razor 模板中使用 XAML 进行编码?

c# - 生成没有忽略值的随机字节数组

c - pipe - fork - c - 为什么程序没有任何错误而没有响应?

windows - 没有密码的用户只有在管理员组中才能被模拟

c++ - CreateProecssAsUser 提升权限?

c# - 错误消息 : Model not picking language-specific resource file

c# - 具有单独实例的 .NET 自定义线程池

c - wait((int *)0) 的含义

c - 阻塞管道,c,linux