WiX installer leaves empty folders for custom actions - wix

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

Related

Creating a symbolic link in a WiX installer using relative paths

I have been trying to do something like what is posted here about creating a symbolic link in a WiX installer. It explains how to make a add-on that will make a symbolic link. However that is not what I am looking for. I am trying to use somtething like this snipping
<CustomAction Id="MakeSymbolicLink"
Directory="TARGETDIR"
ExeCommand="cmd /c mklink .\linkToItem.lnk '%CommonProgramFiles(x86)%\Additional Folders\myexecutable.exe'" />
I have tried using cmd.exe instead of cmd for this and have not been successful.
I am then call the custom action like this:
<Custom Action="MakeSymbolicLink" After="InstallFinalize" />
I have tried calling this before InstallFinalize as well and I get the same behavior.
I am aiming to create the symbolic link through this setup.
The other solution I have is being able to create a shortcut however I have not been able to find much on how to do this option for places other than the start menu or the Desktop
When I run the installer after adding these lines it fails to execute them. Without the Symbolic link custom action being called I can get the installer to complete successfully.
End goal is to get a symbolic link from the common files executable to the install location of the application.
Update
I got the Symbolic link to work changed custom action now looks like:
<CustomAction Id="MakeSymbolicLink"
Directory="TARGETDIR"
ExeCommand='cmd /c mklink .\linkToItem.lnk "%CommonProgramFiles(x86)%\Additional Folders\myexecutable.exe"'
Execute="deferred"
Impersonate="no"/>
and the call to the custom action like this:
<Custom Action="MakeSymbolicLink" Before="InstallFinalize" />
But now the when I run uninstall I get the following error message: There is a problem with this windows installer package. a program run as part of the setup did not finish as expected contact your support personnel or package vendor.
If you use something like this as your Custome action:
<CustomAction Id="MakeSymbolicLink"
Directory="TARGETDIR"
ExeCommand='cmd /c mklink .\linkToItem.lnk "%CommonProgramFiles(x86)%\Additional Folders\myexecutable.exe"'
Execute="deferred"
Impersonate="no"/>
in your InstallExecuteSequence there needs to be:
<Custom Action="MakeSymbolicLink" Before="InstallFinalize">NOT Installed</Custom>
This makes sure that this is only executed on install of your application if you want to execute this on reinstall or other options you may need to look into how to do that further
If making sure to leave zero footprint behind after a user uninstalls the application you will need to delete the symbolic link afterwards.
I solved this by doing the following:
First I created another CustomAction
<CustomAction Id="RemoveSymbolicLink"
Directory="TARGETDIR"
ExeCommand='cmd /c DEL .\linkToItem.lnk '
Execute="deferred"
Impersonate="no"/>
Then I needed another InstallExecuteSequence to execute this. However I only needed to run this on uninstall so it needed a different conditional in to do that so this one looked like:
<Custom Action="RemoveSymbolicLink" After="InstallInitialize">Installed AND NOT REINSTALL</Custom>

WIX installer: Major upgrade into new installation directory

We use WiX for building installation packages. I am new to WiX technology and currently trying to do a major upgrade of the installed application, but on the different directory location than the previous version. For example, if v2 of a product was installed on Program Files (x86)\Old_path\Product , I would like to installed the upgraded version v3 on a different folder C:\Program Files (x86)\New_path\Product.
I have modified the msi property INSTALLDIR to have the new location path. We tried to alter the InstallExecuteSequence, added RemoveRegistryValues after InstallValidate to remove stored old path on registry and did WriteRegistryValues to add new registry values.
<InstallExecuteSequence>
....
<Custom Action="HxPrepare" Before="InstallValidate">NOT Installed</Custom>
<RemoveRegistryValues After="InstallValidate" />
<WriteRegistryValues />
<Custom Action="HxFinalize" Before="StartServices">NOT Installed</Custom>
....
<InstallExecuteSequence />
But I see no change in the installation process, and the new files get copied to the old directory path only. Can I know where is this old path obtained from even after modifying the INSTALLDIR path? How could we do this installation path change during major upgrades.
Reply to the comment by PhilDW :
That is a correct process for Major upgrade. All the older version files are removed. But however in our application, there is no browse dialogue during upgradation to ask for the new/required installation directory. It simply takes previous version path. This is because first we need to take a back up of important settings/user configured files of lower version and later use them in the upgraded version. After this backup is saved, I try to move this backup files to new path and later start copying new files. I do this path change to INSTALLDIR in HxPrepare step and want to continue the process in the new directory. But I cannot know from where the old path is only considered.
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize" />
<Custom Action="PreventDowngrade" After="FindRelatedProducts">DOWNGRADE</Custom>
<Custom Action="HxInit" After="CostFinalize">NOT Installed</Custom>
<Custom Action="HxPrepare" Before="InstallValidate">NOT Installed</Custom>
<Custom Action="HxFinalize" Before="StartServices">NOT Installed</Custom>
<Custom Action="HxPreUninstall" Before="InstallValidate">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
<Custom Action="HxUninstall" After="InstallInitialize">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
The reason I want to perform this installation path change is because I want to change the product manufacturer name and I want the major upgrade of the product to happen on the new path like "C:\Program Files (x86)\New_manufacturer\Product installation" . How can I achieve this?

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 v3.7 - How to remove file in uninstall that was created after installation

I'm creating an installer for a program using WiX. The program creates a log file and a .dat file in the program directory during the configuration process (after complete installation). How do I tell WiX to remove these files during the uninstallation process if they are not present during the installation process?
Any suggestions would be greatly appreciated.
One way is to define the problem out of existence by installing those files. That is, create and install an empty log file and a dat file—initialized to whatever empty or default is for it.
Another way is to put RemoveFile elements under the Component element that is most closely associated with the use those files (e.g., the program exe).
Are you sure you want writable files in the same directory as the program? Usually, programs are installed so that only administrators can change them. If the program uses data that any user can change to affect all users, the data would be stored under the ALLUSERS profile. And, data that a user can change that affects only that user would be stored under that user's profile.
When data is stored that way, it is a question as to when or even whether such data should be deleted. A user might want that data preserved for the next installation of the program even if the user doesn't know how the data is persisted.
This worked for me - use custom command and delete using "del" or "rmdir"
http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/Forced-remove-of-folder-and-files-within-td698425.html
<Product>
<CustomAction Id="Cleanup_logfile" Directory="INSTALLFOLDER"
ExeCommand="cmd /C "del install.log""
Execute="deferred" Return="ignore" HideTarget="no" Impersonate="no" />
<InstallExecuteSequence>
<Custom Action="Cleanup_logfile" After="RemoveFiles" >
REMOVE="ALL"
</Custom>
</InstallExecuteSequence>
</Product>

How to execute Custom Action before RemoveExistingProducts with After="InstallValidate" in 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.