How to remove custom actions binary on uninstallation? - installation

When I'm uninstalling my product directory where custom action binary was placed stays. How can I delete it. Also strange named directory is created on installation - unistallation: "RSCustomActions.CA.dll-" and "RSCustomActions.CA.dll-0" (my binary name RSCustomActions.CA.dll)
My WIX code is
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="Product.Id" Name="Product">
<Directory Id="INSTALLLOCATION" Name="Product">
<!-- TEST -->
<Directory Id="Installer" Name="Installer">
<Component Id="InstallerFiles"
Guid="{0904DB36-2496-419c-A992-B7D86F068F12}">
<File Id="RSCustomActions.CA.dll" Name="RSCustomActions.CA.dll" Source="Binaries\RSCustomActions.CA.dll" />
</Component>
</Directory>
<!-- END TEST -->
<?include "Product.Files.wxi" ?>
</Directory>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder" Name="PMenu">
<Directory Id="ProgramMenuDir" Name="Aspose">
<?include "Product.ProgramMenu.wxi" ?>
</Directory>
</Directory>
<Component Id="Main" Shared="yes" Guid="{EDD4477A-D188-469c-B8D0-4423377C03C6}" Feature="Main.InstallFeatures">
<RemoveFolder Id="DeleteProgramMenuDir" Directory="ProgramMenuDir" On="uninstall" />
</Component>
</Directory>
"Product.Files.wxi" also contains
<Component Id="Product.Remove" Guid="{C6D9D74C-66E8-442a-8E53-78A8D0E2B24D}">
<RemoveFolder Id="Product.RemoveFolder.Action" On="uninstall"/>
</Component>
Please suggest any way how can I remove Installer folder and those strage folders with binary name.
Thanks!

Why do you need installing the CA DLL as a file of the product? You can simply put it to Binary table and forget about it, like this:
<!-- This is a reference to the DLL where all custom actions reside -->
<Binary Id="CustomActions" SourceFile="$(var.Root)\CA\CustomActions.CA.dll" />
And the custom action definition is something like this:
<!-- Sample CA definition -->
<CustomAction Id="MyAction" BinaryKey="CustomActions" DllEntry="MyActionMethod" />
Note that MyActionMethod should be defined in that CA assembly and marked appropriately. There's a good sample of this in dtf.chm in WiX distribution.
Hope this helps.

Related

Wix Toolset - how to install a file to a completely different directory and not as a root subdirectory?

For my application, most of the files need to be installed to a directory in ProgramFiles, and one other file needs to be installed in a directory in AppData/Local.
Here is an example of what I have so far:
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="Folder1" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="AppID" Directory="INSTALLFOLDER">
<Component Id="AppID">
<File Source="$(var.myApp.TargetPath)" />
</Component>
<Component Id="OtherFile" Guid="INSERT-GUID_HERE">
<File Id='OtherFile' Name='OtherFile' Source="otherfile" KeyPath='yes' />
</Component>
<Component Id="CopyId">
<CopyFile Id="CopyId" FileId="OtherFile"
DestinationDirectory="LocalAppDataFolder" />
</Component>
</Fragment>
I've tried to copy the other file to AppData/Local but this won't compile and gives the error:
Unresolved reference to symbol 'Directory:LocalAppDataFolder' in section 'Fragment:'
Ideally, I want the other file to be in directory in AppData/Local, and not in ProgramFiles at all.
Application Launch: Consider doing file-copying on application launch instead of as part of the setup. Easier to implement, debug and change as you need to.
Fix: Try just adding this directly under the TARGETDIR element. This ensures that the standard directory LocalAppDataFolder is part of the compiled MSI file's Directory table:
<Directory Id="LocalAppDataFolder" Name="AppData">
Alternatively, here is a larger mock-up:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="SetupProject2" />
</Directory>
<Directory Id="LocalAppDataFolder" Name="AppData">
<Directory Id="AppRootDirectory" Name="MyApplication">
<Component Id="Test" Feature="ProductFeature" Guid="{11111111-1111-1111-1111-A73067A1AE95}">
<RemoveFolder Id="AppRootDirectory" On="uninstall" />
<RegistryValue Root="HKCU" Key="Software\Something" Name="Flag" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</Directory>
</Directory>
</Directory>

How to get application folder in WIX Toolkit to install service

I'm trying to to write installer for 3rd-party application.
The service should be installed and running with arguments. One of the argument it's home folder where the service was installed.
How I can read the folder where the application was installed and pass it to Wix Element: ServiceInstall as arguments.
<ServiceInstall Id="SInstall"
Type="ownProcess"
Name="myservice"
DisplayName="MyService"
EraseDescription="no"
Start="demand"
ErrorControl="normal"
Arguments="-folder '[INSTALLDIR]\config.txt'>
But [INSTALLDIR] is empty;
I suppose it's should be done by using SetProperty and read it but cannot find any references how to do this.
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Directory Id="ManufacturerFolder" Name="OEM_XXX">
<Directory Id="INSTALLFOLDER" Name="Product $(var.ProductVersion)">
<Directory Id="DirA" />
<Directory Id="DirB" Name="SubService">
<Directory Id="DirC" Name="ComponentA">
<Directory Id="ComponentB" Name="content" />
</Directory>
</Directory>
</Directory>
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<DirectoryRef Id="DirB">
<Component Id="Svc1" Guid="b033eb95-ce88-48ac-b40f-6913c5e4b978" Win64="yes">
<File Source="$(var.SourceDir)\service.exe" />
<ServiceInstall Id="SInstall"
Type="ownProcess"
Name="myservice"
DisplayName="MyService"
EraseDescription="no"
Start="demand"
ErrorControl="normal"
Arguments="-folder '???????\config.txt'>
<ServiceConfig DelayedAutoStart="no" OnInstall="yes" OnReinstall ="yes" />
</ServiceInstall>
<ServiceControl Id="SControl"
Stop="both"
Remove="uninstall"
Name="myservice"
Wait="no" />
</Component>
</DirectoryRef>
</Fragment>
Thanks.
Use [{directoryId} as a reference;
In my case it was
<ServiceInstall Id="SInstall"
Type="ownProcess"
Name="myservice"
DisplayName="MyService"
EraseDescription="no"
Start="demand"
ErrorControl="normal"
Arguments='-folder "[DirB]config.txt"'>
The full list of available system folder you can find on MSDN:
https://learn.microsoft.com/en-us/windows/desktop/msi/property-reference#system-folder-properties
Sometimes names can confuse you but read description.
For example if you would like to define a path to %PROGRAMDATA% you should use [CommonAppDataFolder]
P.S. Build-in variables ends with trailing slash

ICE91 Wix in perMachine Installer

I am trying to make a perMachine Installer that is able to create files and folders in the PersonalFolder and LocalAppDataFolder of each user. I am getting always the warning message "warning LGHT1076: ICE91: ..." as listed below. When I install as an Administrator the file and folder is created despite the warning, but when I try the installer as standard user no file and no folder is created on the user profile. What could be the solution?
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="PFInstallDir" Name="Example">
<Component Id="ApplicationFiles" Guid="12345678-1234-1234-1234-222222222222">
<File Id="ApplicationFile1" Source="notepad.exe"/>
</Component>
</Directory>
</Directory>
<Directory Id="CommonFilesFolder">
<Directory Id="CFInstallDir" Name="Example">
<Component Id="CommonApplicationFiles" Guid="12345678-1234-1234-1234-222222222223">
<File Id="ApplicationFile2" Source="notepad.exe"/>
</Component>
</Directory>
</Directory>
<Directory Id="CommonAppDataFolder">
<Directory Id="CAInstallDir" Name="Example">
<Component Id="CommonAppDataApplicationFiles" Guid="12345678-1234-1234-1234-222222222224">
<File Id="ApplicationFile3" Source="notepad.exe"/>
</Component>
</Directory>
</Directory>
<Directory Id="PersonalFolder">
<Directory Id="InstallDirPersonal" Name="ExampleDocs">
<Component Id="ApplicationPersonalFiles" Guid="12345678-1234-1234-1234-222222222225">
<CreateFolder />
<RemoveFolder Id="RemoveMyExampleDir1" On="uninstall" Directory="InstallDirPersonal"/>
<RegistryKey Root="HKCU" Key="Software\MyCompany\Documents">
<RegistryValue Name="MainExe" Value="1" KeyPath="yes" Type="integer" />
</RegistryKey>
<File Id="Notepad.MyExe"
Source="notepad.exe" DiskId="1" Checksum="yes">
</File>
</Component>
</Directory>
</Directory>
<Directory Id="LocalAppDataFolder" Name="AppData">
<Directory Id="InstallDirAppDataPersonal" Name="ExampleLocals">
<Component Id="ApplicationPersonalDataFiles" Guid="12345678-1234-1234-1234-222222222226">
<CreateFolder />
<RemoveFolder Id="RemoveMyExampleDir" On="uninstall" Directory="InstallDirAppDataPersonal"/>
<RegistryKey Root="HKCU" Key="Software\MyCompany\Example">
<RegistryValue Name="MainExe" Value="1" KeyPath="yes" Type="integer" />
</RegistryKey>
<File Id="Notepad.MyExe1"
Source="notepad.exe" DiskId="1" Checksum="yes">
</File>
</Component>
</Directory>
</Directory>
</Directory>
<Feature Id="DefaultFeature" Level="1">
<ComponentRef Id="ApplicationFiles"/>
<ComponentRef Id="CommonApplicationFiles"/>
<ComponentRef Id="CommonAppDataApplicationFiles"/>
<ComponentRef Id="ApplicationPersonalDataFiles"/>
<ComponentRef Id="ApplicationPersonalFiles"/>
</Feature>
</Product>
-- Build started: Project: SetupProjectPerUsrMachine, Configuration: Debug x86 --
warning LGHT1076: ICE91: The file 'Notepad.MyExe' will be installed to the per user directory 'InstallDirPersonal' that doesn't vary based on ALLUSERS value. This file won't be copied to each user's profile even if a per machine installation is desired.
warning LGHT1076: ICE91: The file 'Notepad.MyExe1' will be installed to the per user directory 'InstallDirAppDataPersonal' that doesn't vary based on ALLUSERS value. This file won't be copied to each user's profile even if a per machine installation is desired.
Problem solved!
http://www.installworld.com/index.php?option=com_content&do_pdf=1&id=146
"If the resource must be copied to each user’s profile, then add functionality to your package to do this. To achieve this, add a current user registry key (i.e., just a dummy registry key) and make this registry key the key path of the component which contains the resource. This means that the resource will be copied to the next user’s profile as part of the MSI self healing mechanism, provided that advertised entry points exist for the product."
http://blog.bittercoder.com/2007/02/28/wix-shortcuts/
<Component Id="StandAloneApplication" Guid="C8D5DB05-2D68-40e8-88D1-EF5BEA18DBE1">
<File Id="SomeCompanySomeProductHostApp"
Name="SomeCompany.SomeProduct.HostApp.exe"
DiskId="1"
Source="....buildSomeCompany.SomeProduct.HostApp.exe"
Vital="yes">
<Shortcut Advertise="yes"
Id="SomeCompanySomeProductHostAppShortcut"
Directory="ProgramMenuDir"
Name="My Product"
WorkingDirectory="INSTALLDIR"
Description="SomeProduct Application"
Icon="HostAppShortcutIcon.exe">
<Icon Id="HostAppShortcutIcon.exe"
SourceFile="....buildSomeCompany.SomeProduct.HostApp.exe" />
</Shortcut>
</File>
</Component>

Wix - The directory is in the user profile but is not listed in the RemoveFile table

I want to create a subfolder in start menu, in my case PMFCompanyFolder already exists and contains links and I don't want remove when uninstalling my product.
So I don't push the RemoveFolder Property and I get :
ICE64: The directory PMFCompanyFolder is in the user profile but is not listed in the RemoveFile table.
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramMenuFolder">
<Directory Id="PMFCompanyFolder" Name="MyCompany">
<Directory Id="PMFProductFolder" Name="MyProduct"/>
</Directory>
</Directory>
</Directory>
<DirectoryRef Id="PMFProductFolder">
<Component Id="PMFProductFolderComponent" Guid="A13A7784-4C82-4CBE-9018-CEC6F266743B">
<RemoveFolder Id="null" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\Microsoft\MyCompany\MyProduct" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</DirectoryRef>
<Feature Id="ProductFeature" Title="" Level="1">
<ComponentRef Id="PMFProductFolderComponent"/>
</Feature>
You should pass the folder id:
<RemoveFolder Id="PMFCompanyFolder" On="uninstall"/>
It is safe to remove it on uninstall - pre-existing items will not be removed.

VS2010 Wix proj - How to pass a command line variable to be used as a directory name

We have a requirement to install the same software in multiple directories on the same machine. I want to install the software using a batch file. I am having difficulty using the variable I have passed in as a directory name. (I am using VS 2010).
Batch file code
msiexec /i "SetupProjectTestMultiInstalls.msi" CUSTOMER="TESTCUSTOMER"
However the path created is
C:\Program Files\SetupProjectTestMultiInstalls[CUSTOMER]
as oppose to what I want
C:\Program Files\SetupProjectTestMultiInstalls\TESTCUSTOMER
Here is my wix xml
<Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />
<?define MYVARIABLE = "Temp" ?>
<?define FORMDIR = "$(var.SolutionDir)WindowsFormsApplication1\bin\Debug\"?>
<Condition Message="CUSTOMER variable must be set in the command line">
CUSTOMER
</Condition>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLLOCATION" Name="SetupProjectTestMultiInstalls">
<Directory Id="Customer" Name="[CUSTOMER]">
<Component Id="ConfigFiles" Guid ="4fdbee76-d149-11df-aa02-05feded72085">
<File Id="WindowsFormsApplication1.exe" DiskId ="1" Vital="yes" ReadOnly="no"
Name="WindowsFormsApplication1.exe"
Source ="$(var.FORMDIR)WindowsFormsApplication1.exe" />
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
<Feature Id="ProductFeature" Title="SetupProjectTestMultiInstalls" Level="1">
<ComponentGroupRef Id="Product.Generated" />
<ComponentRef Id="ConfigFiles" />
</Feature>
</Product>
Any ideas
Thanks
Jake
You can do something like this using INSTALLDIR instead of CUSTOMER to pass the location from the command line :
msiexec /i "SetupProjectTestMultiInstalls.msi" INSTALLDIR="C:\Program Files\SetupProjectTestMultiInstalls\TESTCUSTOMER"
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR" Name=".">
<Component Id="ConfigFiles" Guid ="4fdbee76-d149-11df-aa02-05feded72085">
<File Id="WindowsFormsApplication1.exe" DiskId ="1" Vital="yes" ReadOnly="no"
Name="WindowsFormsApplication1.exe"
Source ="$(var.FORMDIR)WindowsFormsApplication1.exe" />
</Component>
</Directory>
</Directory>
</Directory>
However, I don't think that you can run the installer several times to install the software to different places. If the Product Id is already used then it will probably do a repair instead of a fresh install.

Resources