这里的例子都是有用的,但并不能完全满足我的使用情况。我不想调用该命令并退出。我想打开命令提示符,发送输入,读取输出,然后重复。这是我的解决方案。
创建Utils.CmdManager.cs
using System;
using System.Diagnostics;
using System.Text;
using System.Threading;
namespace Utils
{
public class CmdManager : IDisposable
{
const int DEFAULT_WAIT_CHECK_TIME = 100;
const int DEFAULT_COMMAND_TIMEOUT = 3000;
public int WaitTime { get; set; }
public int CommandTimeout { get; set; }
Process _process;
StringBuilder output;
public CmdManager() : this("cmd.exe", null, null) { }
public CmdManager(string filename) : this(filename, null, null) { }
public CmdManager(string filename, string arguments) : this(filename, arguments, null) { }
public CmdManager(string filename, string arguments, string verb)
{
WaitTime = DEFAULT_WAIT_CHECK_TIME;
CommandTimeout = DEFAULT_COMMAND_TIMEOUT;
output = new StringBuilder();
_process = new Process();
_process.StartInfo.FileName = filename;
_process.StartInfo.RedirectStandardInput = true;
_process.StartInfo.RedirectStandardOutput = true;
_process.StartInfo.RedirectStandardError = true;
_process.StartInfo.CreateNoWindow = true;
_process.StartInfo.UseShellExecute = false;
_process.StartInfo.ErrorDialog = false;
_process.StartInfo.Arguments = arguments != null ? arguments : null;
_process.StartInfo.Verb = verb != null ? verb : null;
_process.EnableRaisingEvents = true;
_process.OutputDataReceived += (s, e) =>
{
lock (output)
{
output.AppendLine(e.Data);
};
};
_process.ErrorDataReceived += (s, e) =>
{
lock (output)
{
output.AppendLine(e.Data);
};
};
_process.Start();
_process.BeginOutputReadLine();
_process.BeginErrorReadLine();
_process.StandardInput.AutoFlush = true;
}
public void RunCommand(string command)
{
_process.StandardInput.WriteLine(command);
}
public string GetOutput()
{
return GetOutput(null, CommandTimeout, WaitTime);
}
public string GetOutput(string endingOutput)
{
return GetOutput(endingOutput, CommandTimeout, WaitTime);
}
public string GetOutput(string endingOutput, int commandTimeout)
{
return GetOutput(endingOutput, commandTimeout, WaitTime);
}
public string GetOutput(string endingOutput, int commandTimeout, int waitTime)
{
string tempOutput = "";
int tempOutputLength = 0;
int amountOfTimeSlept = 0;
// Loop until
// a) command timeout is reached
// b) some output is seen
while (output.ToString() == "")
{
if (amountOfTimeSlept >= commandTimeout)
{
break;
}
Thread.Sleep(waitTime);
amountOfTimeSlept += waitTime;
}
// Loop until:
// a) command timeout is reached
// b) endingOutput is found
// c) OR endingOutput is null and there is no new output for at least waitTime
while (amountOfTimeSlept < commandTimeout)
{
if (endingOutput != null && output.ToString().Contains(endingOutput))
{
break;
}
else if(endingOutput == null && tempOutputLength == output.ToString().Length)
{
break;
}
tempOutputLength = output.ToString().Length;
Thread.Sleep(waitTime);
amountOfTimeSlept += waitTime;
}
// Return the output and clear the buffer
lock (output)
{
tempOutput = output.ToString();
output.Clear();
return tempOutput.TrimEnd();
}
}
public void Dispose()
{
_process.Kill();
}
}
}
然后从PowerShell中添加的类别,并使用它。
Add-Type -Path ".\Utils.CmdManager.cs"
$cmd = new-object Utils.CmdManager
$cmd.GetOutput() | Out-Null
$cmd.RunCommand("whoami")
$cmd.GetOutput()
$cmd.RunCommand("cd")
$cmd.GetOutput()
$cmd.RunCommand("dir")
$cmd.GetOutput()
$cmd.RunCommand("cd Desktop")
$cmd.GetOutput()
$cmd.RunCommand("cd")
$cmd.GetOutput()
$cmd.RunCommand("dir")
$cmd.GetOutput()
$cmd.Dispose()
不要忘记调用Dispose()
功能在最后清理是在后台运行的进程。或者,您可以通过运行如$cmd.RunCommand("exit")
来关闭该过程。不幸的是,运行此代码后,我没有得到任何stdout或stderr。 – Ci3
@ChrisHarris重新测试(在PS 2.0中),它对我有用。你有什么异常吗?当你直接运行相同的命令时,你会得到任何输出吗? –
我得到StdOut,StdErr的空值返回的对象。退出码是“0”。我在等待ping.exe的输出,包括回复,字节,时间等。是吗?我完全按照你在这里的速度跑它。我正在运行Powershell 4.嗯,只是在Powershell 2上运行它,它按预期工作! – Ci3