如何捕获过程的输出(从OR Tools解算器中)并通过控制台显示它

时间:2019-08-31 16:31:07

标签: c# or-tools

我有一个C#winform应用程序,其中的优化模型由OR-Tools解决。优化求解器具有将整个优化过程作为stdout发送的功能。

    Slvr.EnableOutput();
    Solver.ResultStatus restatus = Slvr.Solve(); 

但是,求解器不会自动打开控制台。 目前,我所做的是:

项目属性->应用程序->输出类型->控制台应用程序

,控制台从应用程序开始到运行结束都准备就绪。因此,该过程标准输出将自动显示。

我想要的是在运行以上代码的时候完全打开控制台,并显示求解器的标准输出。然后等待用户输入键以关闭控制台,然后继续执行主应用程序。

2 个答案:

答案 0 :(得分:1)

我想您的问题是您正在尝试在GUI进程内将求解程序作为Winforms应用程序的一部分运行吗?但是Console输出通常在Winforms应用程序中被禁用。您基本上有两种选择:

  • 使用this older SO answer中所述的选项之一将控制台窗口附加到Winforms应用程序中

  • 将应用程序分成两个exe文件:一个运行求解器的命令行程序,以及一个仅包含UI的Winforms部分。然后使用System.Diagnostics.Process.Start作为单独的进程运行命令行部分,从而可以对输出重定向进行细粒度的控制。您可能需要UI将参数传递给命令行程序,例如通过使用临时文件。

第二个选项的工作量更多,特别是对于GUI和命令行工具之间的通信,但是可以以不阻塞GUI的方式实现,并且更容易解决求解器部分中的错误/程序崩溃,并且更健壮。如果您想引入并行化/一次运行多个求解器过程,通常性能会更好。

答案 1 :(得分:1)

Doc Brown 已经回答了您的问题,我添加这个只是为了提供一些我们在这里实现它的代码——这正是他的建议。我们有一个单独的 testPlugin.exe,从这里开始。通信是通过在文件系统上读取和写入的文件进行的。控制台输出在“输出处理程序”中被捕获

using System;
using System.Diagnostics;
using System.IO;

...

        private void startTest()
        {
            int result = 2;
            setFormStatus("working...");   // My method to inform the user with the form to wait.

            getFormData();  // My method to get the data from the form

            string errorMessage = null;
            System.Diagnostics.Process testPlugInProcess = new System.Diagnostics.Process();
            try
            {
                using (testPlugInProcess)
                {
                    testPlugInProcess.StartInfo.UseShellExecute = false;
                    testPlugInProcess.StartInfo.FileName = System.IO.Path.Combine(assemblyDirectory, TestPlugInExe); // The name of the exe file
                    testPlugInProcess.StartInfo.CreateNoWindow = false;
                    testPlugInProcess.StartInfo.Arguments = getModelTestCommandLineArgs(); // My method to create the command line arguments
                    testPlugInProcess.StartInfo.RedirectStandardError = true;
                    testPlugInProcess.StartInfo.RedirectStandardOutput = true;
                    testPlugInProcess.OutputDataReceived += pluginTestOutputHandler;
                    testPlugInProcess.ErrorDataReceived += pluginTestOutputHandler;
                    testPlugInProcess.Start();
                    testPlugInProcess.BeginErrorReadLine();
                    testPlugInProcess.BeginOutputReadLine();
                    testPlugInProcess.WaitForExit();
                    result = testPlugInProcess.ExitCode;
                }
                setFormStatus("");
            }
            catch (Exception ex)
            {
                errorMessage = ex.Message;
            }
            testPlugInProcess = null;
        }

控制台和错误输出在这里写入同一个文件,但您可以将它们分开。

插件处理程序如下所示:

        private static void pluginTestOutputHandler(object sendingProcess,
           DataReceivedEventArgs outLine)
        {
            if (!String.IsNullOrEmpty(outLine.Data))
            {
                for (int i = 0; i < numberOfTriesForWriting; i++) 
                {
                    try
                    {
                        using (StreamWriter sw = File.AppendText(lastPlugInTestTraceFilePath)) // The file name where the data is written.
                        {
                            sw.WriteLine(outLine.Data);
                            sw.Flush();
                            return;
                        }
                    }
                    catch (IOException)
                    {
                        System.Threading.Thread.Sleep(msToWaitBetweenTries);
                    } 
                }
            }
        }