Is it possible to set the values of my Wix Burn gui with a registry search? - wix

My WIX bootstrapper has various optional parameters as well as some settings the user sets up, such as the install location. I want these settings in the GUI to default to the previous values entered by the user when they go to the options screen of the Boostrapper. I have attempted to do this with a util:RegistrySearch of those settings (which are written by the MSI), but they do not appear to be reading in. Is there a way to do this?
These variables are the ones I am attempting to read the registry values into (each one corresponds to a GUI element in the Theme:
<Variable Name="txtCustCode" bal:Overridable="yes" Type="string" Value=""/> <!--CUSTCODE-->
<Variable Name="txtServer" bal:Overridable="yes" Type="string" Value=""/> <!--SERVER-->
<Variable Name="txtDatabase" bal:Overridable="yes" Type="string" Value=""/> <!--DBNAME-->
These are the registry searches with which I am trying to read the values into the variables/controls
<util:RegistrySearch Id="CustCode" Variable="txtCustCode" Root="HKLM" Key="SOFTWARE\[Manufacturer]\[ProductName]" Value="CustCode" Win64="no" Format="raw" Result="value" />
<util:RegistrySearch Id="Server" Variable="txtServer" Root="HKLM" Key="SOFTWARE\[Manufacturer]\[ProductName]\Server" Win64="no" Format="raw" Result="value"/>
<util:RegistrySearch Id="Database" Variable="txtDatabase" Root="HKLM" Key="SOFTWARE\[Manufacturer]\[ProductName]\Database" Win64="no" Format="raw" Result="value" />

Related

Windows Installer not deleting all files on uninstall

I've seen some similar questions asked on here, but none of the solutions given were very clear or worked for me.
I have an installer (created with WiX) which installs certain files and folders. However, when running the installed application, this creates some folders and copies some files into it. These files and folders are not removed on uninstall.
Edited to Show Code so Far:
This INSTALLDIR property:
<Property Id="INSTALLDIR">
<RegistrySearch Id='Registry' Type='raw' Root='HKLM' Key='Software\$(var.Manufacturer)\$(var.ProductName)' Name='Location' />
</Property>
This Component which should set the install location in the registry:
<Component Id="Registry" Guid="*">
<RegistryKey Root="HKMU" Key="Software\$(var.Manufacturer)\$(var.ProductName)">
<RegistryValue Name="Location"
Type="string"
Value="[INSTALLDIR]"
Action="write"
KeyPath="yes" />
</RegistryKey>
<util:RemoveFolderEx On="uninstall" Property="INSTALLDIR" />
</Component>
This does create a record in the registry with the install location, but I'm not sure how to adapt this code to making note of the 'public' directory and removing it - I don't know where the util:RemoveFolderEx should go either (inside which component)
The clearest tutorial I've seen is this one (except that it does have an apparent error).
Replace this block:
<!--
RemoveFolderEx requires that we "remember" the path for uninstall.
Read the path value and set the APPLICATIONFOLDER property with the value.
-->
<Property Id="APPLICATIONFOLDER">
<RegistrySearch Key="SOFTWARE\$(var.Manufacturer)\$(var.SkuName)" Root="HKLM" Type="raw" Id="APPLICATIONFOLDER_REGSEARCH" Name="Path" />
</Property>
with this one:
<!--
RemoveFolderEx requires that we "remember" the path for uninstall.
Read the path value and set the FOLDERTOREMOVE property with the value.
-->
<Property Id="FOLDERTOREMOVE">
<RegistrySearch Key="SOFTWARE\$(var.Manufacturer)\$(var.SkuName)" Root="HKLM" Type="raw" Id="APPLICATIONFOLDER_REGSEARCH" Name="Path" />
</Property>
and this block:
<util:RemoveFolderEx On="uninstall" Property="APPLICATIONFOLDER" />
with this one:
<util:RemoveFolderEx On="uninstall" Property="FOLDERTOREMOVE" />
and you should have a working test.
The reason for using two different properties is given here and here (among with other places).
If you can derive the path from other values you may have set during installation that Windows Installer will preserve for you, such as ARPINSTALLLOCATION, then you can adjust the above implementation to get what you need without having to create your own registry keys.
Builds on B. Murri's answer:
Example: your application installs new files or folders in 'installdir/public'. These files aren't being deleted as they weren't added by the installer.
First, you need to create a registry value which will store where your public directory is installed. This is in case the user changes the install directory.
<!-- Note that the RegistryValue Value is being set to the 'public' directory ID -->
<DirectoryRef Id='INSTALLDIR'>
<Component Id="RemovePublicDir" Guid="your-guid-here">
<RegistryKey Root="HKCU" Key="Software\$(var.Manufacturer)\$(var.ProductName)">
<RegistryValue Name="Location"
Type="string"
Value="[PUBLIC]"
Action="write"
KeyPath="yes" />
</RegistryKey>
<CreateFolder Directory="PUBLIC"/>
<util:RemoveFolderEx Property="FINDPUBLICDIR" On="uninstall"/>
<RemoveFolder Id="PUBLIC" On="uninstall"/>
</Component>
</DirectoryRef>
You now need to add a property which will search for this registry value later on. Make sure your Root value above matches the one below:
<Property Id="FINDPUBLICDIR">
<RegistrySearch Id='Registry' Type='raw' Root='HKCU' Key='Software\$(var.Manufacturer)\$(var.ProductName)' Name='Location' />
</Property>
Add your manufacturer name and product name to variables, like this:
<?define Manufacturer = "My Company"?>
<?define ProductName = "Test Application"?>
Now make sure you call this Component in your Feature tag:
<Feature Id="FeatureId">
<ComponentRef Id="RemovePublicDir" />
</Feature>

WIX- support multiple Instance of Web App on IIS

I am using wix to create my msi installer. the installer will create a new app pool and virtual directory in the IIS to run my web app.
Right now, I am trying to have multiple instance of the web app on the same machine at the same time(either same version, or higher version).
-Is such thing supported in Wix?
-Can I dynamically create multiple app pool and virtual directory on each installation? Because at the moment the name of the appPool, and Virtual directory and destination folder are hard coded inside the Product.WXS file.
I think that you can't even perform setup multiple times, it will just try to uninstall, modify or repair your previous installation or to perform upgrade.
But regarding app pool or website name you can specify it in installation process in your feature selection dialog, to have textbox where you can write down name of website or app pool
<Control Id="WebsiteName" Type="Text" X="..." Y="..." Width="..." Height="..." Text="Website name :" Indirect="no" >
<Condition Action="hide">Installed</Condition>
</Control>
<Control Id="WebsiteName" Type="Edit" X="..." Y="..." Width="..." Height="..." Property="WEBSITENAME" Text="{50}" Indirect="no" >
<Condition Action="hide">Installed</Condition>
</Control>
Than you need to specify your property at Product.wxs
<Property Id="WEBSITENAME" Value="YourDefaultWebSiteName" Secure="yes">
<RegistrySearch Id="FindWebSiteName" Root="HKCU"
Key="SOFTWARE\YourCompany\YourProduct"
Name="WebsiteName" Type="raw"/>
</Property>
<Property Id="APPPOOL" Value="0" Secure="yes">
<RegistrySearch Id="FindWixSetupInstallation" Root="HKCU"
Key="SOFTWARE\YourCompany\YourProduct"
Name="webAppPool" Type="raw"/>
</Property>
Than you need to specify it at your settings where you create app pool and website name
<iis:WebSite Id="DefaultWebSite" Description="Default Web Site">
<iis:WebAddress Id="AllUnassigned" Port="80" />
</iis:WebSite>
<DirectoryRef Id="YourDirectory" >
<Component Id="CMP_CONFIG" Guid="{YOURGUID}" KeyPath="yes">
<iis:WebVirtualDir Id="WebsiteName" Alias="[WEBSITENAME]" Directory="YourDirectory" WebSite="DefaultWebSite">
<iis:WebApplication Id="YourApplicationApp" Name="[WEBSITENAME]" WebAppPool="[WEBSITENAME]" />
<iis:WebDirProperties Id="YourApplicationDirProp" Script="yes" Execute="yes" Read ="yes" DefaultDocuments="Default.aspx"/>
</iis:WebVirtualDir>
</Component>
</DirectoryRef>
And if you want to create shortcut to desktop
<DirectoryRef Id="DesktopFolder">
<Component Id="YourWebsiteAppDesktopShortcut" Guid="{YOURGUID}">
<RegistryValue Root="HKCU"
Key="SOFTWARE\YourCompany\YourProduct"
Name="YourWebsiteApp"
Type="integer"
Value="1"
KeyPath="yes"/>
<util:InternetShortcut Id="WebSiteDesktopShortcut"
Directory="DesktopFolder"
Name="YourWebsiteAppName"
Target="http://localhost/[WEBSITENAME]/"
Type="url" />
</Component>
</DirectoryRef>
And you just need to register all those component reference ID's in your Product.wxs

Is it possible to read from 64 and 32-bit registry entries in the same installation?

In my installation I need to check presence of 64-bit entry at first.
And read its value if it is present in 64-bit part of registry.
If entry is absent then I need to try to read this entry from 32-bit registry part(Wow6432Node).
I need to read it directly from wxs file or from custom action on VBScript.
Is it possible to do?
If you're running a 64bit MSI you can set two AppSearch/RegLocator entries using the style:
<Property Id="MY_32BIT_REG">
<RegistrySearch Id="my32bitreg"
Root="HKLM"
Key="SOFTWARE\My Company"
Name="foo"
Type="raw"
Win64="no" />
</Property>
<Property Id="MY_64BIT_REG">
<RegistrySearch Id="my64bitreg"
Root="HKLM"
Key="SOFTWARE\My Company"
Name="foo"
Type="raw"
Win64="yes" />
</Property>
These entries will check the appropriate "HKLM\SOFTWARE\My Company" and "HKLM\SOFTWARE\Wow6432Node\My Company" registry hives.

Windows 8 search keeps showing my app name in lowercase

I've created an desktop app for Windows and a corresponding WiX installer. Let's assume my app is called "Foo". The main executable and all app references are called "Foo", with caital "F".
But Windows 8 search (the one which pops up when you enter the Start screen and begin typing) only finds the reference to my app when I type it with "f" in lowercase and shows my app name with lowercase "f" in the beginning.
Here's how I register the Start screen reference in WiX:
<RegistryValue Root="HKLM" Key="SOFTWARE\RegisteredApplications" Name="Foo" Value="SOFTWARE\Foo\Capabilities" Type="string" />
<RegistryValue Root="HKLM" Key="SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Foo.exe" Value="[!Foo.exe]" Type="string" />
<RegistryValue Root="HKLM" Key="SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Foo.exe" Name="Path" Value="[APPLICATIONFOLDER]" Type="string" />
Is there a way to tell the Windows indexing service how should it index a particular executable?
To achieve what you are asking, I would add a shortcut to the windows 8 start menu search by creating a Shortcut element. You would tie that in to a Directory element, see general example below:
<Feature Id="StartMenuShortcut" >
<Component Id="StartMenuShortcut" Guid="SOME-GUID-HERE" Directory="ApplicationProgramsFolder" >
<Shortcut Id="ApplicationStartMenuShortcut"
Name="Foo"
Target="[INSTALLFOLDER]\foo.exe"
WorkingDirectory="INSTALLFOLDER"
Icon="SomeIconFileHereIfYouHaveOne.ico"/>
<RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
<RegistryValue Root="HKLM" Key="Software\Microsoft\MyApplicationName" Name="installed" Type="integer" Value="1"
KeyPath="yes"/>
</Component>
</Feature>
Not only will this give you the start menu display name you desire for Foo.exe, but if Foo is ever uninstalled, this shortcut will be removed with it.
Hope this helps.

Using WiX, how to skip a component when a certain registry key does not exist?

I want to copy some files into a directory in another product's installation tree, but only if that product is installed. So I figured I could set a property based on a registry search to find that product's installation root. Then I could use the property in a condition element on the component element.
Here is my code. For some reason, I am getting an error when the other product is not installed and the registry search comes up empty since the registry key will not be found.
<Property Id="PRODUCTPATH">
<RegistrySearch Id="PRODUCTPATH" Root="HKLM" Key="_MY_KEY_" Name="_MY_NAME_" Type="raw" />
</Property>
<SetProperty Id="PRODUCTBINPATH" Value="[PRODUCTPATH]\BIN" After="AppSearch"/>
<Component Id="CommonDLLs" Guid="_MY_GUID_" Directory="INSTALLLOCATION">
<Condition>PRODUCTPATH</Condition>
<RegistryValue Id="_MY_ID_" Root="HKLM" Key="_MY_KEY_2" Name="Installed" Value="1" Type="integer" KeyPath="yes" />
<CopyFile Id="myfile1.dll" FileId="myfile1.dll" DestinationProperty="PRODUCTPATH" DestinationName="myfile1.dll"/>
<CopyFile Id="myfile2.dll" FileId="myfile2.dll" DestinationProperty="PRODUCTPATH" DestinationName="myfile2.dll"/>
</Component>
Try to use the util:RegistrySearch instead of RegistrySeach
This element comes with Util Extension. Check here if you don't know how to use extensions.
The util:RegistrySearch has an attribute (Result) for only checking if the key exists or not.
It would be like that:
<util:RegistrySearch
Id="PRODUCTPATH"
Variable="PRODUCTPATH"
Root="HKLM"
Key="_MY_KEY_"
Format="raw"
Result="exists">
Actually, all you have to do is add a condition to the SetProperty element like this:
<Property Id="PRODUCTPATH">
<SetProperty Id="PRODUCTBINPATH" Value="[PRODUCTPATH]\BIN" After="AppSearch">PRODUCTPATH</SetProperty>