在System.Diagnostics.Process中包装命令shell [英] Wrap command shell in System.Diagnostics.Process

查看:66
本文介绍了在System.Diagnostics.Process中包装命令shell的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有谁知道为什么使用System.Diagnostics.Process来换行?控制台

应用程序并不总是传输I / O,具体取决于你试图消费的过程

?例如,PowerShell似乎不会通过Process对象处理任何I / O.


我知道在PowerShell的情况下有更好的包裹的方法

控制台直接与

System.Management.Automation或一些类似命名的命名空间的程序集连接,但我是

尝试为多种类型的进程使用通用命令行包装器

使用控制台I / O,而PowerShell是一个方便的例子,为什么这个
不能工作。


ProcessStartInfo psi =新的ProcessStartInfo(

@" C:\ Windows \ system32 \ WindowsPowerShell \ v1.0 \ power shell。 exe");

psi.Arguments =" -NoLogo";

psi.UseShellExecute = false;

psi.CreateNoWindow = true;

psi.RedirectStandardInput = true;

psi.RedirectStandardOutput = true;

//psi.RedirectStandardError = true;

处理流程=新流程();

process.StartInfo = psi;

bool started = process.Start();

if (已开始)

{

process.StandardInput.WriteLine(&q uot; 2 + 2");

process.StandardInput.Flush();

string ret = process.StandardOutput.ReadLine(); //< - 在这里停转

System.Console.WriteLine(" PowerShell说\2 + 2 =" + ret +" \"。");

}

另一个我试图包裹的是Dave的原始实现

Raggett的HTML Tidy。下面的内容有时会在ReadToEnd()上停顿。在我添加process.StandardInput.Close();之前,
似乎总是停滞不前。

" process.StandardInput.Flush();"但它仍然在ReadToEnd()的一半时间内停滞。


...

_TidyProcessStartInfo = new ProcessStartInfo(

Directory.GetParent(System.Reflection.Assembly.Get ExecutingAssembly()。Location)

+" \\tidy.exe");

_TidyProcessStartInfo.UseShellExecute = false;

_TidyProcessStartInfo.CreateNoWindow = true;

_TidyProcessStartInfo.RedirectStandardInput = true;

_TidyProcessStartInfo.RedirectStandardOutput = true;

_TidyProcessStartInfo.RedirectStandardError = true;

.. 。

流程流程=新流程();

process.StartInfo = _TidyProcessStartInfo;

process.ErrorDataReceived + = new

DataReceivedEventHandler(Exe_ErrorDataReceived);

bool started = process.Start();

if(started)

{

//process.StandardInput.AutoFlush = true;

process.StandardInput.WriteLine(输入);

process.StandardInput.Flush();

process.StandardInput.Close();

ret = process.StandardOutput.ReadToEnd();

}


谢谢,

Jon

Does anyone know why using System.Diagnostics.Process to "wrap" a console
application does not always transmit the I/O, depending on what processes
you''re trying to "consume"? PowerShell, for example, does not seem to
process any I/O through the Process object.

I know that in the case of PowerShell there are better ways to "wrap" the
console by directly interfacing with the assemblies of
System.Management.Automation or some similarly named namespace, but I''m
trying to use generic command line wrappers for multiple types of processes
that use the console I/O, and PowerShell was a handy example of why this
won''t work.

ProcessStartInfo psi = new ProcessStartInfo(
@"C:\Windows\system32\WindowsPowerShell\v1.0\power shell.exe");
psi.Arguments = "-NoLogo";
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
//psi.RedirectStandardError = true;
Process process = new Process();
process.StartInfo = psi;
bool started = process.Start();
if (started)
{
process.StandardInput.WriteLine("2+2");
process.StandardInput.Flush();
string ret = process.StandardOutput.ReadLine(); // <-- stalls here
System.Console.WriteLine("PowerShell says \"2+2=" + ret + "\".");
}
Another one I was trying to "wrap" was the original implementation of Dave
Raggett''s HTML Tidy. The stuff below sometimes stalls on ReadToEnd(). It
seemed to always stall until I added "process.StandardInput.Close();" after
"process.StandardInput.Flush();" but it still stalls on ReadToEnd() half the
time.

...
_TidyProcessStartInfo = new ProcessStartInfo(
Directory.GetParent(System.Reflection.Assembly.Get ExecutingAssembly().Location)
+ "\\tidy.exe");
_TidyProcessStartInfo.UseShellExecute = false;
_TidyProcessStartInfo.CreateNoWindow = true;
_TidyProcessStartInfo.RedirectStandardInput = true;
_TidyProcessStartInfo.RedirectStandardOutput = true;
_TidyProcessStartInfo.RedirectStandardError = true;
.. . .
Process process = new Process();
process.StartInfo = _TidyProcessStartInfo;
process.ErrorDataReceived += new
DataReceivedEventHandler(Exe_ErrorDataReceived);
bool started = process.Start();
if (started)
{
//process.StandardInput.AutoFlush = true;
process.StandardInput.WriteLine(input);
process.StandardInput.Flush();
process.StandardInput.Close();
ret = process.StandardOutput.ReadToEnd();
}

Thanks,
Jon

推荐答案

4月5日下午12:20,Jon Davis < j ... @ REMOVE.ME.PLEASE.jondavis.net>

写道:
On Apr 5, 12:20 pm, "Jon Davis" <j...@REMOVE.ME.PLEASE.jondavis.net>
wrote:

有谁知道为什么使用System。 Diagnostics.Process towrap控制台

应用程序并不总是传输I / O,具体取决于你试图消费的过程

?例如,PowerShell似乎不会通过Process对象处理任何I / O.


我知道在PowerShell的情况下有更好的包裹的方法

控制台直接与

System.Management.Automation或一些类似命名的命名空间的程序集连接,但我是

尝试为多种类型的进程使用通用命令行包装器

使用控制台I / O,而PowerShell是一个方便的例子,为什么这个
不能工作。


ProcessStartInfo psi =新的ProcessStartInfo(

@" C:\ Windows \ system32 \ WindowsPowerShell \ v1.0 \ power shell。 exe");

psi.Arguments =" -NoLogo";

psi.UseShellExecute = false;

psi.CreateNoWindow = true;

psi.RedirectStandardInput = true;

psi.RedirectStandardOutput = true;

//psi.RedirectStandardError = true;

处理流程=新流程();

process.StartInfo = psi;

bool started = process.Start();

if (已开始)

{

process.StandardInput.WriteLine (2 + 2);

process.StandardInput.Flush();

string ret = process.StandardOutput.ReadLine(); //< - 在这里停转

System.Console.WriteLine(" PowerShell说\2 + 2 =" + ret +" \"。");


}


另一个我试图包裹的是Dave的原始实现

Raggett的HTML Tidy。下面的内容有时会在ReadToEnd()上停顿。在我添加process.StandardInput.Close();之前,
似乎总是停滞不前。

" process.StandardInput.Flush();"但它仍然会在ReadToEnd()的一半时间内停止。


..

_TidyProcessStartInfo = new ProcessStartInfo(

Directory.GetParent(System.Reflection.Assembly.Get ExecutingAssembly()。Location)

+" \\tidy.exe");

_TidyProcessStartInfo.UseShellExecute = false;

_TidyProcessStartInfo.CreateNoWindow = true;

_TidyProcessStartInfo.RedirectStandardInput = true;

_TidyProcessStartInfo.RedirectStandardOutput = true;

_TidyProcessStartInfo.RedirectStandardError = true;

。 。 。

流程流程=新流程();

process.StartInfo = _TidyProcessStartInfo;

process.ErrorDataReceived + = new

DataReceivedEventHandler(Exe_ErrorDataReceived);

bool started = process.Start();

if(started)

{

//process.StandardInput.AutoFlush = true;

process.StandardInput.WriteLine(输入);

process.StandardInput.Flush();

process.StandardInput.Close();

ret = process.StandardOutput.ReadToEnd();


}


谢谢,

Jon
Does anyone know why using System.Diagnostics.Process to "wrap" a console
application does not always transmit the I/O, depending on what processes
you''re trying to "consume"? PowerShell, for example, does not seem to
process any I/O through the Process object.

I know that in the case of PowerShell there are better ways to "wrap" the
console by directly interfacing with the assemblies of
System.Management.Automation or some similarly named namespace, but I''m
trying to use generic command line wrappers for multiple types of processes
that use the console I/O, and PowerShell was a handy example of why this
won''t work.

ProcessStartInfo psi = new ProcessStartInfo(
@"C:\Windows\system32\WindowsPowerShell\v1.0\power shell.exe");
psi.Arguments = "-NoLogo";
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
//psi.RedirectStandardError = true;
Process process = new Process();
process.StartInfo = psi;
bool started = process.Start();
if (started)
{
process.StandardInput.WriteLine("2+2");
process.StandardInput.Flush();
string ret = process.StandardOutput.ReadLine(); // <-- stalls here
System.Console.WriteLine("PowerShell says \"2+2=" + ret + "\".");

}

Another one I was trying to "wrap" was the original implementation of Dave
Raggett''s HTML Tidy. The stuff below sometimes stalls on ReadToEnd(). It
seemed to always stall until I added "process.StandardInput.Close();" after
"process.StandardInput.Flush();" but it still stalls on ReadToEnd() half the
time.

..
_TidyProcessStartInfo = new ProcessStartInfo(
Directory.GetParent(System.Reflection.Assembly.Get ExecutingAssembly().Location)
+ "\\tidy.exe");
_TidyProcessStartInfo.UseShellExecute = false;
_TidyProcessStartInfo.CreateNoWindow = true;
_TidyProcessStartInfo.RedirectStandardInput = true;
_TidyProcessStartInfo.RedirectStandardOutput = true;
_TidyProcessStartInfo.RedirectStandardError = true;
. . .
Process process = new Process();
process.StartInfo = _TidyProcessStartInfo;
process.ErrorDataReceived += new
DataReceivedEventHandler(Exe_ErrorDataReceived);
bool started = process.Start();
if (started)
{
//process.StandardInput.AutoFlush = true;
process.StandardInput.WriteLine(input);
process.StandardInput.Flush();
process.StandardInput.Close();
ret = process.StandardOutput.ReadToEnd();

}

Thanks,
Jon



您可能在重定向时遇到死锁问题。有关详细信息,请参阅

RedirectStandardOutput属性上的文档:

http://msdn2.microsoft.com/en-us/lib...ardoutput.aspx


克里斯

You are probably hitting a deadlock issue when redirecting out. See
the docs on the RedirectStandardOutput property for more information:

http://msdn2.microsoft.com/en-us/lib...ardoutput.aspx

Chris




" Chris Dunaway" < du ****** @ gmail.com写信息

news:11 ********************** @ n59g2000hsh .googlegr oups.com ...

"Chris Dunaway" <du******@gmail.comwrote in message
news:11**********************@n59g2000hsh.googlegr oups.com...

您可能在重定向时遇到死锁问题。有关详细信息,请参阅

RedirectStandardOutput属性上的文档:

http://msdn2.microsoft.com/en-us/lib...ardoutput.aspx


Chris
You are probably hitting a deadlock issue when redirecting out. See
the docs on the RedirectStandardOutput property for more information:

http://msdn2.microsoft.com/en-us/lib...ardoutput.aspx

Chris



显然它是死锁,问题是我不知道如何应用任何

变通方法我在OP中提供的代码给出了

中提供的样本参考链接,虽然乍一看似乎很详细,但是b $ b实际上太简短而无用。 />

也许有人有时间和耐心使我的两个样本有效吗? :)


Jon

Clearly it is deadlocking, the problem is I don''t know how to apply any
workaround to the code I provided in the OP given the samples provided in
the referenced link, which although appears detailed at first glance is
really too brief to be useful.

Perhaps someone has the time and patience to make my two samples work? :)

Jon


2007年4月5日星期四13:24:44 -0700,Jon Davis

< jo*@REMOVE.ME.PLEASE.jondavis.netwrote:
On Thu, 05 Apr 2007 13:24:44 -0700, Jon Davis
<jo*@REMOVE.ME.PLEASE.jondavis.netwrote:

显然它是死锁,问题是我不知道怎么回事给我在OP中提供的代码应用任何

变通方法给出

中提供的样本参考链接,虽然乍一看似乎很详细是

真的太短暂无用了。


也许有人有时间和耐心使我的两个样本有效吗? :)
Clearly it is deadlocking, the problem is I don''t know how to apply any
workaround to the code I provided in the OP given the samples provided in
the referenced link, which although appears detailed at first glance is
really too brief to be useful.

Perhaps someone has the time and patience to make my two samples work? :)



我们大多数人可能没有你正在运行的相关程序

安装。我知道我不会。


那就是说,读到我发现的文件,你可能会因为处理问题而遇到问题。 StandardError流。

也就是说,我在代码中看不到任何可以从那个

流中读取的内容。根据文档,如果您自己的应用程序没有跟踪从流中读取数据,那么一旦流的缓冲区已满,子进程可能会阻止
。那会阻止你的孩子继续处理

,而你的父进程就在那里等待从另一个流中读取更多




如果你要重定向StandardError和StandardOutput,那么在我看来,唯一可靠的方法是确保两个

流都被读取从同时。您可以通过提供

来同步读取至少其中一个(即BeginOutputReadLine

和/或BeginErrorReadLine)。这样,你可以确保你总是从两者中读取b
并且不会阻止子进程继续进行
。或者,使用两个不同的线程来读取两个

流。


这两种技术都记录在备注的末尾附近。 MSDN中RedirectStandardOutput属性的
部分(你说的链接

太短暂而无用)。


Pete

Most of us probably don''t have the associated programs you''re running
installed. I know I don''t.

That said, reading the documentation it occurs to me that you may be
running into a problem with your processing of the StandardError stream.
That is, I don''t see anything in your code that would read from that
stream. According to the documentation, if your own application does not
keep up with reading data from the streams, the child process may block
once the stream''s buffer is full. That would prevent your child process
from continuing, while your parent process sits there waiting to read more
from the other stream.

If you are going to redirect both StandardError and StandardOutput, it
seems to me that the only robust way to do that is to ensure that both
streams are being read from simultaneously. You can do that by providing
for asychronous reading of at least one of them (ie BeginOutputReadLine
and/or BeginErrorReadLine). That way, you can ensure that you will always
be reading from both and not preventing the child process from
continuing. Alternatively, use two different threads to read from the two
streams.

Both of these techniques are documented near the end of the "Remarks"
section for the RedirectStandardOutput property in MSDN (the link you say
is "too brief to be useful").

Pete


这篇关于在System.Diagnostics.Process中包装命令shell的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆