We are using Wix V3.11 to build an msi setup for our C#-Application. We have a 32 Bit and an 64 Bit build for each version:
The preallocated installation path for the 32 Bit build is: 'C:\Program Files (x86)'.
The preallocated installation path for the 64 Bit setup is: 'C:\Program Files'.
We use the following declaration to set the paths:
<?define bitness = $(var.Platform) ?>
<?if $(var.Platform) = "x86" ?>
<?define ProgramFilesPath = ProgramFilesFolder?>
<?define Win64 = no?>
<?else?>
<?define ProgramFilesPath = ProgramFiles64Folder?>
<?define Win64 = yes?>
<?endif?>
Using the variable here:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="$(var.ProgramFilesPath)" Name="$(var.ProgramFilesPath)">
[... more folder ...]
</Directory>
</Directory>
The Problem: When the consumer changes the path for the first installation to e.g. 'C:/MyFolder' and executes an updade, then the msi setup moves the software to 'C:\Program Files (x86)' or 'C:\Program Files'.
Question: How can I keep the custom installation path 'C:/MyFolder' of the first installation on an update? Perhaps is there any 'update' condition I can use? My imagination:
<?define bitness = $(var.Platform) ?>
<?if UPDATE ?> <!-- here -->
<?if $(var.Platform) = "x86" ?>
<?define ProgramFilesPath = ProgramFilesFolder?>
<?define Win64 = no?>
<?else?>
<?define ProgramFilesPath = ProgramFiles64Folder?>
<?define Win64 = yes?>
<?endif?>
<?endif?>
Let's assume that by "update" you mean a major upgrade because it would be extremely strange if a patch or minor update moved all the files from one location to another.
If you are using the usual WiX property name, then the directory chosen by the user will be INSTALLFOLDER, although it's not clear if you are using that or TARGETDIR. Basically you can store the user's final choice in a registry item (or use the WiX "remember property" pattern). On a major upgrade you can retrieve that property and set your INSTALLFOLDER value to that directory on condition that WIX_UPGRADE_DETECTED is set (the default property id used in the major upgrade element). Presumably you will also suppress the browse dialog that allows the user to choose the folder.
Having said that:
It's not clear why you don't want the user to install the major upgrade to a new location if they want to, if the app continues to work.
Those default folders aren't really preallocated - they are just the standard defaults. They are the recommended locations so it might be better to disallow changing them because of the opportunities for unexpected behavior. For example, attempting to install the 32-bit MSI to the native program files folder on an x64 system will result in redirection to the program files (x86) location, which may surprise the user.
Related
I have a large .wxs file and a requirement to change the Product Name from MyApp Workstation version to MyApp Server version when the installer is launched on a Windows Server operating system. I read a lot and I found out that I need to relate to the following MSI property MsiNTProductType which returns the value 1 for workstation and 2 or 3 for server operating systems.
<?xml version="1.0" encoding="UTF-8"?>
<?define ProductName = "MyApp Workstation version" ?>
<Wix>
<Product Name="$(var.ProductName)" ... >
...
</Product>
</Wix>
If I use a condition like the following, it detects that I am on a workstation operating system (in my case Windows 10), but this is not what I want:
<Condition Message="This installer is for Windows Server only!">
<![CDATA[(MsiNTProductType > 1)]]>
</Condition>
I tried the preprocessor variable approach, but evidently it does not work:
<?if MsiNTProductType = 1 ?>
<?define ProductName = "MyApp Workstation version" ?>
<?else ?>
<?define ProductName = "MyApp Server version" ?>
<?endif ?>
I also tried SetProperty and CustomAction without any luck. I am stuck at this.
Is it possible to do something like this? What changes do I have to make to accomplish this? I am very new to WIX and I do not understand how it is supposed to work. Thank you.
LATER EDIT AND SOLUTION
After many days of trying tens of combinations, I was able to do this with the following code which I put before any CustomActions that were already defined:
<Property Id="ConditionalProductName" Value="MyApp Workstation version" />
<SetProperty Id="ConditionalProductName" Before="LaunchConditions" Value="MyApp Server version" >
<![CDATA[(MsiNTProductType > 1)]]>
</SetProperty>
<SetProperty Id ="ProductName" Before ="LaunchConditions" Value ="[ConditionalProductName]"/>
I hope this may help others too. Good luck.
The ProductName property can only be changed prior to the installation starting. Once MSI is running it's immutable.
The preprocessor statements you are trying effect build time not installation time.
The only way to do what you want is create a transform with the different name and then use a bootstrapper to install the MSI without a transform on a non server OS and install the MSI with a transform on a server OS.
Personally this isn't typical practice so I would push back on the requirement from the PM. The only reason I would go through the effort would be the business really really differentiated the branding on the marketing side. Otherwise this just isn't normally done.
I have a C# application which its build targets are x86 or x64. The build output is (for example) ProjectDir/bin/x86|x64/Debug|Release/*
In my *.wxs file I have defined thr following variable
<?define AppTargetPath = "$(var.MyApp.TargetPath)" ?>
Which points to ProjectDir/bin/Debug|Release/app.exe
If I build the installer, it fails because it does not find my app exe
<File Id="AppExe" Source="$(var.AppTargetPath)" KeyPath="yes"/>
If I look on Using Project References and Variables site (http://wixtoolset.org/documentation/manual/v3/votive/votive_project_references.html) I cannot find another variable.
Maybe try this:
Comment out your existing define.
Add the project building the EXE and your WiX project to the same solution.
Add a reference from the WiX project to the EXE / Binary project.
Try this markup (replace project name "TestConsoleApplication" with yours):
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component>
<File Source="$(var.TestConsoleApplication.TargetPath)" />
</Component>
</ComponentGroup>
</Fragment>
Rebuild All.
Toggle Release and Debug builds, then Rebuild All again.
Links:
Summary: My WiX Quick Start Tips.
Basic WiX Project: Step-by-step, Hello WiX project.
Real-World Sample: Real-World Example: WiX/MSI Application Installer
Actually I solved it by putting together the entire path on top of my wxs file:
<?define AppTargetFileName = "$(var.myApp.TargetFileName)" ?>
<?if $(var.Platform) = x64 ?>
<?define AppTargetPath = "$(var.myApp.ProjectDir)\bin\x64\$(var.myApp.Configuration)\$(var.AppTargetFileName)" ?>
<?elseif $(var.Platform) = x86 ?>
<?define AppTargetPath = "$(var.myApp.ProjectDir)\bin\x86\$(var.myApp.Configuration)\$(var.AppTargetFileName)" ?>
<?else ?>
<?define AppTargetPath = "$(var.myApp.TargetPath)" ?>
<?endif ?>
I have a Wix install project in Visual Studio 2012 and have an xml node like
<MsiPackage ... DownloadUrl="http://uat.mywebsite.com/MyMSI.msi">
I want to change the url depending on the build configuration. i.e. in uat I want it to be http://uat.mywebsite.com/... and in release http://mywebsite.com/...
Is this possible, and if so how do I do it?
Your WiX project has access to build parameters, like the Configuration (debug or release). You can conditionally include the correct DownloadUrl for the current configuration by referencing $(var.Configuartion) in your component declarations:
Not tested this but something similar should work:
<?if $(var.Configuartion) = Release?>
<?define DownloadUrl = "http://uat.mywebsite.com/" ?>
<?elseif $(var.Configuartion) = Debug?>
<?define DownloadUrl = "http://mywebsite.com/" ?>
<?endif ?>
<MsiPackage ... DownloadUrl="$(var.DownloadURL)">
What's up with my launch condition? It's supposed to prevent the x86 installer from running on a 64-bit system, but it seems to have no effect.
<!-- Launch Condition to check that x64 installer is used on x64 systems -->
<Condition Message="64-bit operating system was detected, please use the 64-bit installer.">
<![CDATA[VersionNT64 AND ($(var.Win64) = "no")]]>
</Condition>
var.Win64 is derived from the MSBuild variables like this:
<!-- Define platform-specific names and locations -->
<?if $(var.Platform) = x64 ?>
<?define ProductName = "$(var.InstallName) (x64)" ?>
<?define Win64 = "yes" ?>
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
<?define PlatformCommonFilesFolder = "CommonFiles64Folder" ?>
<?else ?>
<?define ProductName = "$(var.InstallName) (x86)" ?>
<?define Win64 = "no" ?>
<?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
<?define PlatformCommonFilesFolder = "CommonFilesFolder" ?>
<?endif ?>
I would like to solve my problem, but I'd also be interested to hear about strategies for troubleshooting this type of problem.
According to the LaunchCondition table definition:
Expression that must evaluate to True for installation to begin.
Your condition consists of 2 parts: the first one evaluates at install time, the other one evaluates at build time. So, for x86 package the second part of condition will evaluate to "no" = "no" at build time, which obviously gives True at install time. And the first part - VersionNT64 - is defined (and thus, True) on x64 machines. That's why the whole condition is True and installation starts.
You can rewrite your condition as follows:
<Condition Message="64-bit operating system was detected, please use the 64-bit installer.">
<?if $(var.Win64) = "yes" ?>
VersionNT64
<?else?>
NOT VersionNT64
<?endif?>
</Condition>
Hence, in 64-bit package the condition will be just VersionNT64, and will pass and start install. Form x86 package the condition will be NOT VersionNT64, which will obviously fail on 64-bit, but start on 32-bit.
Due to user confusion, our app requires separate installers for 32-bit and 64-bit versions of Windows. While the 32-bit installer runs fine on win64, it has the potential to create support headaches and we would like to prevent this from happening.
I want to prevent the 32-bit MSI installer from running on 64-bit Windows machines. To that end I have the following condition:
<Condition Message="You are attempting to run the 32-bit installer on a 64-bit version of Windows.">
<![CDATA[Msix64 AND (NOT Win64)]]>
</Condition>
With the Win64 defined like this:
<?if $(var.Platform) = "x64"?>
<?define PlatformString = "64-bit"?>
<?define Win64 ?>
<?else?>
<?define PlatformString = "32-bit"?>
<?endif?>
Thing is, I can't get this check to work right. Either it fires all the time, or none of the time. The goal is to check presence of the run-time msix64 variable against the compile-time Win64 variable and throw an error if these don't line up, but the logic is not working how I intend it to. Has anyone come up with a better solution?
Include the Condition element only in your 32-bit package (i.e., using ?if? preprocessor statement). The Condition would be "NOT Msix64": Launch conditions are things that must be true, so if Msix64 is set, the launch condition would fail and that means it's an x64 OS and a 32-bit package and the correct thing to do is to block.
We use the following...
<?if $(var.ProcessorArchitecture)=x86 ?>
<Condition Message="!(loc.LaunchCondition_Error64)">
<![CDATA[Installed OR Not VersionNT64]]>
</Condition>
<?endif?>
The condition element works with windows installer properties, which exist during an installation.
However, you are defining a Win64 as a wix variable, not a windows installer property. Wix variables only exist while the setup is created. You have to reference them as $(var.MyWixVariable) where you use them, and the wix preprocessor will then replace them with their defined value.
I would try this instead:
<?if $(var.Platform) = "x64"?>
<?define PlatformString = "64-bit"?>
<Property Id="Win64" Value="1" />
<?else?>
<?define PlatformString = "32-bit"?>
<?endif?>
If $(var.Platform) has the right value when the setup is created, then this will cause a "Win64" property to be recorded in the windows installer database (i.e. the MSI file) and the property will be available during installation for use in a condition element.
Add this condition
<Condition Message="This is designed for 32bit OS">%PROCESSOR_ARCHITECTURE ~= "x86" AND %PROCESSOR_ARCHITEW6432 <> "amd64"></Condition>
You could create one installer with a 32bit component and a 64bit component and put these two conditions in the respective components
<Component Id="bit32Component" Guid="..." Feature="ProductFeature">
<Condition>%PROCESSOR_ARCHITECTURE~="x86" AND %PROCESSOR_ARCHITEW6432<>"amd64"></Condition>
</Component>
<Component Id="bit64Component" Guid="..." Feature="ProductFeature">
<Condition>%PROCESSOR_ARCHITECTURE~="amd64" OR %PROCESSOR_ARCHITEW6432~="amd64"></Condition>
</Component>
here is a reference I used
http://blogs.msdn.com/david.wang/archive/2006/03/26/HOWTO-Detect-Process-Bitness.aspx