Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.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# 当外部子进程调用错误对话框时,如何检测并作出反应_C#_Wix_Runtime Error - Fatal编程技术网

C# 当外部子进程调用错误对话框时,如何检测并作出反应

C# 当外部子进程调用错误对话框时,如何检测并作出反应,c#,wix,runtime-error,C#,Wix,Runtime Error,我知道,乍一看,这可能是你以前见过的一个问题: 但这略有不同 我有一个C#asp.net web应用程序,用于帮助人们为自己的程序创建安装程序。(这里的开发人员大多是机械工程师,在某些计算工具中编写公式,他们不是软件人员,因此我们不希望他们花时间学习wix、调试安装程序、在不同版本之间维护GUID等等。) 服务器端将运行控制台应用程序“heat.exe”(wix工具附带的一个工具),以获取有关如何注册dll等的信息,前提是且仅当它们的存储库中有dll 我是这样做的: public in

我知道,乍一看,这可能是你以前见过的一个问题:

但这略有不同

我有一个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不再为他生成WIXXML

当我登录到服务器时,我发现以下对话框:

然后单击[OK]——然后web应用程序继续运行,并生成xml,这些东西都起作用了

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

对于此错误,我希望继续脚本,但向用户发出警告,heat.exe无法在该特定文件上运行。但要做到这一点,我需要我的asp.net应用程序知道调用了此错误,并对其进行处理,以便脚本可以继续

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


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

我现在拥有了heat.exe,因此它不再是chrash,但这不是一个解决方案,因为heat还可以避免获取自动注册所述代码附带的dll所需的注册表信息。

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

  • 在命令行上启动程序,并检查出现错误时是否有任何输出。可能它写入标准错误,您可以使用重定向标准错误,读取流,并希望在错误发生时获得线索

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

  • 如果以上都不起作用,我会使用过程监视器(例如)。启动process monitor,然后启动应用程序,并将其带到错误点。在ProcessMonitor中过滤巨大的输出,只针对您的应用程序(仍然很多),并在最后搜索是否存在程序可能记录错误的访问。可能是一些日志文件,或者是日志服务。您可以在超时后检查此文件

  • 但无论如何,你在问题中已经提出的黑客方法都会奏效。检测对话框是否打开。还可以浏览对话框的内容,因此您还可以阅读文本并检查它是哪种错误。我在生产代码中使用了一次,以获取外部程序的进度,该程序编写在表单中的文本字段中。我使用spy++(与Visual Studio捆绑)获取文本字段的名称/id,并使用(本机)windows API访问它。一个丑陋的黑客,但工作良好,除非外部程序的用户界面改变。 在您的情况下,它是一个标准错误对话框,因此应该保持一致


用于指定超时。事实上,这是一种比我在问题中所写的更好的超时处理方法,但是。。我是否应该在超时的情况下终止进程?超时并不能很好地解决问题,因为每次尝试运行带有错误的heat时,都会打开错误对话框。我的两个孩子之间要积累很多日志。。对rdp的不定期访问..您是否尝试过显式设置ProcessStartInfo.ErrorDialog=false?是否尝试过使用-sreg命令行选项来加热?感谢您为调试此问题提供的提示。我会考虑释放赏金,如果没有更具体的出现,因为事实上在这个答案中有大量的使用完整的数据。但我还是希望得到一个更“实际”的答案,比如。。捕获此类错误窗口的示例代码..如上所述,关于如何获取信息,有许多选项,这在很大程度上取决于外部应用程序。如果您可以缩小范围,我们肯定可以得出一个更“实现”的答案。程序已从命令行运行,出现错误时没有输出-不在标准输出中,也不在标准错误中:/n根据详细开关(-v)。您可以试试。当对话框出现时,您可以轮询process.MainWindowHandle并查看它是否与0不同。如果它不起作用,您可以像这里一样使用windows钩子进行尝试:编辑:最好先用Spy++检查它,以确保对话框属于heat进程,而不是任何其他windows进程。