[quote=JaxFirehart]
Scorpion: That's how it currently is, give or take, RedirectStandardOutput is already true. I use StandardOutput.ReadToEnd to detect when it is done running and then Process.Close(). Where are you finding the code? And yeah, good idea on the BSA collection, makes more sense that way. You should have seen the code when it first started...
[/quote]
I don't have the source, I'm just using Reflector (which reconstructs it from CIL).
The problem with the code in BSAopt.Run(), is that this:
Process process = new Process {
StartInfo = { FileName = @"resources\BSAOpt\BSAOpt x" + sysArch + ".exe", Arguments = " -deployment -game fo -compress 10 -criticals \"" + inArg + "\" \"" + outArg + "\"", UseShellExecute = false, CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, RedirectStandardOutput = true }
};
process.Start();
string str = process.StandardOutput.ReadToEnd();
process.Close();
will never finish blocking from Process.StandardOutput.ReadToEnd() unless the user presses "OK". The process never finalizes writing to StdOut since it's waiting for input from StdIn once BSAopt pauses, so a deadlock occurs until the user intervenes.
You can test this yourself by making a dummy file called test.bat which contains something like:
@echo off
FOR /L %%i IN (1,1,10) DO (
@echo hello %%i
)
pause
It will print some stuff, then pause, like BSAopt. Try debugging this code to see what happens inside the installer:
Process process = new Process
{
StartInfo = { FileName = @"test.bat", UseShellExecute = false, RedirectStandardOutput = true }
};
process.Start();
string str = process.StandardOutput.ReadToEnd();
process.Close();
str will never be set because the call won't end until you press "Enter" on the empty window it creates.
My mistake in suggesting you use WaitForInputIdle(), that's an unrelated function which won't work in a console situation. My idea for a dumb solution:
var processOutput = new StringBuilder();
process.Start();
process.OutputDataReceived += (sender, e) => processOutput.AppendLine(e.Data);
process.BeginOutputReadLine();
while (!process.HasExited && user_wants_us_to_exit)
{
process.WaitForExit(1000);
process.StandardInput.WriteLine();
}
This will a) Log output, which can be retrieved with processOutput.ToString(), and b) Poll the process in 1s intervals for an exit, while checking a user variable (like a CancellationTokenSource, hint hint) to break out if an exit is needed, and feeding in a newline if the process hasn't exited.