象 Tortoise CVS这样的程序, 完美地为 cvs.exe命令做UI包装. 它用C++/wxWidget 实现, 我在.NET程序员中也经常有这样的需求:
1. 想调用命令行程序, 准确说, 是exe中的子系统为console的程序.
2. 获得标准输出, 标准错误输出
3. 同步地获得输出和标准错误输出, 也就是说, 如果程序中交替地使用
fprintf(stdout, "aaaa\n");
Sleep(2);
fprintf(stderr, "bbbb\n");
那么输出 aaaa之后马上就在UI程序中能获得结果, 而不是等2秒钟以后, 这一点对于获得更直观的用户体验非常重要, 简单的 ReadToEnd() 方法不行, 会让你一直等待, 直到所有东西都输出完事了, 你才一下子获取了所有东西.
比较一下VS2008 在编译程序时的输出就知道这种感觉, 每输出一行内容, 程序员都可以得到一点反馈.
在看 TypeMock的一篇教程时. 偶尔看到一个链接, 这个作者跟我一样, 也是C# snippet compiler的铁杆粉丝, 他写了一个模板来做简单的 UnitTest和TypeMock, 但给我的意外收获是这个模板里用简单的代码实现了上面的需求, 以前在写CVS Reviewer工具时, 大量需要跟cvs.exe命令行工具打交道, 在CodeProject上找到了个ProcessCall 的类专门做这事, 可是那个类限制很强.
关键的几点:
* 想让Console程序被执行时, 不出现DOS的黑乎乎窗口, 必需:
proc.UseShellExecute = false;
proc.CreateNoWindow = true;
不要看到 CreateNoWindow的名字就以为可以仅凭它就能消除DOS窗口, 还得前面的 UseShellExecute=false
* 访问进程实例的 StandardOutput和StandardError 两个方法, 必需在进程的 Start方法调用之后, 否则, 进程未启动时, 是没有这两个流可供访问的.
* 访问StandardOutput还必需得 RedirectStandardError 设为true, 后者在Start方法之前设置.
* Stream.BeginRead 还没搞明白.
阅读(2302) | 评论(0) | 转发(0) |