【问题标题】:Why is Process.StandardOutput different from the actual output and/or incomplete?为什么 Process.StandardOutput 与实际输出不同和/或不完整?
【发布时间】:2018-07-31 22:04:35
【问题描述】:

嗯,首先,当从 C# 执行 PsExec 命令时,一部分输出在 StandardOutput 中,另一部分在 StandardError出于某种原因,如 @987654321 所述@,但这没什么大不了的。

现在,问题是:即使将这两个部分组合在一起,“输出”与命令提示符窗口上显示的内容相比也不完全相同。有时不同,有时不完整。

这是我的代码:

string args = $@"{computerName} -u ""{username}"" -p ""{password}"" {pathOrCommand}";
var pi = new ProcessStartInfo("PsExec.exe", args);
pi.CreateNoWindow = true;
pi.WindowStyle = ProcessWindowStyle.Hidden;
pi.UseShellExecute = false;
pi.RedirectStandardOutput = true;
pi.RedirectStandardError = true;
using (Process p = Process.Start(pi))
{
    var resultLines = new List<string>();
    var handler = new DataReceivedEventHandler(delegate (object o, DataReceivedEventArgs e)
    {
        resultLines.Add(e.Data);
    });
    p.ErrorDataReceived += handler;
    p.OutputDataReceived += handler;
    p.BeginErrorReadLine();
    p.BeginOutputReadLine();

    p.WaitForExit();   
    string result = string.Join("\r\n", resultLines);
}
  • 不同时的示例:

    输入错误的用户名或密码时,命令提示符会显示如下信息:*

    登录失败:未知用户名或密码错误。

    ..而上述代码的输出将是:

    句柄无效。

  • 一个不完整的例子(这更重要)

    执行此命令PsExec \\computer -u username -p password query session时,结果如下所示:*

     SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE
    >services                                    0  Disc
     console           someUserName              1  Active
     rdp-tcp                                 65537  Listen
    

    ..但从 C# 执行时的输出仅为:

     SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE
    

所以,我的问题是:

  • 为什么Process.StandardOutput/Process.StandardError与实际输出不一样?

  • 有没有办法解决这个问题?


*这里只展示输出的相关部分。

【问题讨论】:

  • 可能与 stream.AutoFlush 设置有关?
  • @RubensFarias 我什至没有在我的代码中使用流。我用DataReceivedEvents。也许流是在引擎盖下使用的?即使是这样,那会导致输出是一个完全不同的英文句子吗?这是奇怪的部分!
  • 我明白这不是一个不同的句子,而只是一个_截断_/不完整的版本;在幕后,我们正在玩流:msdn.microsoft.com/library/…
  • @RubensFarias 看看我的问题中的第一个例子:An example of when it's different:
  • 我现在无法测试query session 命令(IIRC 交互模式或psexec 在远程进程结束时结束。应该有一个开关来稍微修改一下)。关于错误输出,将ErrorDataReceived 事件分配给它自己的处理程序。

标签: c# process stdout psexec


【解决方案1】:

我仍然不明白为什么输出不同,但我设法创建了一个解决方法,除非有人提供更好的解决方案,否则我将使用它。

我使用cmd.exestdoutstderr 重定向到临时文件。进程退出后,我读取文件内容,然后删除:

string tempFile = Path.GetTempFileName();
string args = $@"/c PsExec.exe {computerName} -u ""{username}"" -p ""{password}"" {pathOrCommand}";
var pi = new ProcessStartInfo("cmd.exe", $"{args} 1> {tempFile} 2>&1");
pi.CreateNoWindow = true;
pi.WindowStyle = ProcessWindowStyle.Hidden;
using (Process p = Process.Start(pi))
{
    p.WaitForExit();

    string result = File.ReadAllText(tempFile);
    File.Delete(tempFile);
}

希望这可以帮助遇到同样问题的其他人。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-28
    • 1970-01-01
    • 1970-01-01
    • 2019-11-15
    相关资源
    最近更新 更多