【问题标题】:Process Exits immediately if I redirect a Console Application written in Delphi in C# winform application如果我在 C# winform 应用程序中重定向用 Delphi 编写的控制台应用程序,进程立即退出
【发布时间】:2012-11-23 15:41:57
【问题描述】:

我有一个用 Delphi 编写的控制台应用程序 (Host.exe)。 我想在 C# 应用程序(WinForm)中重定向控制台应用程序的输出。

如果我使用以下内容,则调用 (Host.exe) 没有问题,但由于它是作为 (show-window, 完全独立) 运行的,因此无法获得输出。

                ProcessStartInfo pp = new ProcessStartInfo();
                pp.WorkingDirectory = Path.GetDirectoryName(Application.ExecutablePath);
                pp.FileName = Path.Combine(pp.WorkingDirectory, "Host.exe");
                pp.CreateNoWindow = false;
                pp.WindowStyle = ProcessWindowStyle.Normal;
                pp.UseShellExecute = true;
                using (Process pProcess = Process.Start(pp))
                {
                    while ((pProcess != null) && (!pProcess.HasExited))
                    {
                        Application.DoEvents();
                        Thread.Sleep(updatefreq);
                    }
                }

但是,如果我尝试捕获输出(重定向),进程将立即退出(HasExited = true,循环中断,调试器显示“仅完成了 ReadProcessMemory 或 WriteProcessMemory 请求的一部分”。

                ProcessStartInfo pp = new ProcessStartInfo();
                pp.WorkingDirectory = Path.GetDirectoryName(Application.ExecutablePath);
                pp.FileName = Path.Combine(pp.WorkingDirectory, "Host.exe");
                pp.UseShellExecute = false;
                pp.RedirectStandardOutput = true;
                pp.RedirectStandardInput = true;
                pp.RedirectStandardError = true;
                pp.CreateNoWindow = true;
                pp.WindowStyle = ProcessWindowStyle.Hidden;
                StreamReader outputReader = null;
                using (Process pProcess = Process.Start(pp))
                {
                    if (pProcess != null)
                    {
                        //StreamWriter inputWriter = pProcess.StandardInput;
                        //StreamReader errorReader = pProcess.StandardError;
                        outputReader = pProcess.StandardOutput;
                    }
                    while ((pProcess != null) && (!pProcess.HasExited))
                    {
                        string ss = null;
                        if (outputReader != null)
                        {
                            ss = outputReader.ReadLine();
                        }
                        if ((ss != null) && (2 < ss.Length))
                        {
                            string[] s = ss.Split('|');
                            if (3 == s.Length)
                            {
                                float global;
                                //float.TryParse(s[0], out local);
                                float.TryParse(s[1], out global);
                                RadioTracer.SetCurrentMsg(s[2]);
                                RadioTracer.SetCurrentStep((int)global);
                            }
                        }
                        Application.DoEvents();
                        Thread.Sleep(updatefreq);
                    }
                }

我用谷歌搜索了很多,但没有找到解决方案。 以下页面存在类似问题,我尝试了建议的解决方案,但没有任何效果。

https://connect.microsoft.com/VisualStudio/feedback/details/609801/unable-to-redirect-only-the-standard-input-of-process-cmd-exe-or-batch-file-from-windows-form-application

http://go4answers.webhost4life.com/Example/redirectstandardinput-a-32-bit-114440.aspx

http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/4f946750-6c47-406c-810c-21a2b103b5c4

非常感谢...这已经浪费了我很多时间了..我希望我能在这里找到解决方案。

编辑:即使我不使用任何 ReadLine() 或 ReadToEnd() 方法,问题仍然存在。当 'UseShellExecute' 设置为 false 时,Host.exe 将立即退出。Host.exe 应该进行一些大计算(大约需要 2 分钟,并且每隔几秒通过控制台 WriteLine 报告进度)。

【问题讨论】:

  • 这是一个示例,它似乎可以按照您所描述的那样工作——blog.csharphelper.com/2010/11/10/…——他们使用ReadToEnd() 来获取所有stdout,而不是使用ReadLine()。 ..
  • ReadLine() 或 ReadToEnd() 在这种情况下应该无关紧要,因为如果 'UseShellExecute' 设置为 false,即使我没有 ReadLine() 或 ReadToEnd,Host.exe 也会自动退出() 根本...
  • 您的代码有点繁琐。您不需要对 null 进行太多测试。而且您缺少使用 pProcess.StandardOutput 的方法。但是您的代码确实有效。试试它是一个 Delphi 控制台应用程序,它循环执行 Writeln,然后是 Sleep、Writeln、Sleep 等。所以我不知道我们能提供什么帮助。 host.exe 可能有些奇怪。但是我们没有host.exe。也许是 UAC?
  • 谢谢.. 是的。你是对的...... C# 代码的逻辑没问题,因为我创建了一个简单的 Host.exe,它只打印出进度/消息,它工作正常...... UAC 完全关闭。也许 Host.exe 有问题,但我不知道为什么,因为 Host.exe 在命令行下可以正常工作...
  • 我找到了原因,请看“答案”

标签: c# delphi console io-redirection


【解决方案1】:

我发现如果在 C# 中重定向输出,以下几行将导致错误。我在 Delphi 中使用 Console.pas 单元,在该单元的初始化中,它调用 InitScreenMode 过程。

  Reset(Input);
  Rewrite(Output);
  StdIn := TTextRec(Input).Handle;
  StdOut := TTextRec(Output).Handle;

我猜在 C# 中将“UseShellExecute”设置为 false 时,“重置”或“重写”控制台标准输入/标准输出会导致问题

【讨论】:

  • "对此有何解释?"看起来你在回答一个新问题,但这不是 StackOverflow 的工作方式,请阅读faq。您可能想要编辑您的原始问题并包含这些信息,或者提出一个新问题。这取决于您,但您不会在答案中提出新问题。
  • 在传统的 pascal 文件中,reset 打开文件用于输入,而 rewrite 打开文件用于输出。我很确定任何控制台应用程序都必须打开输入/输出流才能使用它。它发生在低级别,您正在查看 console.pas 单元,它是实现此低级别事物的单元。我猜你的猜测是错误的,但我不是这方面的专家,因此,和你一样,我只是评论我的想法。
  • thanks... 我认为Reset(Input) 与C# 中的重定向冲突,但由于它是低级别的,我不知道它不起作用的细节和原因。无论如何,我已经删除了该单元(或简单地注释掉重置)并且它按我的预期完美运行。
猜你喜欢
  • 2014-09-04
  • 2011-02-01
  • 2012-09-13
  • 1970-01-01
  • 2019-01-30
  • 2014-02-18
  • 2021-02-02
  • 1970-01-01
相关资源
最近更新 更多