从进程获取实时输出
我的项目有问题。我想启动一个进程,7z.exe(控制台版本)。 我尝试了三种不同的方法:
- Process.StandardOutput.ReadToEnd();
- 接收到的输出数据BeginOutputReadLine
- StreamWriter
没有任何作用。它总是“等待”过程结束以显示我想要的内容。 我没有任何代码可以放置,只是如果您希望我的代码具有上面列出的内容之一。谢谢。
编辑: 我的代码:
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.CreateNoWindow = true;
process.Start();
this.sr = process.StandardOutput;
while (!sr.EndOfStream)
{
String s = sr.ReadLine();
if (s != "")
{
System.Console.WriteLine(DateTime.Now + " - " + s);
}
}
或者
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.OutputDataReceived += new DataReceivedEventHandler(recieve);
process.StartInfo.CreateNoWindow = true;
process.Start();
process.BeginOutputReadLine();
process.WaitForExit();
public void recieve(object e, DataReceivedEventArgs outLine)
{
System.Console.WriteLine(DateTime.Now + " - " + outLine.Data);
}
或者
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
string output = p.StandardOutput.ReadToEnd();
process.WaitForExit();
其中“进程”是我预先制作的进程
好的,我知道为什么它不能正常工作:7z.exe 是错误:它在控制台中显示加载百分比,并且仅在当前文件时才发送信息完成了。例如,在提取中,它工作得很好:)。我将寻找另一种在没有 7z.exe 的情况下使用 7z 函数的方法(也许使用 7za.exe 或某些 DLL)。感谢大家。 为了回答这个问题,OuputDataRecieved 事件工作正常!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
看看这个页面,看起来这就是适合您的解决方案: http://msdn.microsoft.com/en-us/library/system.diagnostics.process.beginoutputreadline.aspx 和 http://msdn.microsoft.com/en-us/library /system.diagnostics.process.standardoutput.aspx
[编辑]
这是一个工作示例:
顺便说一句,ls -RC:\ 递归地列出 C: 根目录中的所有文件。这些文件很多,我确信当第一个结果出现在屏幕上时它还没有完成。
7zip 有可能在显示输出之前保留它。我不确定你给进程提供了什么参数。
Take a look at this page, it looks this is the solution for you: http://msdn.microsoft.com/en-us/library/system.diagnostics.process.beginoutputreadline.aspx and http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardoutput.aspx
[Edit]
This is a working example:
Btw, ls -R C:\ lists all files from the root of C: recursively. These are a lot of files, and I'm sure it isn't done when the first results show up in the screen.
There is a possibility 7zip holds the output before showing it. I'm not sure what params you give to the proces.
要正确处理输出和/或错误重定向,您还必须重定向输入。
这似乎是您正在启动的外部应用程序运行时的功能/错误,从我到目前为止所看到的情况来看,其他任何地方都没有提到它。
用法示例:
...
To correctly handle output and/or error redirection you must also redirect input.
It seem to be feature/bug in runtime of the external application youre starting and from what I have seen so far, it is not mentioned anywhere else.
Example usage:
...
我不知道是否有人仍在寻找解决方案,但这个问题对我来说已经出现过好几次了,因为我正在 Unity 中编写一个工具来支持某些游戏,并且由于某些系统与单声道的互操作性有限(例如,用于从 Word 中读取文本的 PIA),我经常必须编写特定于操作系统(有时是 Windows,有时是 MacOS)的可执行文件并从 Process.Start() 启动它们。
问题是,当您启动这样的可执行文件时,它将在另一个线程中启动,该线程会阻塞您的主应用程序,从而导致挂起。如果您想在这段时间内向用户提供有用的反馈,而不是各自操作系统召唤出的旋转图标,那么您就完蛋了。使用流不起作用,因为线程在执行完成之前仍处于阻塞状态。
我想到的解决方案(对某些人来说可能有点极端,但我发现对我来说效果很好)是使用套接字和多线程在两个应用程序之间建立可靠的同步通信。当然,这只适用于您同时编写这两个应用程序的情况。如果没有,我想你运气不好。 ...我想看看它是否仅适用于使用传统流方法的多线程,所以如果有人想尝试并在这里发布结果,那就太好了。
无论如何,这是目前对我有用的解决方案:
在主程序或调用应用程序中,我执行以下操作:
这是我建立套接字服务器的位置:
这是我的线程套接字处理程序...请注意,您必须创建多个某些情况下有线程;这就是为什么我在那里有 _builderCommThreads 列表(我从其他地方的代码中移植了它,我在其他地方做了类似的事情,但连续调用多个实例):
当然,您需要在顶部声明一些内容:
...然后在调用的可执行文件中,设置另一端(在本例中我使用了静态,您可以使用您想要的任何内容):
...我使用它在 Windows 上启动一个命令行工具,该工具使用 PIA 内容来从 Word 中提取文本文档。我在 Unity 中尝试了 PIA .dll,但遇到了与 Mono 的互操作问题。我还在 MacOS 上使用它来调用 shell 脚本,这些脚本以批处理模式启动其他 Unity 实例,并在这些实例中运行编辑器脚本,通过此套接字连接与工具进行对话。这太棒了,因为我现在可以向用户发送反馈、调试、监控和响应流程中的特定步骤,等等。
华泰
I don't know if anyone is still looking for a solution to this, but it has come up several times for me because I'm writing a tool in Unity in support of some games and due to the limited interoperability of certain systems with mono (like PIA for reading text from Word, for example), I often have to write OS-specific (sometimes Windows, sometimes MacOS) executables and launch them from Process.Start().
The problem is, when you launch an executable like this it's going to fire up in another thread that blocks your main app, causing a hang. If you want to provide useful feedback to your users during this time beyond the spinning icons conjured up by your respective OS, then you're kind of screwed. Using a stream won't work because the thread is still blocked until execution finishes.
The solution I've hit on, which might seem extreme for some people but I find works quite well for me, is to use sockets and multithreading to set up reliable synchronous comms between the two apps. Of course, this only works if you are authoring both apps. If not, I think you are out of luck. ... I would like to see if it works with just multithreading using a traditional stream approach, so if someone would like to try that and post the results here that would be great.
Anyway, here's the solution currently working for me:
In the main, or calling app, I do something like this:
Here's where I establish the socket server:
Here's my socket handler for the thread... note that you will have to create multiple threads in some cases; that's why I have that _builderCommThreads List in there (I ported it from code elsewhere where I was doing something similar but calling multiple instances in a row):
Of course, you'll need to declare some stuff up at the top:
...then in the invoked executable, set up the other end (I used statics in this case, you can use what ever you want):
...I'm using this to launch a command line tool on Windows that uses the PIA stuff to pull text out of a Word doc. I tried PIA the .dlls in Unity, but ran into interop issues with mono. I'm also using it on MacOS to invoke shell scripts that launch additional Unity instances in batchmode and run editor scripts in those instances that talk back to the tool over this socket connection. It's great, because I can now send feedback to the user, debug, monitor and respond to specific steps in the process, et cetera, et cetera.
HTH
该问题是由调用 引起的Process.WaitForExit方法。根据文档,它的作用是:
因此,为了防止线程阻塞直到进程退出,请连接 Process 对象的Process.Exited事件处理程序,如下所示。仅当 EnableRaisingEvents 属性的值为 true 时,Exited 事件才会发生。
通过这种方式,您将能够在进程仍在运行时通过 Process.OutputDataReceived 事件 就像您当前所做的那样。 (PS - 该事件页面上的代码示例也犯了使用 Process.WaitForExit 的错误。)
另一个注意事项是,您需要确保在您的 Exited 方法触发之前您的 Process 对象没有被清理。如果您的进程是在 using 语句中初始化的,这可能是一个问题。
The problem is caused by calling the Process.WaitForExit method. What this does, according to the documentation, is:
So, to prevent the thread blocking until the process has exited, wire up the Process.Exited event handler of the Process object, as below. The Exited event can occur only if the value of the EnableRaisingEvents property is true.
Done this way, you will be able to get the output of your process, while it is still running, via the Process.OutputDataReceived event as you currently do. (PS - the code example on that event page also makes the mistake of using Process.WaitForExit.)
Another note is that you need to ensure your Process object is not cleaned up before your Exited method can fire. If your Process is initialized in a using statement, this might be a problem.
我已经使用了描述的 CmdProcessor 类 这里有几个取得了巨大成功的项目。乍一看有点令人畏惧,但非常容易使用。
I have used the CmdProcessor class described here on several projects with much success. It looks a bit daunting at first but is very easy to use.
Windows 以不同的方式对待管道和控制台。管道是缓冲的,控制台不是。
RedirectStandardOutput
连接管道。只有两种解决方案。请注意,RTConsole 不处理STDERR 也遇到同样的问题。
感谢 https://stackoverflow.com/users/4139809/jeremy-lakeman 与我分享此信息与另一个问题的关系。
Windows treats pipes and consoles differently. Pipes are buffered, consoles are not.
RedirectStandardOutput
connects a pipe. There are only two solutions.Note that RTConsole does not handle STDERR which suffers the same problem.
Thanks to https://stackoverflow.com/users/4139809/jeremy-lakeman for sharing this information with me in relation to another question.
试试这个。
让上面的内容在一个
线程
中。现在,为了将输出更新到 UI,您可以使用带有两行的
timer
这可能会帮助您
Try this.
Let the above be in a
thread
.Now for updating the output to UI,you can use a
timer
with two linesThis may help you