When I run my installer I get the following issue.
I'm doing some custom actions which require to access the registry and I can only think that its because the WiX configuration doesn't make it request admin priveleges. I've looked at some posts on SO and tried to use.
InstallPriveleges="elevated"
within the package element however this does not make the installer have the admin shield nor request it therefore still producing the error.
Extra information about test project.
The name of my application is :WindowsFormsApplication33, the name of the custom action project is CustomAction1 and name of the Setup project is SetupProject1.
This is my current wix xml file.
<Package InstallerVersion="200" Compressed="yes" InstallPrivileges="elevated" InstallScope="perUser" />
<Binary Id="CustomAction1.CA.dll" SourceFile ="..\CustomAction1\bin\$(var.Configuration)\CustomAction1.CA.dll" />
<CustomAction Id="disableTaskManager"
Return="check"
Execute="immediate"
BinaryKey="CustomAction1.CA.dll"
DllEntry="disableTaskManager" />
<CustomAction Id="enableTaskManager"
Return="check"
Execute="immediate"
BinaryKey="CustomAction1.CA.dll"
DllEntry="enableTaskManager" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="SetupProject1" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
<InstallExecuteSequence>
<Custom Action="disableTaskManager" Before="InstallFinalize" />
<Custom Action="enableTaskManager" After="InstallInitialize"><![CDATA[(NOT UPGRADINGPRODUCTCODE)]]></Custom>
</InstallExecuteSequence>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="Form Test Application" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Guid="{EDA315F6-A115-4348-8607-981C252EA317}">
<File Source="$(var.WindowsFormsApplication33.TargetPath)" KeyPath ="yes" />
</Component>
<Component Guid="{E3182F61-F563-4C13-82B5-8CC39D9DB380}">
<File Source="$(var.CustomAction1.TargetPath)" KeyPath ="yes" />
</Component>
<Component Guid="{E4AF325E-B244-47F5-855A-5B40DBC425D2}">
<File Source="..\WindowsFormsApplication33\bin\Release\WindowsFormsApplication33.exe.config" KeyPath="yes" />
</Component>
</ComponentGroup>
</Fragment>
Update : changing the InstallScope value from perUser to "perMachine" does make a UAC prompt however the DLL error still exists..
Your custom action is immediate, that means it will not run with elevation. It must be deferred to run with elevation. It's got nothing to do with WiX particularly, it's just that immediate custom actions run as the user but limited.
I struggled to get rid of the dll error however an alternative I found was to NOT use Custom Action and use the XML in the wix file to create the registry and then delete the key when uninstalling via the use of :
ForceDeleteOnUninstall="yes"
You have to use this in the
Example :
<!-- Register windows autostart registry -->
<Component Id="RegistryEntries" Guid="45C7AC46-1101-4301-83E1-D24392283A60">
<RegistryValue Type="string"
Name="FooStartup"
Value="[#FooMainApp]"
Root="HKLM"
Key="Software\Microsoft\Windows\CurrentVersion\Run"
Action="write"/>
</Component>
As found on : Registry change upon installing application C#
I really hope this helps someone new to WiX as it did to me.
Use these three attributes inside custom action tag.
<CustomAction ....
Execute="deferred"
Impersonate="no"
Return="ignore" />
These fields will make the custom action to run with admin priveleges.
Related
I have the wix project installer.
I want to use the update new version of my product.
It works fine, but still shows me all dialogs and I need to enter params.(such as install path, user credential and other).
How can I skip all dialogs and using all of these params from older (prev) installer version.
<Product Id="*" Name="$(var.ProductName) $(var.ProductVersion)" Language="1033" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
<Package InstallerVersion="301" Compressed="yes" InstallScope="perMachine" Platform="x64" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." AllowSameVersionUpgrades="yes" />
<MediaTemplate EmbedCab="yes" />
<Feature Id="ProductFeature" Title="COMPANY.Product.Installers.Server" Level="1">
<ComponentGroupRef Id="ProductComponents" />
<ComponentGroupRef Id="ServerInstallerFiles" />
</Feature>
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" ></Property>
<UIRef Id="WixUI_MinimalCustom"/>
<InstallExecuteSequence>
<Custom Action="DoAfterInstallJobParams" Before="DoAfterInstallJob">Not Installed or REINSTALL</Custom>
<Custom Action="DoAfterInstallJob" After="InstallFiles">Not Installed or REINSTALL</Custom>
<Custom Action="DoBeforeUnstallJob" After="InstallInitialize">REMOVE="ALL"</Custom>
</InstallExecuteSequence>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Directory Id="INSTALLFOLDER" Name="COMPANY" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<Property Id="DoBeforeUninstallJob" Value="[INSTALLFOLDER]" />
<Binary Id="CustomActionBinary" SourceFile="$(var.SolutionDir)Output\Installers\Actions\COMPANY.Product.Installers.Server.Actions.CA.dll" />
<CustomAction Id="DoAfterInstallJob" BinaryKey="CustomActionBinary" DllEntry="AfterInstall" Execute="deferred" Return="check" Impersonate="no" />
<CustomAction Id="DoAfterInstallJobParams" Property="DoAfterInstallJob" Value="HOSTING_URL=[HOSTING_URL];DB_CONNECTION=[DB_CONNECTION];INSTALLPATH=[INSTALLFOLDER];LOGIN=[LOGIN];PASSWORD=[PASSWORD]" />
<CustomAction Id="DoBeforeUnstallJob" BinaryKey="CustomActionBinary" DllEntry="BeforeUninstall" Execute="deferred" Return="check" Impersonate="no" />
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<ComponentRef Id="cmpServerHost"/>
</ComponentGroup>
</Fragment>
<Fragment>
<DirectoryRef Id="INSTALLFOLDER">
<Directory Id="ServerHost" Name="ServerHost">
<Component Win64="yes" Id="cmpServerHost" Guid="a4a81104-1e30-463d-87e1-e8a79b4c6829">
<File Id="ServerLog4netConfig" Source="$(var.SolutionDir)..\Logging\log4net.config" />
<RegistryValue Root="HKLM" Key="Software\[Manufacturer]\$(var.ProductName)" Type="string" Value="[INSTALLFOLDER]" KeyPath="yes" Name="COMPANYInstallPath"/>
<File Id="AppVersion" Source="$(var.SolutionDir)Output\Installers\Actions\COMPANY.Product.Installers.Server.Actions.CA.dll" />
</Component>
</Directory>
</DirectoryRef>
</Fragment>
Windows Installer does not persist properties. You have to do it yourself. Here is an example.
http://robmensching.com/blog/posts/2010/5/2/the-wix-toolsets-remember-property-pattern/
Remember Properties: Persisting properties allows you to read back the settings from the first version.
Dialog Control & Order: In order to skip dialogs you need to detect whether a major upgrade is taking place, if you use major
upgrades (which you do based on that source file), and then control
the dialog flow accordingly using conditioning and property values. This requires quite a bit of work and
testing. I would avoid it if you can.
Easy Mode: Just disabling (write protect) or hiding the dialogs fields that contain settings written in the first setup might be
preferable (rather than changing the dialog sequence). You can use conditions and conditioning for both purposes.
Maintenance GUI: For minor upgrades, repair and uninstall the dialog set will be different from the original installation. You will get a "maintenance dialog set" presented rather than the "installation dialog set".
Major Upgrade: A pecularity occurs when you install upgrades via Windows Installer's major upgrade mechanism. Because of how this works technically you get the installation dialog set for the new version as well. This is because it is technically a fresh install of that new product code. The fact that the older version gets uninstalled as part of the process is besides the point. You are not installing a new minor version, you are uninstalling and reinstalling effectively.
WIX_UPGRADE_DETECTED: There is a property that is set in a standard WiX package. It is WIX_UPGRADE_DETECTED. It can be used to detect when a major upgrade is taking place and hence used in conditions to adjust the dialog order of a major upgrade installation. Here are more details on this property, along with description of UPGRADINGPRODUCTCODE - which is another property that is set in the setup being uninstalled (not in the new one being installed).
Here is a quick list of different ways to change WiX GUI.
Wix, custom dialog when previous version exists (customize dialogs when previous version exists).
Ran out of time. Persisting this, will update later.
Some Links:
Removing Default dialogs from MSI
I have a batch script in Installation Directory. I have to execute this batch script as part of MSI Uninstall.
Firstly, To know the location of the Install directory, I am doing RegistrySearch with below piece of code
<Property Id="REGISTRY_RESULT">
<RegistrySearch Id="MyRegistrySearch"
Root="HKCU"
Key="Software\InstallPath"
Name="path"
Type="raw" />
</Property>
I have created custom action to call the batch script.
<SetProperty Id="CMD" Value="C:\Windows\System32\cmd.exe" Before="CostFinalize" />
<CustomAction Id="RunBat" Property="CMD" Execute="deferred" Impersonate="no" Return="check" ExeCommand="[**??REGISTRYSEARCH??**}\RunBat.bat"/>
Custom Action already has one Property Set to "CMD". Now, How to pass REGISTRY_RESULT to my Custom action? Can someone help?
This is how I managed to do this (without using SetProperty):
<Property Id="REGISTRY_RESULT">
<RegistrySearch Id="MyRegistrySearch"
Root="HKLM"
Key="Software\MyProgram"
Name="InstallDir"
Type="raw"/>
</Property>
<CustomAction Id="RunBat" Directory="INSTALLFOLDER" Execute="deferred" Impersonate="no" Return="check" ExeCommand="[SystemFolder]cmd.exe /C [REGISTRY_RESULT]\RunBat.bat"/>
This is the full code of my test wix project that I created, in case you need it:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="ConsoleApp" Language="1033" Version="1.0.0.0" Manufacturer="SoftwareCompany" UpgradeCode="8b78c2e7-47cf-4b25-a0f9-4b648db7336e">
<Package InstallerVersion="500" Compressed="yes" InstallScope="perMachine" />
<MediaTemplate EmbedCab="yes"/>
<Feature Id="ProductFeature" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="ConsoleApp" />
</Directory>
</Directory>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="cmpConsoleApp.exe" Guid="*">
<File Id="ConsoleApp.exe" KeyPath="yes" Source="d:\Learning\WIX\WixTraining\ConsoleApp\bin\Debug\ConsoleApp.exe" />
</Component>
</ComponentGroup>
<Property Id="REGISTRY_RESULT">
<RegistrySearch Id="MyRegistrySearch"
Root="HKLM"
Key="Software\MyProgram"
Name="InstallDir"
Type="raw"/>
</Property>
<CustomAction Id="RunBat" Directory="INSTALLFOLDER" Execute="deferred" Impersonate="no" Return="check" ExeCommand="[SystemFolder]cmd.exe /C [REGISTRY_RESULT]\RunBat.bat"/>
<InstallExecuteSequence>
<Custom Action="RunBat" Before="InstallFinalize">NOT Installed</Custom>
</InstallExecuteSequence>
</Product>
</Wix>
Notice how I wrote my CustomAction, I did not specify property attribute and instead used Directory (Wix forces you to have Directory attribute), I also used ExeCommand="[SystemFolder]cmd.exe /C [REGISTRY_RESULT]\RunBat.bat" whic basically means take cmd.exe from SystemFolder which is C:\Windows\System32\cmd.exe and run batch file RunBat.bat which is in REGISTRY_RESULT folder.
That worked for me, if you still have troubles running your batch file I assume there might be some problems with your RegistrySearch, I suggest you running your msi file with logging enabled (open cmd and type msiexec /i "PATH_TO_YOUR_MSI" /L*V "log.txt") then look into the log.txt and search for REGISTRY_RESULT property, if everything is okay you should see a line REGISTRY_RESULT = {PATH_TO_InstallDir}, if you don't see it than probably this key doesn't exist, alos make sure that you didn't mix up HKCU and HKLM and you indicated the correct one.
my idea is make an uninstall file with .msi install file. I read some information about creating uninstaller shortcut here: http://wixtoolset.org/documentation/manual/v3/howtos/files_and_registry/create_uninstall_shortcut.html , But i cant found information about make uninstall file after msi build , maybe whom know it's possible ? and if possible how i can do it ? or maybe it possible to do with cmd script? Just write script for automatically uninstall my program from mashine. My code is :
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"><?define WpfApp1_TargetDir=$(var.WpfApp1.TargetDir)?>
<Product Id="*" Name="SetupProject2" Language="1033" Version="1.0.0.0" Manufacturer="Andrejka" UpgradeCode="PUT-GUID-HERE">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<Property Id="WIXUI_INSTALLDIR" Value="TESTFILEPRODUCTDIR" />
<Property Id="WixShellExecTarget" Value="[#WpfApp1.exe]" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
<Property Id="LAUNCH_APP_ON_EXIT" Value="1" />
<InstallExecuteSequence>
<Custom Action='LaunchApplication' After='InstallFiles'/>
</InstallExecuteSequence>
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes"/>
<Feature Id="ProductFeature" Title="SetupProject2" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="TESTFILEPRODUCTDIR" Name="SetupProject2">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="SetupProject2" />
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
<!-- <Component Id="ProductComponent"> -->
<!-- TODO: Insert files, registry keys, and other resources here. -->
<!-- </Component> -->
<Component Id="WpfApp1.exe" Guid="*">
<File Id="WpfApp1.exe" Name="WpfApp1.exe" Source="$(var.WpfApp1_TargetDir)WpfApp1.exe" />
</Component>
<Component Id="WpfApp1.exe.config" Guid="*">
<File Id="WpfApp1.exe.config" Name="WpfApp1.exe.config" Source="$(var.WpfApp1_TargetDir)WpfApp1.exe.config" />
</Component>
<Component Id="aws_sdk_net_core_support.dll" Guid="*">
<File Id="aws_sdk_net_core_support.dll" Name="aws-sdk-net-core-support.dll" Source="$(var.WpfApp1_TargetDir)aws-sdk-net-core-support.dll" />
</Component>
<Component Id="AWSSDK.Core.dll" Guid="*">
<File Id="AWSSDK.Core.dll" Name="AWSSDK.Core.dll" Source="$(var.WpfApp1_TargetDir)AWSSDK.Core.dll" />
</Component>
<Component Id="AWSSDK.SimpleNotificationService.dll" Guid="*">
<File Id="AWSSDK.SimpleNotificationService.dll" Name="AWSSDK.SimpleNotificationService.dll" Source="$(var.WpfApp1_TargetDir)AWSSDK.SimpleNotificationService.dll" />
</Component>
<Component Id="MimeSharp.dll" Guid="*">
<File Id="MimeSharp.dll" Name="MimeSharp.dll" Source="$(var.WpfApp1_TargetDir)MimeSharp.dll" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
In general you are not supposed to put uninstall shortcuts in the start menu, it is in fact a violation of Microsoft's logo requirements for Windows applications I believe. Rather you should let people uninstall your product the normal way via the add/remove programs applet.
UPDATE: I found this answer with some more information on this topic: Shortcuts with name "Uninstall <Program Name>" are not displayed in Windows 8/8.1/10
Also, just so it is clear, uninstall, is a built-in feature of MSI files - it is always automatically available unless actively blocked (such as some applications hiding themselves from display in add/remove programs). There is nothing extra you have to do in your WiX sources to support uninstall properly. Just follow Windows Installer guidelines and it comes "for free".
If what you are asking is for a way to create an uninstall batch file, then you can find a plethora of ways to uninstall your MSI file in this "uninstall reference": Uninstalling an MSI file from the command line without using msiexec.
In short, just run the command line below to uninstall your MSI if you have the MSI's product code (you can find your product code by querying your system as described here: How can I find the product GUID of an installed MSI setup? - you might need to look it up since you auto-generate your product code):
msiexec.exe /x {your-product-guid}
or just uninstall by referring to your original MSI installation file like this:
msiexec.exe /x "c:\filename.msi
See the linked answer above (the uninstall reference) for a lot more information about this.
I want to create a WIX Installer (3.8) that only installs silently.
I'm using the Wix file attached to demonstrate my issue.
At
UILevel=2
<InstallExecuteSequence>
<FindRelatedProducts Before="LaunchConditions">UILevel=2</FindRelatedProducts>
</InstallExecuteSequence>
I'm setting the UI level to 2
According to:
msdn.microsoft.com/en-us/library/aa372096%28v=vs.85%29.aspx
then it's:
"
INSTALLUILEVEL_NONE 2 Completely silent installation.
"
So far so good. I can install the "product" which is nothing but an empty directory.
When I set the product's version to: Version="1.1.0.0" and want to do a major upgrade everything also works fine.
When I look at the program an feature "tool" from Microsoft
as shown here:
http://windows.microsoft.com/en-us/windows/uninstall-change-program#uninstall-change-program=windows-7
I see both versions (version 1.0.0.0 and 1.1.0.0) which is not what I expected the Wix installer should do.
When I remove
<InstallUISequence>
<FindRelatedProducts Before="LaunchConditions">UILevel=2</FindRelatedProducts>
</InstallUISequence>
<InstallExecuteSequence>
<FindRelatedProducts Before="LaunchConditions">UILevel=2</FindRelatedProducts>
</InstallExecuteSequence>
from the Wix script, install Version 1.0.0.0 and later after changing the wix script to 1.1.0.0
and major upgrading again,
I only see 1 version (1.1.0.0) at the program an feature "tool" from Microsoft
( windows.microsoft.com/en-us/windows/uninstall-change-program#uninstall-change-program=windows-7 )
which is what I expect the windows installer should do.
So my question would be:
What is missing or wrong at the script
( that the program an feature "tool" from Microsoft shows 2 Versions after a major upgrade )
Wix script:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="SetupProject1" Language="1033" Version="1.1.0.0" Manufacturer="asdf" UpgradeCode="BE170BF6-0C06-4A50-B81B-CDF6609FAD5A">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perUser" InstallPrivileges="limited" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." Schedule="afterInstallInitialize" />
<MediaTemplate />
<InstallUISequence>
<FindRelatedProducts Before="LaunchConditions">UILevel=2</FindRelatedProducts>
</InstallUISequence>
<InstallExecuteSequence>
<FindRelatedProducts Before="LaunchConditions">UILevel=2</FindRelatedProducts>
</InstallExecuteSequence>
<Feature Id="ProductFeature" Title="SetupProject1" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="LocalAppDataFolder">
<Directory Id="INSTALLFOLDER" Name="SetupProject1" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="test" Guid="D6527568-4C76-493B-AF1F-9E973723E773"
SharedDllRefCount="no" KeyPath="no" NeverOverwrite="no" Permanent="no" Transitive="no"
Win64="no" Location="either">
<CreateFolder/>
<RemoveFolder Id="ProductComponents" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\MyFantasyCompany\MyApplicationName" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</ComponentGroup>
</Fragment>
</Wix>
First, there's no such thing as WiX script. WiX is not a imperative programming language, it's a declarative language.
Your major upgrade is failing because the condition on FindRelatedProducts is evaluating to false which means it can never detect the ProductCode of the previous MSI and remove it as part of the upgrade.
If you really want a silent install only, why not just omit a UI from the installer? Personally I have no idea why you are trying to do this and it doesn't follow established best practices.
I am having problems setting the TARGETDIR path. I used dark.exe to reverse engineer a working MSI file and read any posts I could find on this subject, but I seem to be unable to set the TARGETDIR to point to the path ProgramFiles\Manufacturer\Product. Below is a distilation of my WXS file which results in my application being installed to the root of my D-drive for some reason:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*"
Name="FBL - Some App"
Language="1033"
Version="1.0.0.0"
Manufacturer="Foo & Bar Limited"
UpgradeCode="780286c6-e064-4402-80d8-dd2c68b56c04">
<Package InstallerVersion="200"
Compressed="yes"
InstallScope="perMachine"
Comments="Performs some operation that is important" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<Media Id="1" Cabinet="App.1.0.0.cab" EmbedCab="yes" />
<CustomAction Id="setTARGETDIR"
Property="TARGETDIR"
Value="[ProgramFilesFolder][Manufacturer]\[ProductName]"
Execute="firstSequence"
Return="check" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Component Id="C__App.exe"
Guid="{074586E9-A675-2734-A4CD-1CE520922A41}">
<File Id="F__App.exe"
Name="App.exe"
KeyPath="yes"
Assembly=".net"
AssemblyManifest="F__App.exe"
AssemblyApplication="F__App.exe"
DiskId="1"
Source="D:\SomePath\bin\Debug\App.exe" />
</Component>
</Directory>
<Feature Id="DefaultFeature" ConfigurableDirectory="TARGETDIR" Level="1">
<ComponentRef Id="C__App.exe" Primary="yes" />
</Feature>
<Icon Id="favicon.ico" SourceFile="d:\SomePath\favicon.ico" />
<Property Id="ARPPRODUCTICON" Value="favicon.ico" />
<UI />
<InstallExecuteSequence>
<Custom Action="setTARGETDIR" Before="CostFinalize" />
</InstallExecuteSequence>
</Product>
</Wix>
I'm sure I am missing something simple, but I cannot find any further information on what to do from here.
The following modifications were needed:
<CustomAction Id="SetTARGETDIR"
Directory="TARGETDIR"
Value="[ProgramFilesFolder][Manufacturer]\[ProductName]"
Return="check" />
and
<InstallExecuteSequence>
<Custom Action="SetTARGETDIR" After="InstallValidate" />
</InstallExecuteSequence>
Explanation: Use the Directory attribute instead of a property (it's a type 35 custom action) and schedule this action after InstallValidate in the execute sequence - that's when directories are checked for write access and truly set.
(Thanks to Narina Chandra Sekhar, from the WiX user group for the answer on this.)
This is strange...I had the same issue but your answer didn't work for me. All I needed was this:
<Product>
<SetProperty Id='TARGETDIR' Value='[ProgramFilesFolder][Manufacturer]\[ProductName]\' Before='FindRelatedProducts' />
...
</Product>
But then again I think something else in my installer may have been setting the TARGETDIR directory from the property; I was working with some legacy stuff.
Edit: Actually, that was a bad idea. A lot of times, some of these custom actions that are built in can be called at different parts of the installation process, so its just better to add a custom action to set the property.
Here is what worked for me:
<Product>
<CustomAction Id='SetTARGETDIR' Property='TARGETDIR' Value='[ProgramFilesFolder][Manufacturer]\[ProductName]\'/>
...
</Product>
<InstallUISequence>
<Custom Action='SetTARGETDIR' Sequence='1'/>
...
</InstallUISequence>
<AdminUISequence>
<Custom Action='SetTARGETDIR' Sequence='1'/>
...
</AdminUISequence>
Nothing worked for me so what I did is to run the msi with a command line setting the property of the installation directory. By default my program would be installed to drive C but sometimes I wanted it to be installed to D drive so here is what I did:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="APPLICATIONROOTDIRECTORY" Name="XServer">
</Directory>
</Directory>
</Directory>
Here is the command line:
XServer.msi /L*v log.log APPLICATIONROOTDIRECTORY="D:\Program Files (x86)\XServer"
This actually worked for me. The CostFinalize action is where TARGETDIR Directory is defined.
<SetProperty Id="TARGETDIR" Value="[ROOTDRIVE]MyCompany" Sequence="first" Before="CostFinalize">NOT Installed AND NOT TARGETDIR</SetProperty>
I tried changing the installation dir via custom action (cause I needed code to figure out the path with code - long story), and what solved it for me what the timing - I had to schedule the custom action to:
After="CostInitialize"