Can I allow a user to choose either applicationPoolIdentity or specify a user using WiX-IIS extension? - wix

My web application typically will be installed to use applicationPoolIdentity:
<iis:WebAppPool Id="MyAppPool" Identity="applicationPoolIdentity" Name="MyAppPool"/>
but I have a class of users that will want to use a specific domain user instead, which I would typically author like this:
<util:User Id="MyUser" Name="[MY_USER]" Domain="[MY_DOMAIN]" Password="[MY_PASSWORD]" CreateUser="no"/>
<iis:WebAppPool Id="MyAppPool" Identity="other" User="MyUser" Name="MyAppPool" />
Making the user interface for this is simple enough, but is there a way to conditionally switch between Identity="applicationPoolIdentity" and Identity="other" without writing a custom action?

Yes, it is possible but you will need to create a component group with two components that have conditionals. As this solution is a bit verbose, I recommend having it in a separate file.
Here is an example, based on https://www.codeproject.com/Articles/115036/Creating-WIX-Installer-for-ASP-NET-Web-Application.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:iis="http://schemas.microsoft.com/wix/IIsExtension"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Fragment>
<Property Id="IIS_WEBSITE" Value="root"/>
<Property Id="VIRTUAL_DIR_VAL" Value="myappdir" />
<!-- +++++++++++++++++++ web app name properties initialize ++++++++++++++++++++ -->
<Property Id="WEB_APP_NAME" Value="myapp" />
<Property Id="WEB_APP_USE_CUSTOM_APP_POOL_IDENTITY" Value="1" />
<!-- +++++++++++++++++++ app pool identity properties initialize +++++++++++++++ -->
<Property Id="WEB_APP_POOL_IDENTITY_DOMAIN" Value="domain" />
<Property Id="WEB_APP_POOL_IDENTITY_NAME" Value="user" />
<Property Id="WEB_APP_POOL_IDENTITY_PWD" Hidden="yes" />
<!-- Reference to IIS Website to install to, but not create -->
<iis:WebSite Id='rootwebsite'
Description='[IIS_WEBSITE]'
Directory='INSTALLFOLDER'>
<!-- This element has to be here or WiX does not compile. It’s ignored
in this case. -->
<iis:WebAddress Id="AllUnassignedHTTP" Port="80" />
<iis:WebAddress Id="AllUnassignedHTTPS" Port="443" />
</iis:WebSite>
<DirectoryRef Id="INSTALLFOLDER">
<Component Id="InstallWebsiteCustomUser" Guid="[guid]" KeyPath="yes" Win64="yes">
<Condition><![CDATA[WEB_APP_USE_CUSTOM_APP_POOL_IDENTITY = 1]]></Condition>
<util:User Id="WebAppPoolUser"
CreateUser="no"
Name="[WEB_APP_POOL_IDENTITY_NAME]"
Password="[WEB_APP_POOL_IDENTITY_PWD]"
Domain="[WEB_APP_POOL_IDENTITY_DOMAIN]" />
<iis:WebAppPool Id="WebAppPoolCustom"
Name="[WEB_APP_NAME]"
Identity="other"
User="WebAppPoolUser"
ManagedPipelineMode="Integrated"
ManagedRuntimeVersion="v4.0"
RecycleMinutes="200" />
<iis:WebVirtualDir Id="WebVirtualDirCustom"
Alias="[VIRTUAL_DIR_VAL]"
Directory="INSTALLFOLDER"
WebSite="rootwebsite">
<!-- Turn the Virtual Directory into a web application. -->
<iis:WebApplication Id="WebApplicationCustom"
Name="[WEB_APP_NAME]"
WebAppPool="WebAppPoolCustom" />
</iis:WebVirtualDir>
</Component>
<Component Id="InstallWebsite" Guid="[guid]" KeyPath="yes" Win64="yes">
<Condition><![CDATA[WEB_APP_USE_CUSTOM_APP_POOL_IDENTITY <> 1]]></Condition>
<iis:WebAppPool Id="WebAppPool"
Name="[WEB_APP_NAME]"
Identity="applicationPoolIdentity"
ManagedPipelineMode="Integrated"
ManagedRuntimeVersion="v4.0"
RecycleMinutes="200"/>
<iis:WebVirtualDir Id="WebVirtualDir"
Alias="[VIRTUAL_DIR_VAL]"
Directory="INSTALLFOLDER"
WebSite="rootwebsite">
<!-- Turn the Virtual Directory into a web application. -->
<iis:WebApplication Id="WebApplication"
Name="[WEB_APP_NAME]"
WebAppPool="WebAppPool" />
</iis:WebVirtualDir>
</Component>
</DirectoryRef>
<ComponentGroup Id="IisConfiguration">
<ComponentRef Id="InstallWebsiteCustomUser" />
<ComponentRef Id="InstallWebsite" />
</ComponentGroup>
</Fragment>
</Wix>

Related

Issue with Wix not creating IIS pool before running SQL setup scripts

I'm writing a Wix msi that needs to create a database, configure IIS and then run a few SQL setup scripts. The issue I'm running into is that the SQL scripts seem to be running before IIS has completed configuration with the appropriate pool / website. One of the SQL scripts relies on the IIS being configured and causes the installer to fail:
Here's what I have (Relevant parts pulled out of various *.wxs files):
Main.wxs:
<Feature Id="ProductFeature" Title="SamplePortalApi.Setup" Level="1">
<ComponentGroupRef Id="SamplePortalApiComponents" />
<ComponentGroupRef Id="MyIISConfiguration" />
<ComponentRef Id="SqlComponent" /> <!-- Database Setup / Scripts Run Here -->
</Feature>
ConfigureIIS.wxs:
<DirectoryRef Id="INSTALLFOLDER">
<Component Id="SamplePortalAppPool" Guid="" KeyPath="yes">
<iis:WebAppPool Id="SamplePortalAppPool"
Name="SamplePortalApi"
Identity="applicationPoolIdentity"
ManagedPipelineMode="Integrated"
ManagedRuntimeVersion="v4.0" />
</Component>
<Component Id="InstallWebsite" Guid="" KeyPath="yes">
<iis:WebSite Id="SamplePortalApi" Description='SamplePortalApi' Directory='INSTALLFOLDER' AutoStart='no' StartOnInstall='no'>
<iis:WebAddress Id="AllUnassigned" Port="[DB_PORT]" />
<iis:WebApplication Id="SamplePortalApiApplication" Name="[SamplePortalApi][WEBSITE_ID]" WebAppPool="SamplePortalAppPool"></iis:WebApplication>
</iis:WebSite>
</Component>
</DirectoryRef>
<ComponentGroup Id="SamplePortalApiIisConfiguration">
<ComponentRef Id="InstallWebsite" />
<ComponentRef Id="SamplePortalAppPool" />
</ComponentGroup>
Database.wxs
<Binary Id="MigrationBin" SourceFile="Migration.sql"></Binary>
<Binary Id="CreateLoginBin" SourceFile="CreateLogin.sql"></Binary>
<Binary Id="CreateUserBin" SourceFile="CreateUser.sql"></Binary>
<Binary Id="DeleteLoginBin" SourceFile="DeleteLogin.sql"></Binary>
<DirectoryRef Id="INSTALLFOLDER">
<Component Id="SqlComponent" Guid="8A1C82DB-1DD3-4FB5-8600-4F370FE1E04B">
<Condition>NOT Installed</Condition>
<sql:SqlDatabase Id="SamplePortalApiDatabase" Database="[DB_DATABASE]" Server="[DB_SERVER]" CreateOnInstall="yes" DropOnUninstall="yes" ContinueOnError="no">
<sql:SqlScript Id="Migration" ExecuteOnInstall="yes" ExecuteOnUninstall="no" BinaryKey="MigrationBin" ContinueOnError="no" />
<sql:SqlScript Id="CreateLogin" ExecuteOnInstall="yes" ExecuteOnUninstall="no" BinaryKey="CreateLoginBin" ContinueOnError="no"/>
<sql:SqlScript Id="DeleteLogin" ExecuteOnInstall="no" ExecuteOnUninstall="yes" BinaryKey="DeleteLoginBin" ContinueOnError="no"/>
</sql:SqlDatabase>
<CreateFolder/>
</Component>
</DirectoryRef>
What's the best approach here? I think I could run the problematic SQL as a CustomAction rather than as part of the built in WXS functionality, but I don't think this is the most elegant approach. Is there a better way of ensuring that IIS is setup properly first?

Creating a Virtual Directory on IIS using IsWix

I'm creating an IsWix solution that creates an IIS with a static javascript website.
The website is working as expected after the instalation when I enter to
localhost:8080
The problem starts here, I'm unable to serve this website on a virtual directory.
I want to be able to use localhost/myApp to browse the app.
In your main project under Code\IISMeta.wxs you'll find the markup that defines the IIS configuration. This file can express any valid WiX IIS meta as documented here:
https://wixtoolset.org/documentation/manual/v3/xsd/iis/
A basic example (needs some tweaking) would look something like this:
<Directory Id="webSites" Name="WebSites">
<Component Id="webSite" Guid="PUT_GUID_HERE" KeyPath="yes" Permanent="yes">
<CreateFolder />
<iis:WebSite Id="DefaultWebSite" SiteId="*" Description="Default Web Site" Directory="webSites" ConfigureIfExists="no" >
<iis:WebAddress Id="webSite" Port="80" />
<iis:WebDirProperties Id="webSite" AnonymousAccess="yes" WindowsAuthentication="no" />
</iis:WebSite>
</Component>
<Directory Id="webSiteUi" Name="UI">
<Component Id="webSiteUi" Guid="PUT GUID HERE" KeyPath="yes">
<iis:WebAppPool Id="webSiteUi" Name="WebSiteUI" Identity="networkService" ManagedRuntimeVersion="v4.0" ManagedPipelineMode="Classic" />
<iis:WebVirtualDir Id="webSiteUi" Alias="Something" Directory="webSiteUi" WebSite="DefaultWebSite">
<iis:WebDirProperties Id="webSiteUi" AnonymousAccess="yes" WindowsAuthentication="no" />
<iis:WebApplication Id="webSiteUi" WebAppPool="webSiteUi" Name="Something" />
</iis:WebVirtualDir>
</Component>
</Directory>

Wix remove appdata folder on uninstall

I am using Wix 3.11 and have tried a number of different ways and methods and can't seem to be able to figure out why Wix isn't removing my ApplicationDataFolder folder. During install I create the folder in the ApplicationDataFolder location for the user.
My application uses logging and stores it along with a few other things in the directory. During uninstall everything in the application folder is removed but the appdata folder with the logs and other files are left untouched.
I can't figure out why or what I am missing.
WXS Template
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Product Id="*" UpgradeCode="9e578e3d-0119-425c-8633-f54ffaaa4929" Name="#product.name#" Version="#product.version#" Manufacturer="#product.company#" Language="1033">
<Package InstallerVersion="400" Compressed="yes" InstallScope="perMachine" Comments="#product.version#" Description="#product.description#"/>
<Media Id="1" Cabinet="SomeApp.cab" EmbedCab="yes" />
<!-- Installer Properties -->
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
<PropertyRef Id="WIX_IS_NETFRAMEWORK_46_OR_LATER_INSTALLED"/>
<!-- Installer Resources -->
<Icon Id="ApplicationIcon" SourceFile="SomeApp 4\SomeApp 4_vista.ico"/>
<Property Id="ARPPRODUCTICON" Value="ApplicationIcon" />
<Property Id="INSTALLDIR">
<RegistrySearch Key="SOFTWARE\Acme\SomeApp"
Root="HKCU" Type="raw"
Id="APPLICATIONFOLDER_REGSEARCH" Name="installation-path" />
</Property>
<WixVariable Id="WixUILicenseRtf" Value="SomeApp 4\license.rtf" />
<WixVariable Id="WixUIBannerBmp" Value="WixUIBannerBmp.bmp" />
<WixVariable Id="WixUIDialogBmp" Value="WixUIDialogBmp.bmp" />
<!-- Check Existing Install -->
<Upgrade Id="9e578e3d-0119-425c-8633-f54ffaaa4929">
<UpgradeVersion Minimum="#product.version#" OnlyDetect="yes" Property="NEWERVERSIONDETECTED"/>
<UpgradeVersion Minimum="0.0.0" Maximum="#product.version#" IncludeMinimum="yes" IncludeMaximum="no" Property="OLDERVERSIONBEINGUPGRADED"/>
</Upgrade>
<Condition Message="A newer version of this software is already installed.">NOT NEWERVERSIONDETECTED</Condition>
<!-- Prerequisites -->
<Condition Message="This application requires .NET Framework 4.6 or newer. Please install the .NET Framework then run this installer again.">
<![CDATA[Installed OR WIX_IS_NETFRAMEWORK_46_OR_LATER_INSTALLED]]>
</Condition>
<Condition Message="This application requires at least Windows 7 or Windows Server 2008 R2. Please upgrade your computer to a supported operating system and run this installer again.">
<![CDATA[Installed OR (VersionNT >= 601)]]>
</Condition>
<!-- Define the directory structure -->
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder" Name="ProgramFiles">
<Directory Id="INSTALLDIR" Name="#product.company#">
#product.applicationfiles#
#product.servicefiles#
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="#product.name#"/>
<Directory Id="ServiceProgramsFolder" Name="#product.name#"/>
</Directory>
<Directory Id="DesktopFolder" Name="Desktop" />
<Directory Id="LocalAppDataFolder">
<Directory Id="ApplicationDataFolder" Name="Acme" />
</Directory>
</Directory>
<DirectoryRef Id="ApplicationProgramsFolder">
<Component Id="ApplicationShortcut" Guid="1e578e4d-0229-425c-8633-f54ffaaa4901">
<Shortcut Id="ApplicationStartMenuShortcut"
Name="SomeApp 4.6"
Description="#product.company# #product.name# #product.version#"
Target="[INSTALLDIR]SomeApp 4\SomeApp.UserInterface.exe"
WorkingDirectory="INSTALLDIR"
Icon ="ApplicationIcon"/>
<Shortcut Id="ApplicationStartMenuShortcut2"
Name="SomeApp 4.6 (Multiple Instances)"
Description="#product.company# #product.name# #product.version#"
Target="[INSTALLDIR]SomeApp 4\SomeApp.UserInterface.exe"
Arguments="MultipleInstance=True"
WorkingDirectory="INSTALLDIR"
Icon ="ApplicationIcon"/>
<Shortcut Id="ApplicationStartMenuShortcut3"
Name="SomeApp 4.6 (Notifications)"
Description="#product.company# #product.name# #product.version#"
Target="[INSTALLDIR]SomeApp 4\SomeApp.UserInterface.exe"
Arguments="Notifications=True"
WorkingDirectory="INSTALLDIR"
Icon ="ApplicationIcon"/>
<Shortcut Id="HelpStartMenuShortcut"
Name="SomeApp 4.6 Help"
Target="[INSTALLDIR]SomeApp 4\Documentation\SomeApp.chm"
WorkingDirectory="INSTALLDIR"/>
<Shortcut Id="UninstallProduct"
Name="Uninstall SomeApp 4.6"
Target="[SystemFolder]msiexec.exe"
Arguments="/x [ProductCode]"
Description="Uninstall #product" />
<Shortcut Id="desktopshortcut"
Directory="DesktopFolder"
Name="SomeApp 4.6"
WorkingDirectory="INSTALLDIR"
Target="[INSTALLDIR]SomeApp 4\SomeApp.UserInterface.exe" />
<RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
<util:RemoveFolderEx On="uninstall" Property="ApplicationDataFolder" />
</Component>
</DirectoryRef>
<DirectoryRef Id="ServiceProgramsFolder">
<Component Id="ServiceShortcut" Guid="9e578e3d-0229-425c-8633-f54ffaaa4901">
<Shortcut Id="ServiceStartMenuShortcut"
Name="#product.name# Reporting Service"
Description="#product.name# Reporting Service"
Target="[INSTALLDIR]Reporting\SomeApp.ReportingService.exe"
WorkingDirectory="INSTALLDIR"
Icon ="ApplicationIcon"/>
<RemoveFolder Id="ServiceProgramsFolder" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\Microsoft\Acme\SomeApp" Name="service-installed" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</DirectoryRef>
<DirectoryRef Id="INSTALLDIR">
<Component Id="CleanupMainApplicationFolder" Guid="*">
<RegistryValue Root="HKCU" Key="SOFTWARE\Acme\SomeApp" Name="installation-path" Type="string" Value="[INSTALLDIR]" KeyPath="yes" />
<util:RemoveFolderEx On="uninstall" Property="INSTALLDIR" />
<util:RemoveFolderEx On="uninstall" Property="ApplicationDataFolder" />
</Component>
</DirectoryRef>
<!-- Feature: SomeApp Application -->
<Feature Id="Feature.Application"
Title="SomeApp 4 - Application"
Description="SomeApp is an asset management and maintenance application designed to optimize asset value and improve manufacturing productivity."
ConfigurableDirectory="INSTALLDIR"
Level="1"
AllowAdvertise="no">
#product.applicationcomponents#
<ComponentRef Id="ApplicationShortcut" />
<ComponentRef Id="CleanupMainApplicationFolder" />
</Feature>
<!-- Feature: Reporting Service -->
<Feature Id="Feature.Service"
Title="SomeApp 4 - Reporting Service"
Description="This service generates and delivers reports that have been scheduled in the SomeApp Maintenance Management System."
ConfigurableDirectory="INSTALLDIR"
Level="3"
AllowAdvertise="no">
#product.servicecomponents#
<ComponentRef Id="ServiceShortcut" />
<Component Id="ReportingServiceInstaller" Guid="B72CAA3F-F2DB-48D2-90DD-061209AB2CE5" Directory="INSTALLDIR">
<CreateFolder />
<File Id="ReportingService.exe" Name="ReportingService.exe" KeyPath="yes" Source="#product.sourcedir#\Reporting\SomeApp.ReportingService.exe"/>
<ServiceInstall Id="ReportingServiceInstaller"
Type="ownProcess"
Vital="yes"
Name="SomeApp Reporting Service"
DisplayName="SomeApp - Reporting Service"
Description="This service generates and delivers reports that have been scheduled in the SomeApp Maintenance Management System."
Start="auto"
Account="NT AUTHORITY\LocalService"
ErrorControl="ignore"
Interactive="no" />
</Component>
</Feature>
<CustomAction Id="Cleanup_logfile" Directory="INSTALLDIR"
ExeCommand="cmd /C "rmdir %LOCALAPPDATA%\Acme /s /q""
Execute="deferred" Return="ignore" HideTarget="no" Impersonate="no" />
<InstallExecuteSequence>
<Custom Action="Cleanup_logfile" After="RemoveFiles" >
REMOVE="ALL"
</Custom>
</InstallExecuteSequence>
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallValidate"/>
</InstallExecuteSequence>
<UIRef Id="WixUI_FeatureTree" />
<UI>
<DialogRef Id="FilesInUse" />
<DialogRef Id="MsiRMFilesInUse" />
<!-- Add the GUI logic for installation -->
</UI>
</Product>
</Wix>
I have one project that uses util:RemoveFolderEx where it is working properly. The only difference I can see is that I explicitly set a property at runtime to the value of the install directory. My guess is that "INSTALLDIR" and "ApplicationDataFolder" are not actually properties since they are stored in the Directory table of your msi and not the property table. (Checked using ORCA)
Try doing
<SetProperty Id='AcmeAppDataFolderToRemove' Value='[ApplicationDataFolder]' After='AppSearch'/>
and then change your util:RemoveFolderEx to
<util:RemoveFolderEx On="uninstall" Property="AcmeAppDataFolderToRemove" />
and see if that works. (You might need to use Value='ApplicationDataFolder' without the []'s not sure.)
In response to your edit I went and looked at the RemoveFolderEx page and this looks important
The custom action that implements RemoveFolderEx does so by writing temporary rows to the RemoveFile table for each subfolder of the root folder you specify. Because it might dramatically affect Windows Installer's File Costing, the temporary rows must be written before the CostInitialize standard action. Unfortunately, MSI doesn't create properties for the Directory hierarchy in your package until later, in the CostFinalize action.
I figured setting it to the directory would work but apparently these directories don't have values yet when RemoveFolderEx action actually executes. So, when this tries to resolve the properties or set the properties they are actually just empty.
A difference in what I said my installer does and what it actually does is that I get the value I set the property to through a RegistrySearch.
<Property Id="INSTALLDIR">
<RegistrySearch
Id='InstallDirRegistrySearch'
Type='raw'
Root='HKLM'
Key='SOFTWARE\$(var.OEMRegistryRootKeyName)'
Name='SDKPath' />
</Property>
<SetProperty Id='SDKFolderToRemove' Value='[INSTALLDIR]\$(var.OEMProduct) SDK' After='AppSearch'/>
So I would try writing the appdata dir to a registry key and getting the value into a property via registry search then using that property in your removefolderex, you probably don't need the setproperty, I just used it because I needed a folder under INSTALLDIR but in your case you can just have the registry key be the right folder.

install asp.net application on IIS using wix without IIS backward compatibilty on

I have created WiX installer that installs website in IIS but I have to keep IIS backward compatibility on.
<Component Id="VirtualDirectoryWebAppPool" Guid="{GIUD}" Permanent="yes">
<iis:WebAppPool Id="WebAppPool" Name="${ProductName}" ManagedRuntimeVersion="v4.0" ManagedPipelineMode="integrated" />
<CreateFolder />
</Component>
<Component Id="VirtualDirectoryWithoutWinAuth" Guid="{GUID}" Permanent="yes">
<Condition>TYPEOFAUTHENTICATION = "Forms"</Condition>
<iis:WebVirtualDir Id="WebVirtualDirectoryWithoutWinAuth" Alias="[VDNAME]" Directory="WEBUIFOLDER" WebSite="DefaultWebSite" >
<iis:WebApplication Id="WebApplicationWithoutWinAuth" Name="[VDNAME]" WebAppPool="WebAppPool" />
<iis:WebDirProperties Id="WebDirectoryPropertiesWithoutWinAuth" AnonymousAccess="yes" WindowsAuthentication="no" />
</iis:WebVirtualDir>
<CreateFolder />
</Component>
<Component Id="VirtualDirectoryWithWinAuth" Guid="{GIUD}" Permanent="yes">
<Condition>TYPEOFAUTHENTICATION = "Windows"</Condition>
<iis:WebVirtualDir Id="WebVirtualDirectoryWithWinAuth" Alias="[VDNAME]" Directory="WEBUIFOLDER" WebSite="DefaultWebSite" >
<iis:WebApplication Id="WebApplicationWithWinAuth" Name="[VDNAME]" WebAppPool="WebAppPool" />
<iis:WebDirProperties Id="WebDirectoryPropertiesWithWinAuth" AnonymousAccess="yes" WindowsAuthentication="yes" />
</iis:WebVirtualDir>
<CreateFolder />
</Component>
...
<iis:WebSite Id="DefaultWebSite" Description="Default Web Site" Directory="WEBUIFOLDER">
<iis:WebAddress Id="AllUnassigned" Port="80" />
</iis:WebSite>
But I do not want to keep the IIS backward compatibility on.

Make WiX installation set upgrade to the same folder

How can I make a major upgrade to an installation set (MSI) built with WiX install into the same folder as the original installation?
The installation is correctly detected as an upgrade, but the directory selection screen is still shown and with the default value (not necessarily the current installation folder).
Do I have to do manual work like saving the installation folder in a registry key upon first installing and then read this key upon upgrade? If so, is there any example?
Or is there some easier way to achieve this in MSI or WiX?
As reference, I my current WiX file is below:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2003/01/wi">
<Product Id="a2298d1d-ba60-4c4d-92e3-a77413f54a53"
Name="MyCompany Integration Framework 1.0.0"
Language="1033"
Version="1.0.0"
Manufacturer="MyCompany"
UpgradeCode="9071eacc-9b5a-48e3-bb90-8064d2b2c45d">
<!-- Package information -->
<Package Keywords="Installer"
Id="e85e6190-1cd4-49f5-8924-9da5fcb8aee8"
Description="Installs MyCompany Integration Framework 1.0.0"
Comments="Installs MyCompany Integration Framework 1.0.0"
InstallerVersion="100"
Compressed="yes" />
<Upgrade Id='9071eacc-9b5a-48e3-bb90-8064d2b2c45d'>
<UpgradeVersion Property="PATCHFOUND"
OnlyDetect="no"
Minimum="0.0.1"
IncludeMinimum="yes"
Maximum="1.0.0"
IncludeMaximum="yes"/>
</Upgrade>
<!-- Useless but necessary... -->
<Media Id="1" Cabinet="MyCompany.cab" EmbedCab="yes" />
<!-- Precondition: .NET 2 must be installed -->
<Condition Message='This setup requires the .NET Framework 2 or higher.'>
<![CDATA[MsiNetAssemblySupport >= "2.0.50727"]]>
</Condition>
<Directory Id="TARGETDIR"
Name="SourceDir">
<Directory Id="MyCompany"
Name="MyCompany">
<Directory Id="INSTALLDIR"
Name="Integrat"
LongName="MyCompany Integration Framework">
<Component Id="MyCompanyDllComponent"
Guid="4f362043-03a0-472d-a84f-896522ce7d2b"
DiskId="1">
<File Id="MyCompanyIntegrationDll"
Name="IbIntegr.dll"
src="..\Build\MyCompany.Integration.dll"
Vital="yes"
LongName="MyCompany.Integration.dll" />
<File Id="MyCompanyServiceModelDll"
Name="IbSerMod.dll"
src="..\Build\MyCompany.ServiceModel.dll"
Vital="yes"
LongName="MyCompany.ServiceModel.dll" />
</Component>
<!-- More components -->
</Directory>
</Directory>
</Directory>
<Feature Id="MyCompanyProductFeature"
Title='MyCompany Integration Framework'
Description='The complete package'
Display='expand'
Level="1"
InstallDefault='local'
ConfigurableDirectory="INSTALLDIR">
<ComponentRef Id="MyCompanyDllComponent" />
</Feature>
<!-- Task scheduler application. It has to be used as a property -->
<Property Id="finaltaskexe"
Value="MyCompany.Integration.Host.exe" />
<Property Id="WIXUI_INSTALLDIR"
Value="INSTALLDIR" />
<InstallExecuteSequence>
<!-- command must be executed: MyCompany.Integration.Host.exe /INITIALCONFIG parameters.xml -->
<Custom Action='PropertyAssign'
After='InstallFinalize'>NOT Installed AND NOT PATCHFOUND</Custom>
<Custom Action='LaunchFile'
After='InstallFinalize'>NOT Installed AND NOT PATCHFOUND</Custom>
<RemoveExistingProducts Before='CostInitialize' />
</InstallExecuteSequence>
<!-- execute comand -->
<CustomAction Id='PropertyAssign'
Property='PathProperty'
Value='[INSTALLDIR][finaltaskexe]' />
<CustomAction Id='LaunchFile'
Property='PathProperty'
ExeCommand='/INITIALCONFIG "[INSTALLDIR]parameters.xml"'
Return='asyncNoWait' />
<!-- User interface information -->
<UIRef Id="WixUI_InstallDir" />
<UIRef Id="WixUI_ErrorProgressText" />
</Product>
</Wix>
There's an example in the WiX tutorial: https://www.firegiant.com/wix/tutorial/getting-started/where-to-install/
<Property Id="INSTALLDIR">
<RegistrySearch Id='AcmeFoobarRegistry' Type='raw'
Root='HKLM' Key='Software\Acme\Foobar 1.0' Name='InstallDir' />
</Property>
Of course, you've got to set the registry key as part of the install too. Stick this inside a component that's part of the original install:
<RegistryKey
Key="Software\Software\Acme\Foobar 1.0"
Root="HKLM">
<RegistryValue Id="FoobarRegInstallDir"
Type="string"
Name="InstallDir"
Value="[INSTALLDIR]" />
</RegistryKey>
'Registry' is deprecated. Now that part of code should look like this:
<RegistryKey Id="FoobarRegRoot"
Action="createAndRemoveOnUninstall"
Key="Software\Software\Acme\Foobar 1.0"
Root="HKLM">
<RegistryValue Id="FoobarRegInstallDir"
Type="string"
Name="InstallDir"
Value="[INSTALLDIR]" />
</RegistryKey>
You don't really need to separate RegistryKey from RegistryValue in a simple case like this. Also, using HKMU instead of HKLM takes care of it whether you're doing a machine or user install.
<RegistryValue
Root="HKMU"
Key="Software\[Manufacturer]\[ProductName]"
Name="InstallDir"
Type="string"
Value="[INSTALLDIR]"
KeyPath="yes" />