1

我正在扩展一个 .NET4 命令行应用程序,除其他外,它创建了一个外部进程来调用svn.exe以从我们的存储库中提取一些数据。问题是当我们的账号密码修改后,认证失败,SVN提示输入账号密码。

SVN 通过向标准错误写入提示来做到这一点。输出如下所示:

标准输出:更新“。”:
STDERR:身份验证领域:<http://{host}:8080> VisualSVN 服务器
STDERR:“joe.smith”的密码:

我认为出错的地方是子进程(此后称为 CP)的第二个“行”不包含换行符,并且在父进程(PP)阻塞标准输入之前可能没有被BeginErrorRead Line()拾取溪流。我的猜测得到了以下事实的支持:关闭 CP 上的输入流会导致来自输出流和错误流的剩余数据由我的DataReceivedEventHandler回调处理。

事件的顺序似乎是:

  1. CP 开始写入 STDOUT。
  2. 如果缓存的身份验证凭证错误,CP 开始将上述消息写入 STDERR。
  3. 根据我是从 STDERR 同步读取还是异步读取,会发生以下情况:
    • 同步:CP 似乎在等待来自 STDIN 的输入,而 PP 等待来自 STDERR 的更多数据。即使偷看或检查流是否关闭也会导致死锁。
    • 异步:在 CP 等待从其 STDIN 读取之前,不读取第二行。

假设我已经正确诊断出问题,我仍然不知道该怎么做。

至于我尝试过的选项:

  • 这篇 MSDN 文章之后,我尝试从标准错误中同步读取。这似乎充满了危险,因为任何方法只要读取标准错误中的最后一个字符就会无限期地阻塞。
  • 上一个链接还建议“或者,您可以通过创建两个线程并在单独的线程上读取每个流的输出来避免死锁情况。” ,但是我在这条赛道上的努力显然被误导了。当我知道我已经到达流的尽头时,我看不到线程如何提供帮助,为时已晚。

为了澄清,我怎样才能安全地读到标准错误流的末尾而不会导致死锁?

4

1 回答 1

1

I think your analysis is correct. I've had to do a bit of CP stdio redirection, and it's always a pain on Win32 (designed as a UI platform rather than command-line...).

Anyway, you could try reading from the actual streams (using BeginRead, or ReadAsync if .NET 4.5) and doing the Encoding conversion yourself. That would be my first attempt.

Otherwise, you'd have to use multiple threads. I've done this before, and it's a pain.

Either way, you're not actually waiting for the end of the CP's stderr. Just monitor it for you magic string. Most console programs do not close their stdout or stderr until they exit, so you can't read it all the way to the end until it has exited.

于 2012-07-15T01:18:18.383 回答