在 C# 中的 CMD 中确定命令是否已执行完毕
Determine if a command has been finished executing in CMD in C#
简介
我正在使用 TCP 客户端-服务器配置在 c# 中创建一个 R.A.T(远程管理工具)。
一切都很顺利,直到我意识到需要检测命令是否已在我的 C# 应用程序创建的命令提示符进程中完成执行。
请看下面的代码。
private static Process CMDProc = null;
private static StreamWriter ToCMDShell = null;
public static void StartCMD()
{
ProcessStartInfo PSInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
CMDProc = new Process { StartInfo = PSInfo };
CMDProc.Start();
ToCMDShell = CMDProc.StandardInput;
ToCMDShell.AutoFlush = true;
CMDProc.BeginOutputReadLine();
CMDProc.BeginErrorReadLine();
CMDProc.OutputDataReceived += (s, e) => { /*Do something with e.Data*/ };
CMDProc.ErrorDataReceived += (s, e) => { /*Do something with e.Data*/ };
ToCMDShell.WriteLineAsync("ping 8.8.8.8"); //Execute a long running command in cmd terminal.
}
我想要实现的目标
您可能猜到 ping 命令需要不同的时间才能完成,具体取决于互联网连接的速度,现在我想要的是 运行 一个名为 CMDCommandExecuted()
的方法,当长时间运行像“ping”这样的 ning 命令在使用 c# 代码调用的终端中完成执行 ToCMDShell.WriteLineAsync("any dos command to execute");
。
到目前为止我尝试了什么
我试图从 CMDProc.OutputDataReceived
事件处理程序接收到的输出流中读取 e.Data
但没有成功,因为可能是其他一些长 运行ning 命令而不是ping 根本没有数据写入输出流,因此它不是防弹解决方案。
是的,我也曾尝试在互联网上搜索我的解决方案,但没有成功!
这就是为什么我在这里寻求您的帮助。
使用CMDProc.WaitForExit()
等待完成,CMDProc.ExitCode
获取最终状态码。
如果您从流中获得一些数据表明进程已挂起、冻结或需要终止,请调用 CMDProc.Kill()
。
如果您从流中获得一些数据表明您应该做其他事情,您可以生成其他进程或向该进程发送额外的 WriteLine
调用以进行进一步处理。
以下程序将 ping 命令输出正确发送回给我。也许您只需要等待命令或控制台读取行来给它时间。
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace MyNamespace
{
class Program
{
private static Process CMDProc = null;
private static StreamWriter ToCMDShell = null;
public static void Main()
{
StartCMD();
}
public static void StartCMD()
{
ProcessStartInfo PSInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
CMDProc = new Process { StartInfo = PSInfo };
CMDProc.Start();
ToCMDShell = CMDProc.StandardInput;
ToCMDShell.AutoFlush = true;
CMDProc.BeginOutputReadLine();
CMDProc.BeginErrorReadLine();
CMDProc.OutputDataReceived += (s, e) =>
{
Console.WriteLine("PROC: {0}", e.Data);
if (e.Data != null && e.Data.Contains("Average ="))
{
// last line, you don't have to exit here, you could do something else instead...
ToCMDShell.WriteLine("exit");
}
};
CMDProc.ErrorDataReceived += (s, e) => Console.WriteLine("PROC ERR: {0}", e.Data);
ToCMDShell.WriteLine("ping 8.8.8.8"); //Execute a long running command in cmd terminal.
CMDProc.WaitForExit();
Console.WriteLine("Job done, press ENTER to quit");
Console.ReadLine();
}
}
}
看起来 WriteLineAsync
直到长 运行 命令完成后才完成(例如,命令 window 已准备好接受新输入),因此您只需要 Wait
on the return from WriteLineAsync
当你需要发送更多的数据,或者知道之前的命令已经完成。
private static Process CMDProc = null;
private static StreamWriter ToCMDShell = null;
public static void StartCMD() {
ProcessStartInfo PSInfo = new ProcessStartInfo {
FileName = "cmd.exe",
Arguments = "/k",
CreateNoWindow = false,
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
CMDProc = new Process { StartInfo = PSInfo };
CMDProc.Start();
ToCMDShell = CMDProc.StandardInput;
ToCMDShell.AutoFlush = true;
CMDProc.BeginOutputReadLine();
CMDProc.BeginErrorReadLine();
CMDProc.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
CMDProc.ErrorDataReceived += (s, e) => Console.WriteLine($"ERR: {e.Data}");
var run = ToCMDShell.WriteLineAsync("ping 8.8.8.8"); //Execute a long running command in cmd terminal.
// do some stuff
run.Wait(); // wait for long command to complete
ToCMDShell.WriteLine("exit"); //Done
}
简介
我正在使用 TCP 客户端-服务器配置在 c# 中创建一个 R.A.T(远程管理工具)。 一切都很顺利,直到我意识到需要检测命令是否已在我的 C# 应用程序创建的命令提示符进程中完成执行。 请看下面的代码。
private static Process CMDProc = null;
private static StreamWriter ToCMDShell = null;
public static void StartCMD()
{
ProcessStartInfo PSInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
CMDProc = new Process { StartInfo = PSInfo };
CMDProc.Start();
ToCMDShell = CMDProc.StandardInput;
ToCMDShell.AutoFlush = true;
CMDProc.BeginOutputReadLine();
CMDProc.BeginErrorReadLine();
CMDProc.OutputDataReceived += (s, e) => { /*Do something with e.Data*/ };
CMDProc.ErrorDataReceived += (s, e) => { /*Do something with e.Data*/ };
ToCMDShell.WriteLineAsync("ping 8.8.8.8"); //Execute a long running command in cmd terminal.
}
我想要实现的目标
您可能猜到 ping 命令需要不同的时间才能完成,具体取决于互联网连接的速度,现在我想要的是 运行 一个名为 CMDCommandExecuted()
的方法,当长时间运行像“ping”这样的 ning 命令在使用 c# 代码调用的终端中完成执行 ToCMDShell.WriteLineAsync("any dos command to execute");
。
到目前为止我尝试了什么
我试图从 CMDProc.OutputDataReceived
事件处理程序接收到的输出流中读取 e.Data
但没有成功,因为可能是其他一些长 运行ning 命令而不是ping 根本没有数据写入输出流,因此它不是防弹解决方案。
是的,我也曾尝试在互联网上搜索我的解决方案,但没有成功!
这就是为什么我在这里寻求您的帮助。
使用CMDProc.WaitForExit()
等待完成,CMDProc.ExitCode
获取最终状态码。
如果您从流中获得一些数据表明进程已挂起、冻结或需要终止,请调用 CMDProc.Kill()
。
如果您从流中获得一些数据表明您应该做其他事情,您可以生成其他进程或向该进程发送额外的 WriteLine
调用以进行进一步处理。
以下程序将 ping 命令输出正确发送回给我。也许您只需要等待命令或控制台读取行来给它时间。
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace MyNamespace
{
class Program
{
private static Process CMDProc = null;
private static StreamWriter ToCMDShell = null;
public static void Main()
{
StartCMD();
}
public static void StartCMD()
{
ProcessStartInfo PSInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
CMDProc = new Process { StartInfo = PSInfo };
CMDProc.Start();
ToCMDShell = CMDProc.StandardInput;
ToCMDShell.AutoFlush = true;
CMDProc.BeginOutputReadLine();
CMDProc.BeginErrorReadLine();
CMDProc.OutputDataReceived += (s, e) =>
{
Console.WriteLine("PROC: {0}", e.Data);
if (e.Data != null && e.Data.Contains("Average ="))
{
// last line, you don't have to exit here, you could do something else instead...
ToCMDShell.WriteLine("exit");
}
};
CMDProc.ErrorDataReceived += (s, e) => Console.WriteLine("PROC ERR: {0}", e.Data);
ToCMDShell.WriteLine("ping 8.8.8.8"); //Execute a long running command in cmd terminal.
CMDProc.WaitForExit();
Console.WriteLine("Job done, press ENTER to quit");
Console.ReadLine();
}
}
}
看起来 WriteLineAsync
直到长 运行 命令完成后才完成(例如,命令 window 已准备好接受新输入),因此您只需要 Wait
on the return from WriteLineAsync
当你需要发送更多的数据,或者知道之前的命令已经完成。
private static Process CMDProc = null;
private static StreamWriter ToCMDShell = null;
public static void StartCMD() {
ProcessStartInfo PSInfo = new ProcessStartInfo {
FileName = "cmd.exe",
Arguments = "/k",
CreateNoWindow = false,
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
CMDProc = new Process { StartInfo = PSInfo };
CMDProc.Start();
ToCMDShell = CMDProc.StandardInput;
ToCMDShell.AutoFlush = true;
CMDProc.BeginOutputReadLine();
CMDProc.BeginErrorReadLine();
CMDProc.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
CMDProc.ErrorDataReceived += (s, e) => Console.WriteLine($"ERR: {e.Data}");
var run = ToCMDShell.WriteLineAsync("ping 8.8.8.8"); //Execute a long running command in cmd terminal.
// do some stuff
run.Wait(); // wait for long command to complete
ToCMDShell.WriteLine("exit"); //Done
}