How to detect and react with an external subprocess, causes a dialog box with an error

I know that this may at first glance look like a question that you saw before: Know when an external process window is displayed

But that is a little different.

I have a C # asp.net web application that helps people create an installer for their programs. (The developers here are mostly mechanical engineers who build equations in some calculation tools, they are not software users, so we don’t want them to spend time studying wix, debugging installers, GUID GUIDs between releases, etc.)

The console application "heat.exe" (the tool that comes with the wix tools) will be launched on the server to collect dll registration information, etc., if and only if they have a dll in their repository ..

I do it like this:

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; } 

I thought it worked. He passed the tests, he worked for some time without problems, and then suddenly the developer called that the created webtool no longer creates wix xml for him.

When I logged in to the server, I found this dialog box:

The runtime error message

and then click [OK] - then the web application continued, and you created xml and everything was processed.

Now I have found a dll that causes heat to throw this error. It really does not need to be logged (typically right?). So I could probably just write a timeout to kill heat.exe if necessary, and thus unlock the waiting script (and basically fix the problem until it repeats with the dll that really needs in registration). But this does not actually detect an error, that is, it simply detects that the material takes time ...

In this error, I would like to continue the script, but warned the user that heat.exe could not be started in this particular file. But for this, I need my asp.net application to know that this error was caused, and delete it so the script can continue.

as *? I get information that this error occurred at runtime, so I can deal with it from a script server?

Have you tried using the -sreg command line option to heat up?

Now I have it, and as a result, heat.exe no longer processes it, but this is not a solution, since the heat also avoids collecting the registry information that I need to auto-update the DLL that comes with this code.

+6
source share
1 answer

Working with external "fault tolerant" executables often requires some deception. I would try the following:

  • Run the program on the command line and check if there is any output when an error occurs. It probably writes a standard error, and you can use a RedirectStandardError, read the stream, and hopefully get a hint when an error occurs.

  • Check if there is any logging feature in heat.exe that you can enable, and use this to detect the error. Maybe a detailed parameter or a log file ...

  • If none of this was done, I would use a process monitor (e.g. https://technet.microsoft.com/de-at/sysinternals/bb896645.aspx ). Launch the process monitor and then your application and bring it to the point of error. Filter the huge output on the process monitor only for your application (which is still quite a lot) and search at the end if there is access where the program may report an error. Perhaps some log files or a logging service. You can check this file after the timeout.

  • But something will work in any case - this is the hack that you already suggested in your question. To determine if a dialog box has opened. It is also possible to view the contents of the dialog so that you can also read the text and check which error is. I used this once in production code to get the progress of an external program that was written in a text field inside a form. I used spy ++ (bundled with Visual Studio) to get the name / identifier of the text field and access it using the (native) windows API. An ugly hack, but it works great if the external interface of the program is not changed. In your case, this is the standard Error Dialog, so it should remain completely consistent.

+1
source

Source: https://habr.com/ru/post/985049/


All Articles