在当前控制台中运行进程
本文关键字:运行 进程 控制台 | 更新日期: 2023-09-27 18:24:01
我正在为Windows编写一个基本的shell,我想知道是否有任何方法可以运行子进程(Process process
),使其使用当前控制台窗口。我的意思是我不想重定向输入/输出;我希望进程从当前控制台获取输入,并将输出直接打印到同一控制台窗口。
原因是我希望允许此子流程为输出设置控制台颜色,如果我重定向流程的标准输出,则无法实现这一点。此外,我目前使用的代码
while (!process.HasExited)
process.StandardInput.WriteLine(Console.ReadLine());
以将标准输入重定向到进程。但是,如果进程在输入后立即退出(例如,我键入"exit"+ENTER,进程退出),则此循环将再次运行,因此控制台正在等待用户的输入,而该用户永远不会被进程使用(它即将退出)。
那么,长话短说,我如何在当前控制台中运行进程,以便它可以设置控制台颜色并直接从控制台获取输入?
编辑:以下是我的代码中与此问题相关的方法:
static int runExe(string exePath, params string[] args)
{
ProcessStartInfo startInfo = new ProcessStartInfo(exePath, args)
{
ErrorDialog = false,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true
};
Process process = new Process() { StartInfo = startInfo };
process.Start();
ReadThreadState stdout = readThread(process.StandardOutput, false);
ReadThreadState stderr = readThread(process.StandardError, true);
while (!process.HasExited)
process.StandardInput.WriteLine(Console.ReadLine());
stdout.stop = stderr.stop = true;
return process.ExitCode;
}
class ReadThreadState
{
public bool stop;
}
private static ReadThreadState readThread(StreamReader reader, bool isError)
{
ReadThreadState state = new ReadThreadState();
new Thread(() =>
{
while (!state.stop)
{
int current;
while ((current = reader.Read()) >= 0)
if (isError)
writeError(((char)current).ToString(), ConsoleColor.Red);
else
Console.Write((char)current);
}
}).Start();
return state;
}
您需要创建一个ProcessStartInfo
并将UseShellExecute
设置为false
:
var info = new ProcessStartInfo("program.exe", "arguments");
info.UseShellExecute = false;
var proc = Process.Start(info);
proc.WaitForExit();
这将在同一控制台中启动您的程序。
使用上述技术的工作程序:
private static void Main(string[] args)
{
Console.WriteLine("Starting program");
var saveColor = Console.BackgroundColor;
Console.BackgroundColor = ConsoleColor.Blue;
var info = new ProcessStartInfo("cmd", "/c time");
info.UseShellExecute = false;
var proc = Process.Start(info);
proc.WaitForExit();
Console.BackgroundColor = saveColor;
Console.WriteLine("Program exited");
Console.ReadLine();
}
运行该程序时,它会启动cmd.exe的新副本,并运行time命令,该命令要求输入。我只是用cmd.exe作为例子来说明。任何从标准输入读取的程序都可以工作。还要注意,控制台颜色工作正常。
Jim Mischel的回答就像一个符咒。我正在将一些批处理文件转移到C#中,这非常有效。你可能会发现这个小实用方法很方便。只需使用一个命令行,并像在批处理文件中运行CALL一样运行它。只需将其放入实用程序类:
public static void RunCmd(string command) {
Process.Start(new ProcessStartInfo("cmd.exe", "/c " + command) {
UseShellExecute = false
}).WaitForExit();
}