Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在没有';useshellexecute=false';_C#_Input_Process_Output_Invoke - Fatal编程技术网

C# 如何在没有';useshellexecute=false';

C# 如何在没有';useshellexecute=false';,c#,input,process,output,invoke,C#,Input,Process,Output,Invoke,我到处找了,但就是找不到正确的答案 我使用VS2013>C#>Windows窗体应用程序 下面是我的流程的工作版本。 但我有两个小问题,我不知道如何解决 *.exe是一种优化算法,它显示它所做的每一次迭代以及它找到的当前最佳解决方案。 ->但是因为我有'useshellexecute=false',所以在命令shell中看不到任何内容 用户可以随时按“Ctrl+C”中断算法,算法将停止并返回当前最佳解决方案 ->但是因为我有'useshellexecute=false',所以我不能输入任何关键命

我到处找了,但就是找不到正确的答案

我使用VS2013>C#>Windows窗体应用程序

下面是我的流程的工作版本。 但我有两个小问题,我不知道如何解决

  • *.exe是一种优化算法,它显示它所做的每一次迭代以及它找到的当前最佳解决方案。 ->但是因为我有'useshellexecute=false',所以在命令shell中看不到任何内容

  • 用户可以随时按“Ctrl+C”中断算法,算法将停止并返回当前最佳解决方案 ->但是因为我有'useshellexecute=false',所以我不能输入任何关键命令

  • 如何解决此问题?? -我需要查看交互并能够按“Ctrl+C”。 -它不必在命令shell中,我可以使用alternativ“接口”。 -如果设置“useshellexecute=true”,如何输入命令并读取所有行

    请注意:

    P.StartInfo.Arguments
    
    输入命令不起作用。*.exe将显示“无效输入”错误

    有效的代码:

    private void btn_Optimize_Start_Click(object sender, EventArgs e)
        {
            Process P = new Process();
    
            P.StartInfo.FileName = @Application.StartupPath + @"\Algorithm.exe";
            P.StartInfo.UseShellExecute = false;
            P.StartInfo.RedirectStandardInput = true;
            P.StartInfo.RedirectStandardOutput = true;
            P.StartInfo.RedirectStandardError = true;
    
            P.Start();
            //sets timelimit 30 min
            P.StandardInput.WriteLine("set lim tim 1800"); 
            //reads the modell for which an optimal solution has to be found 
            P.StandardInput.WriteLine("read modell.zpl");
            //command that starts the optimization algorithm
            P.StandardInput.WriteLine("optimize");         //this part can take hours
            //command that displays the solution
            P.StandardInput.WriteLine("display solution");
            //ends the *.exe
            P.StandardInput.WriteLine("quit");
    
            //saves all information in a log-file with which I can work
            string[] log = P.StandardOutput.ReadToEnd().Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
    
            //opens a function, that formats the solution
            this.result_create(log);
        }
    
    编辑2014年11月11日/RichTextBox中的线程化过程/输出:

    private void btn_Optimize_Start_Click(object sender, EventArgs e)
        {
            Process P = new Process();
    
            P.StartInfo.FileName = @Application.StartupPath + @"\Algorithm.exe";
            P.StartInfo.UseShellExecute = false;
            P.StartInfo.RedirectStandardInput = true;
            P.StartInfo.RedirectStandardOutput = true;
            P.StartInfo.RedirectStandardError = true;
            //*** NEW *** Event Handler for the asynchron Output-Process
            P.OutputDataReceived += new DataReceivedEventHandler(this.Asyn_Process);
    
            P.Start();
    
            //*** NEW *** Starts asynchron Output-Process
            P.BeginOutputReadLine();
    
            //sets timelimit 30 min
            P.StandardInput.WriteLine("set lim tim 1800"); 
            //reads the modell for which an optimal solution has to be found 
            P.StandardInput.WriteLine("read modell.zpl");
            //command that starts the optimization algorithm
            P.StandardInput.WriteLine("optimize");         //this part can take hours
            //command that displays the solution
            P.StandardInput.WriteLine("display solution");
            //ends the *.exe
            P.StandardInput.WriteLine("quit");
    
            //*** DELETED ***
            //saves all information in a log-file with which I can work
            //string[] log = P.StandardOutput.ReadToEnd().Split(new string[] { Environment.NewLine }, StringSplitOptions.None); 
    
            //opens a function, that formats the solution
            //this.result_create(log);
        }
    
        //*** NEW *** The asynchronous Process
        private void Asyn_Process(object sender, DataReceivedEventArgs e)
        {
            if (this.rTB_Log.InvokeRequired && e.Data != null)
            {
                //Anonym Invoke Function
                this.rTB_Log.Invoke(new MethodInvoker(delegate()
                {
                    //Writes Output continuously in the RichTextBox
                    this.rTB_Log.Text += e.Data + Environment.NewLine;
                    //Scroll to End of RichTextBox continuously
                    this.rTB_Log.SelectionStart = this.rTB_Log.Text.Length;
                    this.rTB_Log.ScrollToCaret();                          
                }));
            }
            //When the process has finished (e.Data == null)
            else
            {
                //Anonym Invoke Function
                this.rTB_Log.Invoke(new MethodInvoker(delegate()
                {
                    //Saves the RichTextBox-Content in a Text-File
                    this.rTB_Log.SaveFile(Algorithm.log", RichTextBoxStreamType.PlainText);
                }));
            }
        }
    

    首先,您没有从
    UseShellExecute=true
    中获得任何好处。这只是副作用--
    ShellExecute
    与重定向不兼容,因此您可以看到没有重定向会发生什么

    你的核心问题是你需要程序的输出去两个地方。在Unix上,您可以使用
    tee
    将输出发送到控制台和您选择的文件(或伪文件),您的应用程序将读取该文件以获得结果

    Windows没有现成的工具来实现这一点,但所有必要的部分都在那里。您想要的方法是:

  • 使用重定向,而不是
    ShellExecute
  • 连续读取应用程序输出,而不是使用
    ReadToEnd()
  • 从子应用程序读取的所有内容也会显示给用户。将它发送到您自己的控制台窗口是可以的,但是将它转储到文本框中,或者解析它并生成一个绘图也是同样有效的
  • 当用户想要中断搜索时,他们将使用您的UI来完成,因为子进程不再从控制台读取其输入。您必须将其转发给子进程,就像按下了CTRL+C一样。有一个Win32函数可以做到这一点,
    generateConsoleControlevent
    。我认为没有任何.NET替代品,因此您可能必须使用p/invoke
  • 更糟糕的是,如中所述,
    generateConsoleControlevent
    作用于整个流程组,而
    process.Start
    不使用创建新组的标志,因此您可能还需要p/invoke
    CreateProcess
    。这意味着您还必须使用p/invoke来设置流重定向,这基本上意味着创建管道并将它们粘贴到传递给
    CreateProcess
    STARTUPINFO
    结构中。这是一个很大的工作。也许你会很幸运地分享这个过程组,而组中没有其他人的反应不好。文档还说“只有组中与调用进程共享同一控制台的进程才能接收信号。换句话说,如果组中的进程创建了新控制台,则该进程不会接收信号,其子进程也不会接收信号。”因此,您的应用程序中也需要有控制台,使用a控制台子系统或使用
    alloconsole

  • 谢谢你的信息-我也很害怕。-我编辑了我的代码,以便连续异步阅读。-我还没有试过GenerateConsoleCtrlEvent,因为这不是优先级,所以它必须等到我有时间的时候才能使用。请去掉
    调用所需的
    。在不需要调用时调用
    Invoke
    不是错误,跳过该逻辑也是错误的。