对于我实现的一个我的工作是应该从cmd窗口发送/检索命令/结果/工具。 一切工作正常,但低于使用情况下不能做任何事情。 看来,如果我的应用程序在等待着什么(而不是显示的结果)
从我的工具,我浏览到蟒蛇文件夹。 从Python的文件夹我尝试启动python.exe,但在这一点上,我的编辑并不做任何事情。 它只是不断的等待。
为了您的关照,我也在这里连接视频。 它会更容易为你们明白我想说的。
查看视频在这里(在YouTube上)
我还附上我目前拥有的代码。
ProcessStartInfo info = new ProcessStartInfo("cmd.exe");
string argument = null;
if (!string.IsNullOrEmpty(startingDirectory) && System.IO.Directory.Exists(startingDirectory))
{
argument += @"cd\";
}
else
{
argument += "\"";
}
info.Arguments = argument;
info.CreateNoWindow = true;
info.RedirectStandardError = true;
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
this.shellProcess = System.Diagnostics.Process.Start(info);
this.shellProcess.EnableRaisingEvents = true;
//this.InputStream.AutoFlush = true;
this.shellProcess.Exited += new EventHandler(ProcessExited);
this.ErrorBeginRead();
this.OutputBeginRead();
private void OutputBeginRead()
{
this.shellProcess.StandardOutput.BaseStream.BeginRead(outputBuffer, 0, outputBuffer.Length, new AsyncCallback(this.OnOutputInput), this.shellProcess);
}
private void ErrorBeginRead()
{
this.shellProcess.StandardError.BaseStream.BeginRead(errorBuffer, 0, errorBuffer.Length, new AsyncCallback(this.OnErrorInput), this.shellProcess);
}
谢谢 !
编辑:启动蟒蛇只是一个例子。 我需要使用其他正常的CMD命令行作为well.It将是很好,如果有人能指出我在做什么错我还是什么我必须做的代码,从而实现预期功能的方法相同。
编辑2:正常CMD命令完美的工作。 命令行工具,像Python,Perl不工作。
编辑3:所以我设法做移动一丁点向前以下杰米的建议。 用户界面是不是“挂”了。 但是当我访问Python解释器,解释器的输出仍然不是我的工具可见。 任何建议,为什么会是这样吗?
你不能命令发送到外壳这种方式。 在info.Arguments的字符串是提供给该程序的命令行上的参数。 如果你想在cmd.exe shell中执行一系列命令,然后退出,你将不得不提供/ C参数。 如果你有你想要执行你要么必须把命令在批处理文件并执行或它们括在引号,并与&&,即分隔多个命令info.Arguments = @"/c ""cd \ && dir""";
。 你的另一个问题从来没有返回时,为它没有任何执行,或者适当的,论点cmd.exe,在默认情况下的互动模式打开。 / c选项告诉cmd.exe执行相关命令,然后退出。
此外,像Python和Perl解释器有时当从直接的ProcessStartInfo推出的怪异行为。 如果info.Arguments = @"""MyPerlProgram.pl""";
与perl.exe所在不起作用,你可能会发现有必要启动它们内部的cmd.exe得到正常行为了出来,即info.Arguments = @"/c ""perl.exe ""MyPerlProgram.pl""""";
。
见Cmd的和ProcessStartInfo.Arguments财产 。
要回答你的编辑3的问题,你可能没有正确挂接到输出。 而不是试图钩住的StreamReader的BaseStream,钩与OutputDataReceived事件this.shellProcess.OutputDataReceived += ProcessOutputHandler;
你叫的地方开始ProcessOutputHandler具有类似签名之前public static void ProcessOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
。 呼叫后,立即启动,调用this.shellProcess.BeginOutputReadLine();
。 这个过程是为错误输出中,以及类似的。 见Process.BeginOutputReadLine方法和Process.BeginErrorReadLine方法的更多细节。
如果仍然有问题,你得到了什么,如果你只是尝试process.StartInfo.Arguments = @"/c ""python.exe -c ""import sys; print 'Test.';""""";
?
此外,下面的代码演示了大部分的壳连通的必要的概念:
public static void Main()
{
using (Process process = new Process())
{
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.WorkingDirectory = @"C:\";
process.StartInfo.FileName = Path.Combine(Environment.SystemDirectory, "cmd.exe");
// Redirects the standard input so that commands can be sent to the shell.
process.StartInfo.RedirectStandardInput = true;
// Runs the specified command and exits the shell immediately.
//process.StartInfo.Arguments = @"/c ""dir""";
process.OutputDataReceived += ProcessOutputDataHandler;
process.ErrorDataReceived += ProcessErrorDataHandler;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
// Send a directory command and an exit command to the shell
process.StandardInput.WriteLine("dir");
process.StandardInput.WriteLine("exit");
process.WaitForExit();
}
}
public static void ProcessOutputDataHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
Console.WriteLine(outLine.Data);
}
public static void ProcessErrorDataHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
Console.WriteLine(outLine.Data);
}
您可能导致您的问题线程问题。 我已经做了一些这方面的进一步工作,并能得到一个文本框在窗体上用下面的代码更新:
using System;
using System.Diagnostics;
using System.IO;
using System.Timers;
namespace DummyFormsApplication
{
class ProcessLauncher : IDisposable
{
private Form1 form;
private Process process;
private bool running;
public bool InteractiveMode
{
get;
private set;
}
public ProcessLauncher(Form1 form)
{
this.form = form;
process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.WorkingDirectory = @"C:\";
process.StartInfo.FileName = Path.Combine(Environment.SystemDirectory, "cmd.exe");
// Redirects the standard input so that commands can be sent to the shell.
process.StartInfo.RedirectStandardInput = true;
process.OutputDataReceived +=new DataReceivedEventHandler(process_OutputDataReceived);
process.ErrorDataReceived += new DataReceivedEventHandler(process_ErrorDataReceived);
process.Exited += new EventHandler(process_Exited);
}
public void Start()
{
if (running == false)
{
running = true;
InteractiveMode = true;
// Runs the specified command and exits the shell immediately upon completion.
process.StartInfo.Arguments = @"/c ""C:\python27\python.exe -i""";
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
}
}
public void Start(string scriptFileName)
{
if (running == false)
{
running = true;
InteractiveMode = false;
// Runs the specified command and exits the shell immediately upon completion.
process.StartInfo.Arguments = string.Format(@"/c ""C:\python27\python.exe ""{0}""""", scriptFileName);
}
}
public void Abort()
{
process.Kill();
}
public void SendInput(string input)
{
process.StandardInput.Write(input);
process.StandardInput.Flush();
}
private void process_OutputDataReceived(object sendingProcess, DataReceivedEventArgs outLine)
{
if (outLine.Data != null)
{
form.Invoke(form.appendConsoleTextDelegate, new object[] { outLine.Data });
}
}
private void process_ErrorDataReceived(object sendingProcess, DataReceivedEventArgs outLine)
{
if (outLine.Data != null)
{
form.Invoke(form.appendConsoleTextDelegate, new object[] { outLine.Data });
}
}
private void process_Exited(object sender, EventArgs e)
{
running = false;
}
public void Dispose()
{
if (process != null)
{
process.Dispose();
}
}
}
}
我创建了一个表格,并添加一个文本框,并在表格下面的代码:
public delegate void AppendConsoleText(string text);
public AppendConsoleText appendConsoleTextDelegate;
private void Form1_Load(object sender, EventArgs e)
{
appendConsoleTextDelegate = new AppendConsoleText(textBox1_AppendConsoleText);
using (ProcessLauncher launcher = new ProcessLauncher(this))
{
launcher.Start();
launcher.SendInput("import sys;\n");
launcher.SendInput("print \"Test.\";\n");
launcher.SendInput("exit()\n");
}
}
private void textBox1_AppendConsoleText(string text)
{
textBox1.AppendText(string.Format("{0}\r\n", text));
}
有一点需要注意的是,如果Form1_Load事件未完成,调用将挂起,直到它。 如果您在事件长期运行的代码,你要么需要异步调用使用的BeginInvoke,或定期调用的DoEvents在长时间运行的代码。
编辑
根据您的意见,我已经修改了代码互动提交工作。 然而,有,有问题。 Python提示符( >>>
)被设置在输出StandardError的并且它不呼应StandardInput。 它也不会终止该行。 这使得检测提示困难,并导致一些出提示字符的顺序输出的由于process_ErrorDataReceived未击发,直到该过程结束或行结束看出。
有没有足够的代码在你的问题要弄清楚到底是什么你的应用程序挂。 有你的代码中的一些事情看起来很奇怪。 例如,为什么你开始自己的错误,并输出读取循环,而不是使用内置的Process类的人? 像这样:
var shellProcess = System.Diagnostics.Process.Start(info);
shellProcess.EnableRaisingEvents = true;
shellProcess.Exited += ProcessExited;
shellProcess.OutputDataReceived += ShellProcess_OutputDataReceived;
shellProcess.ErrorDataReceived += ShellProcess_ErrorDataReceived;
shellProcess.BeginOutputReadLine();
shellProcess.BeginErrorReadLine();
void ShellProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
// Do Something
}
void ShellProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
// Do Something
}
由于您的错误和输出异步事件不烧,这使我相信,有可能是一辈子的问题与shellProcess。 如果您发布更多的代码,我们可以提供更好的指导。
我不能看到所有的代码,但是你可以很容易地使用蒸汽对象写/命令发送到您创建的 CMD窗口。 例如:
StreamWriter inputStream = shellProcess.StandardInput;
//send command to cmd prompt and wait for command to execute with thread sleep
inputStream.WriteLine("echo "CMD just received input");
inputStream.Flush();
在比如上面的例子中,命令提示符将收到echo
,就像它在窗口中输入命令。 为了显示输出,你必须创建StreamReader
对象,并将其分配给进程的StandardOutput
。