How to execute Custom Action before RemoveExistingProducts with After="InstallValidate" in WiX - wix

I have something like this:
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallValidate"/>
</InstallExecuteSequence>
Since one of the uninstallation fails i need to execute a Custom Action to solve the problem BEFORE RemoveExistingProducts. Something in the lines of:
<CustomAction Id="FixStuff" .. />
<InstallExecuteSequence>
<Custom Action="FixStuff" Before="RemoveExistingProducts" />
<RemoveExistingProducts After="InstallValidate"/>
</InstallExecuteSequence>
This of course doesn't work since Custom Action cannot be before InstallInitialize. I'd really like to remove existing products between InstallValidate and InstallInitialize, but i'd like to execute FixStuff before removing existing products.
Is it even possible to do that?

Unfortunately you cannot run an elevated custom action before RemoveExistingProducts with your current configuration.
Some possible approaches would be:
Move RemoveExistingProducts right before InstallFinalize. This solves the custom action problem, but other problems may occur since this approach has many restrictions (the components need to maintain their names and GUIDs between versions, your custom actions should be aware that the upgrade is performed at installation end etc.).
Create an EXE bootstrapper which fixes the old installer before launching the new MSI. This bootrapper can require Administrator privileges through a manifest:
http://msdn.microsoft.com/en-us/library/bb756929.aspx
Repair the broken MSI by using this method:
fix the problem in the old MSI
create a BAT or EXE bootstrapper which recaches it through this command:
msiexec /fv <path_to_msi>
distribute this MSI as an update before your new package
When your new package runs RemoveExistingProducts, the old cached MSI should be fixed and it should uninstall correctly.

Related

WIX Installer getting Bad condition and sequence error

I want my custom action to be executed after the complete installation is been done. Went through so many sites but didn't get it work.
<Binary Id="DepTypeCustomActionBinary" SourceFile="$(var.SolutionDir)\Proj.Setup\DepCustomAction.CA.dll"/>
<CustomAction Id="CheckDepType" BinaryKey="DepTypeCustomActionBinary" DllEntry="CustomAction1" Impersonate="no" Execute="deferred" Return="check" HideTarget="no" />
<InstallExecuteSequence>
<Custom Action="CheckDepType" After="InstallFinalize">NOT Installed</Custom>
</InstallExecuteSequence>
Above is my code and I am getting below error:
CheckDepType is a in-script custom action. It must be sequenced in between the InstallInitialize action and the InstallFinalize action in the InstallExecuteSequence table
I'll just add a short answer rather than adding too many comments. I am not sure what dscrt40.dll is doing - is it a file you use during installation for some runtime dependency? I wouldn't recommend installing your own files into a pre-existing folder - if that is what you are doing.
I suppose you could try to use the RemoveFile construct to have the Windows Installer engine remove the file in question on install, this should prevent the need for a custom action. You must not do this if you install the file you are removing via a Windows Installer component first - then self-repair is likely to kick in to put it back afterwards.
A custom action that makes changes to the system can not be sequenced after InstallFinalize - the database change transaction ends with InstallFinalize, and you no longer have elevation for the custom actions that follow after InstallFinalize (immediate mode custom actions can be inserted, but they will fail unless you are running with admin rights - don't try it - it is impossible to rely on). You can only insert change custom actions (deferred custom actions) after InstallInitialize and before InstallFinalize in the InstallExecuteSequence.
You should be aware that files will be present on disk after the action InstallFiles has run (technically on the second run through the InstallExecuteSequence - the first run - immediate - just creates an execution script, the second run - deferred - executes the script), so you can in principle delete files after this action has run, but it doesn't really make sense to do so.
Why do you need to delete this file?
Do you install this file yourself or is it a pre-existing file?

Strange behaviour of MSI installer on uninstall package

I made something wrong in my installer, but I don't know what it is:
during uninstallation I see how all contents of the product folder is disappearing...
...and then, after uninstallation is complete, the contents is appearing again - my product is not uninstalled actually.
Such behaviour is not always, but happens accidentally (or I didn't catch some factors).
Can anybody help with this issue?
I have checked in the EventViewer that uninstallation completed with error 1603.
The documentation tells that this error means:
A system restart may be required because the file being updated is also currently in use.
But no product's files were opened during uninstallation. Also I stopped all applications from my product.
The reason became simple. In the InstallExecute sequence I had:
<InstallExecuteSequence>
<Custom Action="ModifyServiceConfig" Before="InstallFinalize"/>
</InstallExecuteSequence>
As a result, on uninstallation this custom action was calling too, and I got an error 1603.
I didn't considered the fact that instructions inside InstallExecute sequence are called during uninstallation too.
The fragment above must look like this:
<InstallExecuteSequence>
<Custom Action="ModifyServiceConfig" Before="InstallFinalize">NOT Installed</Custom>
</InstallExecuteSequence>
That means that this custom action must be called only during installation.

WiX installer leaves empty folders for custom actions

I've created a WiX installer project and a CustomAction project. I've successfully added the MyCustomAction to the installation script and it works as it should.
However, the installer leaves empty folders in the [INSTALLFOLDER] every time the installer is executed. They're named MyCustomAction.CA.dll-, MyCustomAction.CA.dll-0, MyCustomAction.CA.dll-1 etc. Even the uninstaller won't remove them, so the amount of empty folders just get bigger.
Is there a way to prevent the folder creation? I've tried different Execute values (commit, deferred) but they don't seem to make any difference.
MyCustomAction is defined as follows:
<CustomAction Id="MyCustomAction"
Return="check"
Execute="commit"
FileKey="MyCustomAction.CA.dll"
DllEntry="MyCustomAction" />
<InstallExecuteSequence>
<Custom Action="MyCustomAction" Before="InstallFinalize">NOT Installed</Custom>
</InstallExecuteSequence>
I found a solution to the problem: I had included the MyCustomAction.CA.dll in my product's installation files and not in its own Fragment. That caused the dll to be copied to the installation folder.
Now when the CustomActions are defined in their own Fragment the temporary folder is not created in the INSTALLFOLDER.
did you add a binary entry for them?
<Binary Id='FooBinary' SourceFile='foo.dll'/>
http://wixtoolset.org/documentation/manual/v3/wixdev/extensions/authoring_custom_actions.html

Deleting files and directories before installation of MSI

Our product was installed via InstallShield Setup over the years. I changed the installation to MSI (WiX) this year. Now the MSI should clean up the directory, which remains the same.
One custom action in the MSI I implemented to start the uninstallation of the old product:
<CustomAction Id="UninstallIS" Property="QtExecCA" Value=""[WindowsFolder]IsUn0407.exe" -f "[ProgramFilesFolder]\company\product\Uninst.isu"" Execute="deferred" />
<CustomAction Id="QtExecCA" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="ignore" Impersonate="no" />
After the removal of the old product there are temporary files and some subdirectories that are different from client to client and are unknown to the InstallShield Setup, so I would try to delete them via the MSI.
Keeping the UAC in mind, I think that I can't use command-line commands to do this also the 'Remove File Table' is not useful here (to much unknown files and many directories).
What is a possible way to do this?
Thank You for any help!
You can use a Deferred custom action which has Impersonate flag set to "no". This way it will run under the local system account with full privileges.
The custom action can use custom code (for example an EXE or DLL) or a command line.
Please note that deferred custom actions can be scheduled only after InstallInitialize action in InstallExecuteSequence.
As a side-note, make sure you thoroughly test it. Deleting files from the target machine is very dangerous. You never know what you may end up deleting.

msi file not running when called through wix customaction

I have the following in my wix project but the msi file (which is valid and runs from the command line) will not run either with or without the silent parameter
<InstallExecuteSequence >
<Custom Action="Runmymsi" After="InstallFinalize">Not Installed</Custom>
</InstallExecuteSequence>
I have run into this before. Your issue is that you can't call an MSI from another MSI. These need to be run at separate times. I would suggest writing a bootstrapper that will run your MSIs in the proper sequence.