【问题标题】:Run Process in Current Console在当前控制台中运行进程
【发布时间】:2013-07-19 17:12:59
【问题描述】:

我正在为 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;
}

【问题讨论】:

  • 尝试使用cmd.exe/c 选项。喜欢Process.Start("cmd.exe", "YOURAPP.exe /c");
  • @Anri 我不认为那是我需要的;我不想通过cmd.exe 运行它。
  • 通过 cmd 启动控制台应用程序几乎没有区别
  • 这个要求有点危险。这意味着另一个应用程序可能应该是您在程序中引用的 .dll,而不是另一个可执行程序。
  • @Servy 我正在编写一个有颜色的命令外壳。如果我从 shell 中键入“shell” ENTER,则子 shell 没有颜色。我想要它。但是,我不能为 shell 将运行的每个程序引用每个 .dll;有些程序甚至可能不是 .NET 程序...

标签: c# process console


【解决方案1】:

您需要创建一个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 为例进行说明。任何从标准输入读取的程序都可以工作。另请注意,控制台颜色可以正常工作。

【讨论】:

  • 我已经这样做了(也许我应该发布更多我的代码),并且子进程从不要求控制台输入。这不是答案:(
  • @feralin:你可能想试试我的例子。我不知道你做了什么,但我的样本做了你说你想做的事。
  • @feralin:您问:“我如何在当前控制台中运行一个进程,以便它可以设置控制台颜色并直接从控制台获取输入?”我的例子就是这样做的。
  • 你知道,你是对的。我可以发誓我早点尝试过,但我想我没有。我的错:(。你的答案是正确的。
  • 另请注意 CreateNoWindow=false 的(隐式)默认值与 OP 代码中的显式 true 。答案的宝石在这里。
【解决方案2】:

Jim Mischel 的回答很有魅力。我正在将一些批处理文件处理移动到 C# 中,效果很好。您可能会发现这个小实用方法很方便。只需一个命令行,并像在批处理文件中调用 CALL 一样运行它。只需将其填充到实用程序类中即可:

public static void RunCmd(string command) {
    Process.Start(new ProcessStartInfo("cmd.exe", "/c " + command) {
        UseShellExecute = false
    }).WaitForExit();            
}    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-13
    • 2011-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多