【问题标题】:how to detect, and react when an External sub Process, invokes an error dialog当外部子流程调用错误对话框时如何检测并做出反应
【发布时间】:2015-06-18 12:20:54
【问题描述】:

我知道,乍一看,这可能看起来像您以前见过的问题: Knowing when an external process' window shows

但这略有不同。

我有一个 C# asp.net Web 应用程序,用于帮助人们为他们的程序创建安装程序。 (这里的开发人员大多是在某些计算工具中编写方程式的机械工程师,他们不是软件人员,所以我们不希望他们花时间学习 wix、调试安装程序、维护版本之间的 GUID 等等。 )

服务器端将运行控制台应用程序“heat.exe”(wix 工具附带的一个工具),以收集有关如何注册 dll 等的信息,当且仅当他们的存储库中有 dll 时..

我是这样做的:

    public int runHeat(string filePath, string outputFile, ref string response)
    {
        response += "run heat.exe to harvest file data" + '\r' + '\n';

        string args = "file " + '"' + filePath + '"' + " -srd -out" + '"' + outputFile + '"';
        string command = Path.Combine(WixBinariesPath, "heat.exe");
        string workPath = Path.GetDirectoryName(filePath);

        StringBuilder outputBuilder;
        ProcessStartInfo processStartInfo;
        Process process;

        outputBuilder = new StringBuilder();

        processStartInfo = new ProcessStartInfo();
        processStartInfo.CreateNoWindow = true;
        processStartInfo.RedirectStandardOutput = true;
        processStartInfo.RedirectStandardInput = true;
        processStartInfo.UseShellExecute = false;
        processStartInfo.WorkingDirectory = workPath;
        processStartInfo.Arguments = args;
        processStartInfo.FileName = command;
        processStartInfo.ErrorDialog = false;

        //create the process handler
        process = new Process();
        process.StartInfo = processStartInfo;

        // enable raising events because Process does not raise events by default
        process.EnableRaisingEvents = true;

        // attach the event handler for OutputDataReceived before starting the process
        process.OutputDataReceived += new DataReceivedEventHandler
        (
            delegate(object sender, DataReceivedEventArgs e)
            {
                // append the new data to the data already read-in
                outputBuilder.AppendLine(e.Data);
            }
        );

        // start the process
        // then begin asynchronously reading the output
        // then wait for the process to exit
        // then cancel asynchronously reading the output
        process.Start();
        process.BeginOutputReadLine();
        process.WaitForExit();

        // use the output
        response += outputBuilder.ToString();

        if (process.ExitCode != 0)
            response += '\r' + '\n' + "heat.exe exited with code: " + process.ExitCode;

        process.CancelOutputRead();
        return process.ExitCode;
    }

我认为这有效.. 它通过了测试,它已经运行了一段时间没有问题,然后突然,一个开发人员打电话给我做的 webtool,不再为他生成 wix xml..

当我登录服务器时,我发现这个对话框

然后单击 [OK] - Web 应用程序然后继续,并生成 xml,一切正常..

我现在找到了导致热量抛出此错误的 dll。它真的不需要注册(典型的对吧?)。所以我可能只写一个超时的东西,如果需要很长时间就杀死 heat.exe,从而解锁等待脚本,(并基本上解决问题,直到它再次发生与实际需要注册的 dll 一起)但那不是真正检测到错误,那只是检测那些东西需要时间......

遇到此错误,我想继续执行脚本,但会向用户发出警告,即 heat.exe 无法在该特定文件上运行。但要做到这一点,我需要我的 asp.net 应用程序知道这个错误被调用并处理它,以便脚本可以继续..

怎么*?我是否可以获取发生此运行时错误的信息,以便我可以从服务器脚本中处理它?

您是否尝试过使用 -sreg 命令行选项来加热?

我现在有了,因此 heat.exe 不再崩溃,但这不是解决方案,因为 heat 还避免了获取我需要的注册表信息来自动注册相关代码附带的 dll。

【问题讨论】:

  • 使用overload of WaitForExit 指定超时时间。
  • 这实际上是比我在问题中写的更好的超时处理方法,但是..我应该在超时的情况下终止进程吗?
  • 超时,并不能完全解决问题,因为这会使错误对话框打开,每次尝试运行时出现错误。在我对 rdp 的不定期访问之间积累了很多 idalogs ..
  • 您是否尝试过明确设置 ProcessStartInfo.ErrorDialog = false?
  • 你试过用-sreg命令行选项加热吗?

标签: c# wix runtime-error


【解决方案1】:

使用外部“不合作”的可执行文件通常需要一些技巧。我会尝试以下方法:

  • 在命令行启动程序,检查出错时是否有输出。可能它会写入标准错误,您可以使用 RedirectStandardError,读取流并希望在错误发生时得到线索。

  • 检查 heat.exe 中是否有可以启用的日志记录功能,并使用它来检测错误情况。也许是一个详细的设置,或者一个日志文件......

  • 如果以上方法都不起作用,我会使用进程监视器(例如https://technet.microsoft.com/de-at/sysinternals/bb896645.aspx)。启动进程监视器,然后启动您的应用程序并将其带到错误点。将进程监视器中的大量输出过滤到您的应用程序(仍然很多)并在最后搜索是否存在程序可能记录错误的任何访问。也许是一些日志文件或日志服务。您可以在超时后检查此文件。

  • 但是在任何情况下都会起作用的是您在问题中已经建议的 hack。检测对话框是否打开。还可以浏览对话框的内容,因此您还可以阅读文本并检查是哪种错误。我在生产代码中使用过一次来获取外部程序的进度,该程序写在表单内的文本字段中。我使用 spy++(与 Visual Studio 捆绑)来获取文本字段的名称/ID,并使用(本机)Windows API 访问它。一个丑陋的黑客,但除非更改外部程序的 UI,否则工作正常。 在你的情况下,它是一个标准的错误对话框,所以它应该保持一致。

【讨论】:

  • 感谢您提供调试此问题的指针。如果没有更具体的内容出现,我会考虑释放赏金,因为实际上这个答案中有很多有用的数据。我仍然希望有一个更“实施”的答案,比如..一个捕获这种类型错误窗口的示例代码..
  • 如上所述,关于如何取回信息有很多选择,很大程度上取决于外部应用程序。如果您可以缩小范围,我们肯定可以制定出更“实施”的答案。
  • 程序已经从命令行运行,出现错误时没有输出-不在标准输出中,也没有在标准错误中:/
  • 根据wixtoolset.org/documentation/manual/v3/overview/heat.html 有一个详细开关(-v)。你可以试试。
  • 当对话框出现时,您可以轮询 process.MainWindowHandle 并查看它是否与 0 不同。如果它不起作用,您可以像他们在这里一样使用 windows 挂钩尝试它:stackoverflow.com/questions/11285928/… 编辑:也许最好先用 Spy++ 检查它,以确保对话框属于加热过程而不属于任何其他windows进程。
猜你喜欢
  • 2012-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-07
  • 2021-11-15
  • 1970-01-01
  • 1970-01-01
  • 2020-11-15
相关资源
最近更新 更多