我正在扩展一个 .NET4命令行应用程序,除其他外,创建一个外部进程来调用svn.exe
从我们的存储库中提取一些数据。问题是,当我们的帐户密码更改时,身份验证失败,SVN提示输入帐户密码。
SVN通过向标准错误写入提示来做到这一点。输出如下所示:
标准输出: 更新".":STDERR: Authentication realm: VisualSVN ServerSTDERR:"joe.smith"的密码:
我认为出错的地方是子进程(CP以后)的第二"行"不包含换行符,并且可能不会在标准输入流上的父进程(PP)块之前被BeginErrorReadLine()拾取。我的猜测得到了以下事实的支持:关闭 CP 上的输入流会导致输出流和错误流中的剩余数据由我的 DataReceivedEventHandler 回调处理。
事件的顺序似乎是:
- CP开始写入STDOUT。
- 如果缓存的身份验证凭据错误,CP 将开始将上述消息写入 STDERR。
- 根据我是同步读取还是异步读取 STDERR,会发生以下情况:
- 同步:CP 似乎等待来自 STDIN 的输入,而 PP 等待来自 STDERR 的更多数据。即使查看或检查流是否已关闭也会导致死锁。
- 异步:在 CP 等待从其 STDIN读取之前,不会读取第二行。
假设我已经正确诊断了问题,我仍然不知道该怎么做。
至于我尝试过的选项:
- 在这篇 MSDN 文章之后,我尝试从标准错误中同步读取。这似乎充满了危险,因为任何方法一旦读取最后一个字符 fron 标准错误就会无限期地阻止。 上
- 一个链接还建议"或者,您可以通过创建两个线程并在单独的线程上读取每个流的输出来避免死锁情况",但是我沿着这条轨道的努力显然是错误的。我不明白线程如何提供帮助,当我知道我已经到达流的尽头时,为时已晚。
澄清一下,如何安全地读取标准错误流的末尾而不导致死锁?
我认为你的分析是正确的。我不得不做一些 CP stdio 重定向,这在 Win32 上总是很痛苦(设计为 UI 平台而不是命令行......
无论如何,您可以尝试从实际流中读取(使用 BeginRead
,或者ReadAsync
如果是 .NET 4.5)并自己进行Encoding
转换。这将是我的第一次尝试。
否则,您必须使用多个线程。我以前做过这个,这很痛苦。
无论哪种方式,您实际上都不是在等待CP的stderr的结束。只需为您监控魔术字符串即可。大多数控制台程序在退出之前不会关闭其 stdout 或 stderr,因此在它退出之前,您无法一直读取到最后。