【问题标题】:Create a cmd window and write to it from C# application创建一个 cmd 窗口并从 C# 应用程序写入它
【发布时间】:2017-08-16 05:30:13
【问题描述】:

我正在为 Grasshopper for Rhino 开发一个 C# 组件。由于我正在运行一些非常繁重的迭代分析,因此我想将结果连续输出到 cmd 窗口,以确保分析实际正在运行。

这是我尝试过的:

using System.Diagnostics;


Result results = new Result();
Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.CreateNoWindow = false;
cmd.StartInfo.UseShellExecute = false;
cmd.Start();

do {
    results = RunHeavyOperation(results);
    cmd.StandardInput.WriteLine("echo " + results.usefulInfo);
} while (!results.conditionForEnd);

cmd.WaitForExit();

Result RunHeavyOperation(Result previousResults) {
    Result res = doHeavyStuff(previousResults);
    return res;
}

我意识到我遗漏了一部分,但那是什么?

【问题讨论】:

  • 为了记录,我暂时使用System.Diagnostics.Debug.Write(results.usefulInformation);解决了这个问题,但是如果应用程序进入生产状态,这将不起作用。

标签: c# cmd stdout stdin


【解决方案1】:

在 Visual Studio 中创建控制台应用程序。在 VS 2017 中,它看起来像这样(在起始页上):

控制台应用程序会自动打开命令控制台。然后你可以写给它

Console.WriteLine("hello");

程序终止时控制台会自动关闭。因此,如果您想保持打开状态,请务必在最后致电 Console.ReadKey();

【讨论】:

  • 这一切都很好,但该应用程序已经深入开发 - 将现有应用程序迁移到控制台应用程序是否容易?
  • 这取决于您是否已经制作了 WinForms 或 WPF 应用程序并已经创建了 UI,或者您是否只编写了业务逻辑。在后一种情况下,您将无需进行任何转换。当然,应用程序不能同时是控制台和 WinForms 或 WPF 应用程序。
【解决方案2】:

您的方法是错误的:您目前没有写入控制台窗口。相反,您通过启动cmd.exe 创建了一个进程并写入该进程的标准输入管道cmd.exe 不知道这一点。这与通过键盘在控制台中输入不同,甚至会产生奇怪的效果。
假设您输出了一个换行符,因此cmd.exe 可能会尝试“执行”您之前作为命令输出的内容。

正确的方法是调用AllocConsole。通过这个调用,您可以为您的进程创建一个控制台窗口,并通过Console.WriteLine() 简单地使用它。

完成工作和记录后,您最终需要通过FreeConsole 再次关闭并释放此控制台。

所以导入这两个原生方法:

internal sealed class NativeMethods
{
    [DllImport("kernel32.dll")]
    public static extern bool AllocConsole();

    [DllImport("kernel32.dll")]
    public static extern bool FreeConsole();
}

并在您的代码中使用它们:

NativeMethods.AllocConsole();

// start work
Console.WriteLine("log messages...");

// finished work

NativeMethods.FreeConsole();

请注意,FreeConsole()关闭控制台窗口,因此您的所有日志消息都会丢失。而且控制台只有这么大的缓冲区,如果离开缓冲区,您将无法滚动回旧消息。

因此,最好将日志消息简单地写入一个文件,以便以后进行分析。

【讨论】:

  • 是的,这就是我要找的。谢谢!
  • 我可以在 winforms 应用程序中执行此操作吗?我可以打开控制台,但没有写入任何内容!
  • @OlivierJacot-Descombes 是的,你可以,我刚刚再次测试了它,它对我有用。
  • 我必须使用来自this 答案的代码才能使其工作。但是当从 VS 2017 中启动应用程序时,输出仍然重定向到调试输出窗口。它仅在从 VS 外部启动应用程序时才有效。
  • @OlivierJacot-Descombes 它适用于我在 VS2017 中。您是否从附加的调试器开始?然后当然它不会工作,因为已经有一种控制台(调试器)。由于 OP 希望它在生产中工作,我认为我的代码没问题。如果你不调试就开始工作。
猜你喜欢
  • 2019-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-11
  • 1970-01-01
相关资源
最近更新 更多