Reputation: 193
With the wix toolset, environment variables are accessible in the .wxs file via the env preprocessor prefix, such as
$(env.TestEnvVariable)
I've configured our build pipeline to set the environment variables I need, and the msi builds fine. However, you can no longer build the .msi locally, because none of the variables are defined in the local development environment.
I'm using the wix extension for visual studio, and I've been trying to update my .wixproj files to set properties like so:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureWixToolsetInstalled" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" xmlns:fg="http://www.firegiant.com/schemas/v3/wxs/fgwep.xsd">
<!-- ... some other bits -->
<PropertyGroup>
<TestEnvVariable>TestValue</TestEnvVariable>
</PropertyGroup>
</Project>
But when I try and build the msi, I get the error
Undefined preprocessor variable '$(env.TestEnvVariable)'
Additionally, I get the same error when trying to access the variable with the 'var' prefix:
Undefined preprocessor variable '$(var.TestEnvVariable)'
I understand that you can set 'var' style preprocessor variables using the define constant element
<PropertyGroup>
<DefineConstants>SomeOtherVariable=someValue</DefineConstants>
</PropertyGroup>
But in our hosted pipelines we are setting these variables as environment variables, because that is easily surfaced in what we're using (azure devops). I could convert all those 'env' variables to 'var' via redefining them all, but that seems unnecessarily complicated, and I would like to maintain their distinction as environment variables. My goal is to allow local dev builds to use the same variable structure, just set them conditionally on configuration=Debug or something.
Is there no better way to set 'env' preprocessor variables for local dev other than conditionally running a batch file to set TestEnvVariable=TestValue
?
Upvotes: 3
Views: 2986
Reputation: 55581
Please take a look at the source code to IsWiX. You'll find an example of pulling the environment variable TF_BUILD_BUILDNUMBER and using it to set the ProductVersion.
The concept is to set an MSBuild property, pass it through to the compiler as a constant and then use it in the Product Version attribute.
Lines 14,21,27
Line 11
Upvotes: 1
Reputation: 193
Alright after a bit of sleeping on it and kicking around, here's the solution that I came to: The main issue that I was encountering was not fully grasping where Environment variables were pulled from by wix, and how that interacted with the MSBuild steps in the .wixproj file.
The solution is to create a custom MSBuild task to set environment variables locally during the build. You can create a custom build task .dll for this, or use the technique described in this answer for more current versions of MSBuild: https://stackoverflow.com/a/20014410/11908758
Basically, in the Project element in your .wixproj you need to define the custom task:
<UsingTask
TaskName="SetEnvironmentVariableTask"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<Name ParameterType="System.String" Required="true" />
<Value ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Using Namespace="System" />
<Code Type="Fragment" Language="cs">
<![CDATA[
Environment.SetEnvironmentVariable(Name, Value);
]]>
</Code>
</Task>
</UsingTask>
Then, inside the BeforeBuild target, use it to set the environment variables based on a condition that will only be true for local debug builds. Note that this task will only set the variable for the Target the task is called in, and the task will not work outside of a Target element :
<Target Name="BeforeBuild">
<!-- Set environment variables for debug build-->
<SetEnvironmentVariableTask Condition="'$(Configuration)'=='Debug'" Name="MyEnvironmentVariable" Value="Value_for_debug_installer" />
</Target>
Then, you can access it in your .wxs files somewhere and not get the pre-processor error:
<Property Id="PROP_MyProperty" Value="$(env.MyEnvironmentVariable)" />
Upvotes: 1