The forum has been set to read-only mode. For community discussion and questions, head over to our Discord: https://discord.taleoftwowastelands.com

Installer design

Have something to say about Tale of Two Wastelands or have an idea for a new feature? Let us know here.
Post Reply
scorpion
Posts: 74
Joined: Thu May 22, 2014 8:25 pm

Installer design

Post by scorpion » Sat Jun 07, 2014 1:14 am

I would like to know why the installer requires a pause and several interruptions to close out console windows from BSAopt.




  • If the purpose of the interruption is to prevent the install from being unattended, why does the installer proceed directly from step-to-step, with no way to interrupt this process?


  • If the purpose is to allow users to validate the output before proceeding, why isn't an option provided for the installer to break out in case of an error instead of continuing?


  • If the purpose is just to record the process' output, why isn't the output redirected to a log that doesn't need user intervention?


Currently, I can't see the point of a design for a multi-hour (!) installation that proceeds unattended, but requires frequent user intervention to press an "Okay" button.


You do not have the required permissions to view the files attached to this post.

JaxFirehart
Posts: 3003
Joined: Wed Sep 12, 2012 12:33 am

Do you know any programming

Post by JaxFirehart » Sat Jun 07, 2014 1:17 am

Do you know any programming scorpion?



TJ
Posts: 2181
Joined: Mon Sep 17, 2012 1:06 pm

The purpose is because you're

Post by TJ » Sat Jun 07, 2014 1:18 am

The purpose is because you're on windows 8, and windows 8 broke the intended design. The rest of us don't get that. We don't currently have a way to fix it.


Also if it's a multi-hour installation you've got a really slow computer, or your forgetting to press a key to continue.


My project Dash is on Kickstarter!



scorpion
Posts: 74
Joined: Thu May 22, 2014 8:25 pm

Yes, I am a C# developer.

Post by scorpion » Sat Jun 07, 2014 1:22 am

[quote=JaxFirehart]


 


Do you know any programming scorpion?


[/quote]


Yes, I am a C# developer.



JaxFirehart
Posts: 3003
Joined: Wed Sep 12, 2012 12:33 am

Awesome!

Post by JaxFirehart » Sat Jun 07, 2014 1:28 am

Awesome!


The problem is that the BSAOpt program is a command line program and I don't have much control over it. When I spoke to the developer he implied that BSAOpt itself spawns its own command prompt when run from the console. So basically, I don't have much access to that window. The source code for BSAOpt is available but it is in C++ and compiled with wxWidgets and has been beyond my ability to decipher.


I am an amateur, mostly self taught programmer, so if you have ideas and the experience to back them up, I'm all ears; we just get a lot of people around here who bitch about the installer and have no idea the work that goes into it.



scorpion
Posts: 74
Joined: Thu May 22, 2014 8:25 pm

JaxFirehart wrote:

Post by scorpion » Sat Jun 07, 2014 1:44 am

[quote=JaxFirehart]Awesome!


The problem is that the BSAOpt program is a command line program and I don't have much control over it. When I spoke to the developer he implied that BSAOpt itself spawns its own command prompt when run from the console. So basically, I don't have much access to that window. The source code for BSAOpt is available but it is in C++ and compiled with wxWidgets and has been beyond my ability to decipher.


I am an amateur, mostly self taught programmer, so if you have ideas and the experience to back them up, I'm all ears; we just get a lot of people around here who bitch about the installer and have no idea the work that goes into it.


[/quote]


 


No problem! I've taken a look at the installer and would suggest a few changes:


In the install BackgroundWorker, instead of having a bunch of nested if/elses, build a collection of the BSAs you want to work on, so you can make a single loop to check if it's succeeded/failed and allow a user to interrupt after a BSA.


To log output and get rid of the BSAopt windows, turn on RedirectStandardOutput in the ProcessStartInfo used to spawn the utility in BSAopt.Run(), since it creates a new Process for the BSA utility. Turning on the output redirect will let you access the new process' StandardOutput property for logging (alternate event-based solution). Since the installer just loops until the utility is done anyway, use Process.WaitForInputIdle() to block until the console window is waiting for the "Okay", then feed it a carriage return to close out of the process. Or just use Process.Close() after it finishes blocking.


 


Cheers.


 


Sorry for the wall of text, but if there's anything else I can add or clear up, I'd be happy to help.



TJ
Posts: 2181
Joined: Mon Sep 17, 2012 1:06 pm

Actually we appreciate your

Post by TJ » Sat Jun 07, 2014 2:42 am

Actually we appreciate your input. Jax has been working on the installer alone, as nobody else on the team has the ability. I'm sure he'll enjoy discussing this with you when he gets the chance.


My project Dash is on Kickstarter!



thermador
Posts: 773
Joined: Tue Aug 07, 2012 2:24 pm

Indeed, thanks scorpion!

Post by thermador » Sat Jun 07, 2014 3:58 am

Indeed, thanks scorpion!

JaxFirehart
Posts: 3003
Joined: Wed Sep 12, 2012 12:33 am

Scorpion: That's how it

Post by JaxFirehart » Sat Jun 07, 2014 4:07 am

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...


 



scorpion
Posts: 74
Joined: Thu May 22, 2014 8:25 pm

JaxFirehart wrote:

Post by scorpion » Sat Jun 07, 2014 4:52 am

[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.



Post Reply