4

我正在使用带有代码的 C# .NET 4 进程启动 PsExec

var startInfo = new ProcessStartInfo(psExecLocation)
{
    Arguments = string.Format(@"\\{0} -accepteula -u {1} -p {2} {3}", serverName, username, password, command),
    RedirectStandardError = true,
    RedirectStandardOutput = true,
    CreateNoWindow = true,
    StandardErrorEncoding = Encoding.UTF8,
    StandardOutputEncoding = Encoding.UTF8,
    UseShellExecute = false
};

当我与我的开发机器在同一个域中时,使用 PsExec 可以正常工作(对于我正在进行的所有调用,这不仅仅是我遇到的问题)以及在跨域执行简单的 DOS 命令(rmdir 和 mkdir)时(正如我在这次通话之前所做的那样)。

但是,当我让它运行以下命令时:

C:\7Zip\7za x "C:[文件路径包含空格]\__STAGING__\App01 [Trunk - STAGE_20121217.2].7z" -o"C:[文件路径包含空格]\__STAGING__\" -y -aoa

它永远不会回来。我可以看到它开始返回数据(我正在使用进程重定向输出并开始返回它所做的事情),但随后它突然停止并且什么也不做。调用后它永远不会返回

process.WaitForExit();

奇怪的是它确实成功完成了。我可以 RDP 进入我们正在提取文件的服务器,我可以在那里看到文件,只是 PsExec 没有返回任何内容。我已经尝试删除 -y -aoa 开关并移动事物的顺序,但似乎没有任何效果。仅供参考,我们试图在其中提取此内容的服务器是 Windows Server 2003 版本和 Windows Server 2008 R2 版本。

正如所问的,这正是我使用 PsExec 打开进程所要做的:

        try
        {
            using (var process = new Process())
            {
                var startInfo = new ProcessStartInfo(psExecLocation)
                    {
                        Arguments = string.Format(@"\\{0} -accepteula -u {1} -p {2} {3}", serverName, username, password, command),
                        RedirectStandardError = true,
                        RedirectStandardOutput = true,
                        CreateNoWindow = true,
                        StandardErrorEncoding = Encoding.UTF8,
                        StandardOutputEncoding = Encoding.UTF8,
                        UseShellExecute = false
                    };

                process.StartInfo = startInfo;

                var processOutput = "";
                Action<object, DataReceivedEventArgs> action = (obj, eventArgs) =>
                    {
                        if (string.IsNullOrWhiteSpace(eventArgs.Data) == false)
                            processOutput += string.Format("{0}\r\n", eventArgs.Data);
                    };

                process.OutputDataReceived += new DataReceivedEventHandler(action);
                process.ErrorDataReceived += new DataReceivedEventHandler(action);

                process.Start();

                process.BeginOutputReadLine();
                process.BeginErrorReadLine();

                process.WaitForExit();

                // There appears to be a fault in PsExec that has everything go to error even if it is output. This gets around that
                output = "";
                if (string.IsNullOrWhiteSpace(processOutput) == false)
                {
                    output = processOutput;

                    // error code 0 means it worked / succeeded. Any other "error code" means something failed
                    var loweredOutput = processOutput.ToLower().Replace("\r\n", "").Trim();
                    return loweredOutput.EndsWith("error code 0.") || loweredOutput.EndsWith("error code 0");
                }

                // if it got here, psexec didn't return anything. That SHOULD never happen (emphasis on should)
                return false;
            }
        }
        catch (Exception ex)
        {
            Logging.Logger.LogError(ex);
            output = "";
            return false;
        }
4

1 回答 1

0

这不是一个真正的答案,但我遇到了一个非常相似的问题。我在同一个域中运行,但看到的结果与描述的相同。

每次我从 C# 代码或 PowerShell 运行 PsExec 时,进程似乎都会挂起。当我查看远程服务器时,我看到 PSEXESVC 进程启动,以及我试图在远程服务器上运行的命令。该命令正常退出,但 PSEXESVC 似乎挂起。

我传递的远程命令是:cmd /c dir E:\temp

我已经在 LINQPad 上对此进行了测试,其中 CreateNoWindow 设置为 false 以及重定向设置为 false 并且打开的命令提示符确实返回了预期的输出。一旦我尝试再次捕获输出,该过程就会回到挂起状态。

我知道这曾经在一两年前使用相同的代码在 C# 中工作,所以我不确定是什么改变导致它现在挂起。

于 2012-12-20T23:18:54.050 回答