0

I have been working on this issue for days but can't find 'good' solution, please bear with me.

The task is running PowerShell script that wraps the calls to 'netsh advfirewall firewall add ...', obviously this needs elevated privilege. Also, in this PowerShell script, different exit codes are set for success or failures. Everything is fine if define a deferred WiX custom action, i.e. if succeed, a dialog about successful firewall change shows, if failed, installation rolls back. However, our customer likes to have the installer:

"Don't let MSI installation rollback if PowerShell script fails, but show some nice warning message on UI dialog at the the end of installation"

In order to wrap different exit codes, I added .NET custom action to invoke Powershell script in C# method and tried to pass it back as CustomActionData property to MSI installer. Unfortunately, I couldn't achieve this and I believe it is because deferred action can't interact with the MSI database, see this post stackoverflow question.

So, in order to pass exit code from .NET custom action back, I think 'immediate' action would set properties. I knew by default, 'immediate' action can not be elevated, but how about in .NET custom action method, can I force Powershell Script to be run as admin in C# method?

In general, is there any other way to achieve our goal. Just recap:

  1. run PowerShell with elevated privilege;
  2. don't rollback installation if Powershell script fails, instead, show different UI with different Powershell script exit codes.

Any answer is greatly appreciated. Thank you.

Community
  • 1
  • 1
Chloe
  • 41
  • 6
  • 1
    you wont roll back the installation if u return ActionResult.Success; in try catch (in both clauses ).It will try to execute , if it fails it will go to the catch and there u return success.As for the evelated privileges , you can ask the user to run as administrator – Chris Tanev Mar 23 '16 at 16:40
  • @FromStuckToFlow, thank you for your reply. Do you mean in c# custom action method, it is NOT controlled by the 'immediate' definition on WiX side? We can always ask user to grand admin by showing UAC window? – Chloe Mar 23 '16 at 16:48
  • It is controlled , it will executed depending on your InstallExecuteSqeuence and how you set it up.Try to ask for running as administrator Before="InstallInitialize" – Chris Tanev Mar 23 '16 at 16:51
  • Specify that your installer must be run as administrator. – Bill_Stewart Mar 23 '16 at 17:00
  • @Bill_Stewart, could you elaborate your idea? Do you mean in WiX, elevate privilege at the very beginning or ask user to run *.msi file as administrator? Thank you. – Chloe Mar 24 '16 at 14:11
  • Try searching for information; e.g.: [http://www.google.com/search?&q=wix+require+administrator](http://www.google.com/search?&q=wix+require+administrator). – Bill_Stewart Mar 24 '16 at 15:19

2 Answers2

1

Perhaps instead of using your own code, use the built-in functionality for firewalls:

http://wixtoolset.org/documentation/manual/v3/xsd/firewall/firewallexception.html

Using the firewall extension in WiX

and custom actions that alter the system must always be deferred so that they can be rolled back and undone.

You don't get a choice about rollbacks. If the installation fails it will roll back! Immediate custom actions are elevated only if the entire install is elevated and run as Administrator. Again, this is because immediate CAs are not expected to modify the system and therefore need no elevation.

Rollback is only loosely associated with deferred CAs. Rollbacks happen for any failure of the install, and Rollback CAs are the way that CAs undo what they already did. It's the posssibility of install failure and rollback that requires deferred CAs to have a rollback equivalent. While CAs can cause a rollback if they decide that their failure is severe enough to fail the install, rollbacks are what Windows will do anyway. An MSI install is a transaction, and the goal is that it all works or all fails, and the install keeps a rollback script (and saves files) to restore the system to its original state. Nobody really wants a partially installed product with some indeterminate set of changes to a system. So if you change the firewall settings with an immediate CA they will be permanent, no matter the fate of the install. It also means that your code that changes firewall settings needs to take account of the possibility that the changes may already be there from a previous failed install. The code will also need to deal with this situation if it's deferred and doesn't have a rollback CA.

When a customer says they don't want an install to roll back it's the equivalent of saying they want COM but don't want reference counting. These things are embedded in the architecture and the design.

Community
  • 1
  • 1
PhilDW
  • 20,260
  • 1
  • 18
  • 28
  • thank you for your answer. We do want to have our own powershell script to get more flexibility. Also, we don't want to have installation rolled back. Thank you all the same. – Chloe Apr 01 '16 at 13:57
  • 1. You don't get a choice! If the installation fails it will roll back! 2. Immediate custom actions are elevated only if the entire install is elevated and run as Administrator. Again, this is because immediate CAs are not expected to modify the system and therefore need no elevation. – PhilDW Apr 01 '16 at 16:13
  • I understand the design purpose of rolling back failed deferred CA because it changes system settings. However, our customer doesn't want to have installation rolling back. If you could elaborate potential risk of *NOT* rolling back for failed deferred CA, it would convince our customer to change his mind. Thank you in advance. – Chloe Apr 01 '16 at 16:58
-1

First of all, thank you all for answering my question. All suggestions sound promising and I will definitely try soon. For now, strictly speaking, what I am typing here is not a direct answer but just a workaround.

Always return ActionResult.Success is surely a sufficient way to avoid rollback. In order to run with elevated privilege, the .NET custom action is run as 'deferred' action; Inside the .NET custom action function, Powershell script is invoked and its exit code is got as script return. Base on the different exit codes, MessageBox.Show() is used in .NET custom action method to show user Powershell script running status. It is a modal dialog box, and it clearly notifies user before installation process continues.

Chloe
  • 41
  • 6