views:

2813

answers:

4

How can we prompt for a computer restart after install from within a C# custom action?

We are using VS 2005's setup project for our setup, and we need to programmatically decide to prompt for a restart (so it will not happen on every install, just on some).

UPDATE: We're looking for something that is already built into the MSI custom action system first. If that doesn't exist, we can resort to restarting the PC ourselves somehow, but would like to avoid that.

UPDATE: We see where you can set REBOOT=Force when edited the Msi in Orca, can you modify these tables from a C# custom action at runtime? We could set this to restart every time, but that might make our setup annoying (it will only need to restart on rare occasions).

UPDATE: We tried setting:

savedState["REBOOT"] = "Force";

From within the Install() method of our custom action, but no luck. It doesn't seem like the IDictionary, savedState really does anything.

Also tried:

Context.Parameters["REBOOT"] = "Force";

But I think this collection is just the command line arguments passed to the custom action.

UPDATE: Is there a way to edit our MSI with Orca to make this trick work? Maybe schedule a reboot on a condition of some file existing? We have not found how to set MSI properties from a C# custom action.

UPDATE: We tried hooking into AppDomain.ProcessExit and AppDomain.DomainUnload and starting a new thread and calling Process.GetCurrentProcess().WaitForExit() and none of those events will fire from within a C# custom action...

A: 

When I've had to do this before we used a Win32 API function from user32.dll, I think this was it: ExitWindowsEx()

Sneal
We need something built into the MSI custom action system.We can always programmatically restart the PC with shutdown.exe (or your Win32 function), but looking for a better solution since the MSI needs to finish properly first.
Jonathan.Peppers
We had a C++ custom action library that would restart if needed, and now that I think about it, it probably set the MSI REBOOT flag rather than directly calling a Win32 function. Its been a while so I'm not sure... C++ custom actions aren't too terrible to write, so I wouldn't rule it out.
Sneal
Know how to set MSI flags from a managed custom action? I'm thinking it might not be possible...
Jonathan.Peppers
+1  A: 

You need to add or call the MSI custom action ScheduleReboot http://msdn.microsoft.com/en-us/library/aa371527(VS.85).aspx in your InstallExecuteSequence, . You can do this by using the MSI function MsiDoAction, http://msdn.microsoft.com/en-us/library/aa370090(VS.85).aspx inside a custom action. Please note that the custom action that schedules this must be an immediate custom action, not a deferred custom action. This means you will probably need to schedule it after InstallFinalize. You could also add it to the InstallExecuteSequence with a condition on a public property that your custom action sets.

LanceSc
This is in C#, not C++. The C# custom action system that ships with Visual Studio is not as sophisticated, and we only get 3 methods to override Install(), Uninstall(), Rollback(). Can your answer be accomplished with the setup method we are currently using? We for sure do not want to re-write our setup project in C++.
Jonathan.Peppers
MS implemented a C++ custom action called InstallUtilLib that is shipped with visual studio this basically just wraps C# and .Net custom action system as a hacky way to run a managed custom action. I wish we had used something like WiX from the beginning but we are looking for a patch, not a rewrite.
Jonathan.Peppers
With your architecture, I agree with Glytzhkof that adding it to your InstallExecuteSequence with a condition is the best way to go. You can automate doing this through the MSI API. I have used the MSI API C# wrapper available here, http://sourceforge.net/projects/izfree/files/, to write a number of small executables for automating MSI build tasks. You could easily write a small executable and then have it do a post-build task to add the necessary information. MSI is a just a database for installation with a very strict SQL grammar.
LanceSc
This may feel like a hack and in some sense it is. Visual Studio Deployment projects can only handle very simple tasks, which is why we ended up abandoning them. If you find yourself needing to implement another solution like this, I strongly suggest you cut your losses and find a new MSI front end.
LanceSc
A: 

LanceSc has given you the answer. You need to run ScheduleReboot, and the best way to do so is to insert it in the InstallExecuteSequence conditioned by your own custom property that you set inside your custom action.

As you mention, Wix is the way to go for future flexibility. Wix now also includes DTF (Deployment Tools Foundation) which is a rich set of .NET class libraries that wrap the entire Windows API. You can use this to easily access MSI databases from C# or to write C# custom actions. I can provide more info on this if desirable.

Glytzhkof
Is there a way to run ScheduleReboot from the standard custom action system for C# included with VS 2005? If so, do you have an example?Sadly we do not have the time to redo our setup project with WiX, we would rather do something hacky where we run a process that waits for msiexec.exe to exit and prompts for a restart than redo our setup.
Jonathan.Peppers
Understand where you are coming from. It is hacky indeed, but you should be able to take the compiled MSI from VS and open with Orca (Msi table editor, get from the SDK). Then you can simply modify the InstallExecuteSequence table by adding a row such as:Action: ScheduleRebootCondition: Not Installed AND MYCUSTOMPROPERTYSequence: 6500 (must be unique, and before InstallFinalize).Then you set the MYCUSTOMPROPERTY in your C# custom action if (and only if) a reboot is required.
Glytzhkof
We will try the Orca trick, I will let you know our results.
Jonathan.Peppers
If it doesn't work, u can forward me the MSI (if possible), and I'll have a quick look.
Glytzhkof
It won't be until next Monday, we have a guy on vacation.
Jonathan.Peppers
How do you modify the value for MYCUSTOMPROPERTY in a C# custom action. We can figure out the rest if we knew how to do that.
Jonathan.Peppers
Glytzhkof
The guy on the link is using InstallShield.Is there not a way to make a Visual Studio setup project's C# custom action restart the computer???
Jonathan.Peppers
There is some source code samples in the Installshield samples folder that I would like to forward to you. However, can't find how to email from here just now - in a bit of a rush. You can mail me at nick+gmail etc...
Glytzhkof
Email me at jonathan [dot] peppers [at] gmail [dot] com.
Jonathan.Peppers
+1  A: 

As it seems, the only way for us to solve this is to either:

A) Modify the MSI with orca to make the setup restart for every install

B) Redo the setup project with WiX or Install Shield

Thanks for the help guys.

Jonathan.Peppers