WiX uninstall - close application before Restart Manager - wix

I have an installer done with WiX. When it's done installing, it starts an application that injects some code in the Explorer process.
Currently when I uninstall, the Restart Manager kicks in and offers to shut down my application and Explorer. Instead of that I want to close my application manually (this is done by running it again with -exit on the command line). I have a custom action that does it.
Here's what I tried so far:
<CustomAction ExeCommand="-exit" FileKey="MyApp.exe" Id="CloseMyApp" Impersonate="yes" Return="ignore" />
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize" />
<Custom Action="CloseMyApp" Before="RemoveFiles" />
</InstallExecuteSequence>
This doesn't work. The action is done way after the Restart Manager session. So the Restart Manager pops up and asks to close my app and Explorer. The action runs later, but by then the app is already gone.
So then I tried this:
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize" />
<Custom Action="CloseMyApp" Before="RemoveExistingProducts" />
</InstallExecuteSequence>
This also doesn't work. The action is done too late still. I also get "warning LGHT1076 : ICE63: Some action falls between InstallInitialize and RemoveExistingProducts.".
So basically - how do I execute my custom action during uninstall and before the Restart Manager session?
I'm guessing if I use Impersonate="no" it might run at the right time, however that's not an option. That's because the new process must run for the same user as the process that has to close because it looks up its window and sends messages. That's much trickier to do if the processes belong to different users.
Any ideas?

You would need the CloseMyApp custom action to run before InstallValidate since that is when the restart manager is processed (doc). Alternatively, you could disable restart manager with MSIDISABLERMRESTART or MSIRESTARTMANAGERCONTROL Properties.

Related

WiX: Custom Actions don't run when using msiexec /i Setup.msi /qn (quiet mode installation without UI)

Our problem is that custom actions don't run when using msiexec /i Setup.msi /qn (quiet mode installation without UI). They only run with normal installation with UI.
In our Product.wxs for example, we have defined the following:
<Binary Id="SetupCustomAction" SourceFile="$(var.SetupCustomActions.TargetDir)$(var.SetupCustomActions.TargetName).CA.dll" />
<CustomAction Id="UPDATE_CONFIG" BinaryKey="SetupCustomAction" DllEntry="UpdateConfiguration" Execute="commit" Return="check" Impersonate="no" />
<InstallExecuteSequence>
...
<Custom Action="UPDATE_CONFIG" After="InstallFiles"><![CDATA[NOT Installed AND USEIMPERSONATE="0"]]></Custom>
...
</InstallExecuteSequence>
Do we have to use "Quiet Execution Custom Action", trying this out didn't help though!
Please help!
The obvious explanation is that USEIMPERSONATE has the value 1 so the custom action will not run, but I assume perhaps you are setting it to 0 on the command line.
Apart from that it would be useful to know if the install actually succeeds, because if it normally requires elevation with a UAC prompt then this UAC dialog will not be shown, so the custom action will not run elevated and it will fail. The install might succeed because Commit custom actions run after the install, so "check" is not relevant because the install cannot roll back. If you configure that CA as an install custom action it might fail and roll back the install. So after InstallFiles is also not relevant because it's a Commit CA.
The log should show something.
Okay, I have found the cause of the error and a fix for it: The ALLUSERS OR PREVIOUSINSTALLSCOPE (read from the registry) Properties must be set to "1". That way, the DISABLE_IMPERSONATE Custom Action gets run and sets the USEIMPERSONATE Property to "0". Then UPDATE_CONFIG and other Custom Actions get run.
To sum up, the solution is:
Change DISABLE_IMPERSONATE Property to this: <Custom Action="DISABLE_IMPERSONATE" After="AppSearch"><![CDATA[ALLUSERS=1 OR PREVIOUSINSTALLSCOPE="1"]]></Custom>
Call msiexec like this: msiexec /i Bechtle.A365.Office.Client.msi /qn ALLUSERS=1
Thanks to #Ritmo2k, #Brian Sutherland and #PhilDW for pointing me to the right direction.

Invoking Data Protection API from within a CustomAction

I am trying to run some unmanaged code from a C# ca within WIX. I have a wrapper around the CryptProtectData function, this code works fine if run from an admin prompt. I have scheduled the ca as deferred hoping it would run during the elevated session however it fails in this context.
The scheduling is as follows:
<CustomAction Id="SetCustomActionDataValue" Property="EncryptValues" Value="foo=bar;...;" />
<CustomAction Id="EncryptValues" BinaryKey="InstallerCustomAction.CA.dll" DllEntry="EncryptValues" Execute="deferred" Impersonate="no" HideTarget="no" Return="check" />
<InstallExecuteSequence>
<Custom Action="SetCustomActionDataValue" After="InstallFiles" />
<Custom Action="EncryptValues" After="SetCustomActionDataValue" />
</InstallExecuteSequence>
What needs to be done to allow something like this to run during the installer, preferably after the files and registry entries are committed to the system?
Do you have any logging in your CA? Can you confirm that your CustomActionData made it over?
One thing you might try is to wire this up as a simple console app and use PSExec to invoke a cmd.exe prompt as SYSTEM.
I've never used this API but the comment "Typically, only a user with the same logon credential as the user who encrypted the data can decrypt the data." makes me think that this might not run well as SYSTEM. This article seems to confirm that. http://www.obviex.com/samples/dpapi.aspx
FWIW, I'm not sure what you are trying to achieve but I'd consider moving it from the installer to the application if possible. Installers are generally best kept simple and reliable.

Run ExeCommand in customAction as Administrator mode in Wix Installer

I am new to wix installer. I have developed a set-up using wix installer for my application and I need to execute a Custom Action to run a command in cmd.exe. In XP it works fine. But in Windows 8 & 7 the cmd prompt needs to be run as administrator.
I have googled and found the keywords Elevated Privileges and impersonate might help me.
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" InstallPrivileges="elevated"></Package>
As you can see above, I used the InstallScope attribute set to perMachine, and I have used Impersonate="No" in the CustomAction element:
<CustomAction Id='comReg' Directory='INSTALLLOCATION' Impersonate='no'
ExeCommand='"[NETFRAMEWORK40CLIENTINSTALLROOTDIR]regasm.exe" "[INSTALLLOCATION]myProduct.dll" /codebase' Return='check' />
But I didn't get any changes while installating. I need the command prompt to open and run the above command in Administrator Mode.
And can anyone please tell me about these keywords "Elevated Privileges & impersonate"
<InstallExecuteSequence>
<Custom Action='comReg' After='InstallFinalize'>NOT REMOVE</Custom>
<Custom Action='comUnreg' Before='RemoveFiles'>REMOVE</Custom>
</InstallExecuteSequence>
How to do it?
The wix documentation here explains the Impersonate attribute:
This attribute specifies whether the Windows Installer, which executes as LocalSystem, should impersonate the user context of the installing user when executing this custom action. Typically the value should be 'yes', except when the custom action needs elevated privileges to apply changes to the machine.
You also need to understand the difference between deferred and immediate custom actions. See the Execute attribute on the same help page:
This attribute indicates the scheduling of the custom action. This attribute's value must be one of the following:
deferred
Indicates that the custom action runs in-script (possibly with elevated privileges).
immediate
Indicates that the custom action will run during normal processing time with user privileges. This is the default.
At present your custom action is immediate, which means it is running with user privileges. See this blog post for lots of details, but particularly:
Any immediate custom actions impersonate the invoking user. Before Windows Vista this wasn't a problem since at this point the installing administrative user had a privileged token. With the introduction of UAC in Windows Vista the default administrative token with UAC enabled is a filtered token and does not hold all privileges. Since immediate custom actions are not supposed to modify machine state - only to gather state data and schedule custom actions to run deferred - this still shouldn't be a problem. After all, at this point the generation of the installation and rollback scripts is all that should be going on.
You should never modify machine state with an immediate custom action. Use a deferred one, and keep impersonate to no, and it should work:
<CustomAction Id='comReg' Directory='INSTALLLOCATION' Execute='deferred' Impersonate='no' ExeCommand='"[NETFRAMEWORK40CLIENTINSTALLROOTDIR]regasm.exe" "[INSTALLLOCATION]EAWordImporter.dll" /codebase' Return='check' />
EDIT: Schedule the custom action using the InstallExecuteSequence element:
<InstallExecuteSequence>
<Custom Action='comReg' Before='InstallFinalize'/>
</InstallExecuteSequence>

'wix execute batch before uninstall with administrator

My WiX XML file installs app that contains windows-service named OLOLO_SERVICE (for example). I want to stop this service when installing/reinstalling my app.
I use CustomAction with ExeCommand='sc stop OLOLO_SERVICE'.
<CustomAction Id='EnsureThatServiceIsStopped' Directory='INSTALLLOCATION'
Impersonate="no" Execute="immediate" ExeCommand="sc
stop OLOLO_SERVICE" Return="ignore" />
Inside <InstallExecuteSequence> tag is action
<Custom Action='EnsureThatServiceIsStopped' Before='InstallValidate' />
But this doesn't works, uninstaller shows this window "For uninstallation continue you should stop following executables" (maybe not 100% correct, because in my russian Windows 7 it is written in russian).
I think that possible reasons for this are
script runs before admin rights taken (and stopping service fails because it needs admin privilegies)
script runs after validation (and validation fails when checking installed executables)
Plesae help me, I want to stop service using batch 'sc stop OLOLO_SERVICE'
PS. I decided to simplify a question: I want my WiX to execute 'sc stop OLOLO_SERVICE' with administrator privilegies and before checking for running applications
You don't need to do this in a batch file, you can use the ServiceControl element:
<ServiceControl Id="ServiceControl_OloService"
Name="OLOLO_SERVICE"
Stop="both"
Remove="uninstall"
Wait="yes" />

Set environment variable before running a custom action in WiX

I have to build an MSI-based installer using WiX and I need to set environment MY_HOME before running a command action.
I have a component:
<Component Id="SEMYHOME"
Guid="*my guid*">
<CreateFolder />
<Environment Id="MY_HOME"
Action="set"
Part="all"
Name="MY_HOME"
Permanent="no"
System="yes"
Value="[APPLICATIONPATH]myapp"/>
</Component>
Then I have a custom action:
<CustomAction Id="InstallMyService"
Directory="INSTALLDIR"
ExeCommand='"[INSTALLDIR]myapp\install_service.bat" install'
Execute="immediate"
Return="ignore"/>
<InstallExecuteSequence>
<Custom Action="InstallMyService"
After="InstallFinalize"/>
</InstallExecuteSequence>
NOTE: This action need the MY_HOME variable to be set before running.
When install this MSI, I got a log showing that the MY_HOME variable is set before running the custom action "InstallMyService", but the command to install my service still fails. I found that the cause is when command called, MY_HOME still not set.
After an install is finished, MY_HOME was set as expected, but the custom action fails :(
How can I fix this problem?
Windows Installer and Custom Actions are hosted via the Service Control Manager which has a long history of not respecting broadcast messages that are sent announcing Environment changes. So even if you fix the immeadiate / deferred problem that Yan mentions you'll find that your custom action still doesn't have the environment variable.
Why don't just just pass "[APPLICATIONPATH]myapp" to your .bat file and fetch it in as %2?
BTW I also don't reccomend calling batch files from an installer. It's fragile and embarrassing to see installs that run popping up little black windows.
You CA is immediate. This means that it runs immediately when Windows Installer is processing your MSI package. And this obviously happens before the component containing <Environment/> is installed. Modify it to be deferred (Execute="deferred") and schedule before InstallFinalize.