[wix-users] Make WiX Project work in Visual Studio & Build Machine

Edwin Castro egcastr at gmail.com
Tue Dec 31 09:45:39 PST 2019


> In my case, I am using the WiX binary / tool path and the WiX DLL
references in my Custom
> targets file. Hence I am forced to refer it as the first Import element
in wixproj file.

I only see you using WixToolPath in the HeatTarget target in your .targets
file. Specifically, I don't see you using WixBinPath, WixToolPath,
WixTargetsPath, nor WixTasksPath anywhere in the .targets file outside of
the HeatTarget target. If you were using those properties in PropertyGroups
or ItemGroups outside of Targets (effectively at "file-level") then you'd
need to have those properties defined prior to those uses. You can define
Targets before any properties the target uses as long as those properties
are defined prior to target use. For example, you could move the HeatTarget
as the first thing that appears in the .wixproj before anything else
happens and it would still work because WixToolPath will be defined by the
time the HeatTarget is called.

That might have been a little confusing. Let me try differently. Here is
the processing order of stuff in MSBuild:

All PropertyGroups and ItemGroups under the Project element are evaluated
first in order from top to bottom. Any properties that are defined later
overwrite previous definitions. Imports are evaluated at the point where
they appear as if the imported file existed at that precise spot. Targets
are defined where they exist but are not called yet. This means you can
overwrite a target that already exists by adding a different target
definition later on. Properties and Items used inside a target do not need
to be defined until use. This particularly powerful because it allows you
to define a target that defines items based on other data in one target and
then use those items in a later target. Those targets could be defined in
any order but are executed in the correct order by using the Depends
attribute.

> Also, do you mean I should use .props instead of .targets? Not sure what
is the difference
> between the two.

There is no functional difference between .props and .targets. In fact you
can use any extension you want and MSBuild will still work properly.
Convention dictates to name files that define properties only (and maybe
ItemGroups) in .props files and .targets files can have reusable bits like
common properties, items, and targets. You can call them whatever you want.

> Should the wix props file be deployed inside the WiX binaries directory?

My wix.props expects to exist one directory above the WiX bin directory
because it is defining the paths to the WiX bin and WiX sdk directories. If
you use wix.props directly in the bin directory then you'll need to modify
those paths a little. Note that MSBuildThisFileDirectory contains the path
to the directory in which the wix.props file exists. If you put wix.props
inside the WiX bin directory then MSBuildThisFileDirectory will be the WiX
bin directory.

> Can the props hold other targets like Exec command for Heat?

Sure. A .props file only has PropertyGroups (and maybe ItemGroups) by
convention only. You could put Targets in there too but I wouldn't worry
too much about what is inside your MSBuild files. I'd personally continue
using .targets for all your MSBuild files and not worry about it too much.

> My intent is to have all my custom properties, WiX Binary references,
paths and call to other targets inside a single .targets file and just add
the reference of this file in my wixproj file and nothing else.

Sure, makes sense. You should be able to do something like that with
careful planning. I would not get too hung up on a single .targets file
though. You may need to split stuff into multiple .targets files if you
need them to occur in different locations within your .wixproj. Easier to
just add multiple imports at different locations than trying to reorder
things established by Visual Studio, MSBuild, and/or WiX.

> Then from the Project's properties window in VS, I just want to pass the
values to the parameters and trigger the Build.

I'm not exactly sure what you mean by "Project's properties window in VS"
but I think that window only lets you modify stuff that Visual Studio knows
about. I don't think you'll be able to change anything custom.

I hope you're not triggering builds from within Visual Studio. I'd
personally learn how to trigger your builds from the command line using
MSBuild.exe directly. That is how your build machine is going to trigger
your build. You pass property overrides on the command line (which I think
are never overwritten but I could be remembering incorrectly so please test
this out first) rather than in any property window in Visual Studio.

--
Edwin G. Castro


On Tue, Dec 31, 2019 at 7:54 AM Ven H <venh.123 at gmail.com> wrote:

> Thanks a lot once Edwin. I have a couple of questions. In my case, I am
> using the WiX binary / tool path and the WiX DLL references in my Custom
> targets file. Hence I am forced to refer it as the first Import element in
> wixproj file.
>
> Also, do you mean I should use .props instead of .targets? Not sure what
> is the difference between the two. Should the wix props file be deployed
> inside the WiX binaries directory? Can the props hold other targets like
> Exec command for Heat?
>
> My intent is to have all my custom properties, WiX Binary references,
> paths and call to other targets inside a single .targets file and just add
> the reference of this file in my wixproj file and nothing else. Then from
> the Project's properties window in VS, I just want to pass the values to
> the parameters and trigger the Build.
>
> Please advise.
>
>
> On Tue, Dec 31, 2019 at 2:58 AM Edwin Castro <egcastr at gmail.com> wrote:
>
>> I have not yet reproduced the problem but I think I had a similar
>> sounding issue at work with Visual Studio 2015 a few months ago. Here is
>> what I ended up doing there.
>>
>> First, I kept the normal definition of WixTargetsPath in the first
>> PropertyGroup in the .wixproj. Immediately after this first PropertyGroup I
>> did my custom import. The end of the .wixproj has the normal Import of
>> $(WixTargetsPath).
>>
>> <?xml version="1.0" encoding="utf-8"?>
>> <Project ToolsVersion="" DefaultTargets="Build" xmlns="
>> http://schemas.microsoft.com/developer/msbuild/2003">
>>   <PropertyGroup>
>>     <Configuration Condition=" '$(Configuration)' == ''
>> ">Debug</Configuration>
>>     <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
>>     <ProductVersion>blahblah</ProductVersion>
>>     <ProjectGuid>blahblah</ProjectGuid>
>>     <SchemaVersion>blahblah</SchemaVersion>
>>     <OutputType>Package</OutputType>
>>     <WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND
>> '$(MSBuildExtensionsPath32)' != ''
>> ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
>>     <WixTargetsPath Condition=" '$(WixTargetsPath)' == ''
>> ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
>>   </PropertyGroup>
>>   <Import Project="path\to\custom\wix\wix.props" Condition="
>> '$(WixTargetsPath)' == '' AND Exists(' path\to\custom\wix.props ') "/>
>> ...
>>   <Import Project="$(WixTargetsPath)" />
>>   <!--
>>   To modify your build process, add your task inside one of the targets
>> below and uncomment it.
>>   Other similar extension points exist, see Wix.targets.
>>   <Target Name="BeforeBuild">
>>   </Target>
>>   <Target Name="AfterBuild">
>>   </Target>
>>   -->
>> </Project>
>>
>> In my custom wix.props I declared the properties below. I think I found
>> all of these properties needed to be defined so that Visual Studio will
>> properly load the .wixproj. I suspect the wix .targets can be updated to
>> handle this a little better so that a smaller number of properties need to
>> be customized as per the current documentation.
>>
>> <?xml version="1.0" encoding="utf-8"?>
>> <Project ToolsVersion="4.0" xmlns="
>> http://schemas.microsoft.com/developer/msbuild/2003">
>>     <PropertyGroup>
>>         <WixRootDirectory>$(MSBuildThisFileDirectory)</WixRootDirectory>
>>         <WixBinDirectory>$(WixRootDirectory)bin</WixBinDirectory>
>>
>> <WixExtensionsDirectory>$(WixBinDirectory)</WixExtensionsDirectory>
>>         <WixSdkDirectory>$(WixRootDirectory)sdk</WixSdkDirectory>
>>     </PropertyGroup>
>>     <PropertyGroup>
>>
>> <WixTargetsDirectory>$(WixExtensionsDirectory)</WixTargetsDirectory>
>>         <WixTasksDirectory>$(WixBinDirectory)</WixTasksDirectory>
>>
>> <LuxTargetsDirectory>$(WixExtensionsDirectory)</LuxTargetsDirectory>
>>         <LuxTasksDirectory>$(WixBinDirectory)</LuxTasksDirectory>
>>     </PropertyGroup>
>>     <PropertyGroup>
>>         <WixExtDir>$(WixBinDirectory)</WixExtDir>
>>         <WixInstallPath>$(WixBinDirectory)\</WixInstallPath>
>>         <WixToolPath>$(WixInstallPath)</WixToolPath>
>>     </PropertyGroup>
>>     <PropertyGroup>
>>
>> <WixTargetsPath>$(WixTargetsDirectory)\wix.targets</WixTargetsPath>
>>         <WixTasksPath>$(WixTasksDirectory)\WixTasks.dll</WixTasksPath>
>>
>> <LuxTargetsPath>$(LuxTargetsDirectory)\lux.targets</LuxTargetsPath>
>>         <LuxTasksPath>$(LuxTasksDirectory)\LuxTasks.dll</LuxTasksPath>
>>     </PropertyGroup>
>> </Project>
>>
>> The custom wix.props lives in a directory that includes the wix bin and
>> sdk directories:
>>
>> path\to\custom\wix\
>> +-- wix.props
>> +-- bin\
>> +-- sdk\
>>
>> I'd recommend you have a single wix.props file for overriding the wix
>> properties so that the import at the end of the .wixproj works properly and
>> import that .props file immediately after WixTargetsPath is defined if it
>> is still not defined as shown above. This way this single wix.props file
>> has a single responsibility.
>>
>> You could then use a second .props or .targets file to import other
>> customizations at whatever time that makes the most sense.
>>
>> Please let me know if this strategy works a little better for you. If it
>> doesn't then please let me know and I'll see about actually reproducing
>> your setup.
>>
>> --
>> Edwin G. Castro
>>
>>
>> On Mon, Dec 30, 2019 at 8:55 AM Edwin Castro <egcastr at gmail.com> wrote:
>>
>>> Hi Ven,
>>>
>>> I think this is not reproducing on Visual Studio 2012. I'll see about
>>> installing Visual Studio 2019 and try to reproduce your issue there.
>>>
>>> --
>>> Edwin G. Castro
>>>
>>>
>>> On Sat, Dec 28, 2019 at 8:31 AM Ven H <venh.123 at gmail.com> wrote:
>>>
>>>> Thanks a lot for your help, Edwin. Please find the .wixproj and
>>>> .targets below.
>>>>
>>>> *.wixproj*
>>>>
>>>> <?xml version="1.0" encoding="utf-8"?>
>>>> <Project ToolsVersion="4.0" DefaultTargets="Build"
>>>> InitialTargets="EnsureWixToolsetInstalled" xmlns="
>>>> http://schemas.microsoft.com/developer/msbuild/2003">
>>>>   <PropertyGroup>
>>>>     <Configuration Condition=" '$(Configuration)' == ''
>>>> ">Debug</Configuration>
>>>>     <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
>>>>     <ProductVersion>3.10</ProductVersion>
>>>>     <ProjectGuid>{9ecbe76b-ecc4-4a17-bc8b-f2224421f616}</ProjectGuid>
>>>>     <SchemaVersion>2.0</SchemaVersion>
>>>>     <OutputName>My.Custom.MSI</OutputName>
>>>>     <OutputType>Package</OutputType>
>>>>     <PublishDir>..\HeatFolder</PublishDir>
>>>>   </PropertyGroup>
>>>>   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' ==
>>>> 'Debug|x86' ">
>>>>     <OutputPath>bin\$(Configuration)\</OutputPath>
>>>>
>>>> <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
>>>>     <DefineConstants>Debug;HeatFldrPath=$(PublishDir)</DefineConstants>
>>>>   </PropertyGroup>
>>>>   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' ==
>>>> 'Release|x86' ">
>>>>     <OutputPath>bin\$(Configuration)\</OutputPath>
>>>>
>>>> <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
>>>>
>>>> <WixVariables>$(FilePath)=$(ProjectDir)HeatFolder;$(PVersion)="1.11.0.111"</WixVariables>
>>>>
>>>> <DefineConstants>HeatFldrPath=$(FilePath);ProductVersion=1.11.0.111;BuildNumber=$(BldNum)</DefineConstants>
>>>>   </PropertyGroup>
>>>>   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' ==
>>>> 'Full-Release|x86' ">
>>>>     <OutputPath>bin\$(Configuration)\</OutputPath>
>>>>
>>>> <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
>>>>
>>>> <DefineConstants>Release;HeatFldrPath=$(PublishDir)</DefineConstants>
>>>>   </PropertyGroup>
>>>>   <ItemGroup>
>>>>     <Compile Include="Content\GlobalCustomActions.wxs" />
>>>>     <Compile Include="Content\GlobalExitDlg.wxs" />
>>>>     <Compile Include="Content\GlobalFatalError.wxs" />
>>>>     <Compile Include="Content\GlobalInstallDlg.wxs" />
>>>>     <Compile Include="Content\GlobalLicenseAgreementDlg.wxs" />
>>>>     <Compile Include="Content\GlobalSetupFolderDlg.wxs" />
>>>>     <Compile Include="Content\GlobalWelcomeDlg.wxs" />
>>>>     <Compile Include="Content\GlobalWixUI.wxs" />
>>>>     <Compile Include="Content\Product.wxs" />
>>>>     <Compile Include="Content\UserFiles.wxs" />
>>>>     <Compile Include="Content\UserIIS.wxs" />
>>>>     <Compile Include="Content\UserRegistry.wxs" />
>>>>   </ItemGroup>
>>>>   <ItemGroup>
>>>>     <Folder Include="conf\" />
>>>>     <Folder Include="Content\" />
>>>>     <Folder Include="Images\" />
>>>>     <Folder Include="lib\" />
>>>>   </ItemGroup>
>>>>   <ItemGroup>
>>>>     <Content Include="AppPoolAttrs.xml" />
>>>>     <Content Include="AppPoolUpgradeChanges.xml" />
>>>>     <Content Include="conf\default.yml" />
>>>>     <Content Include="Content\CustomActions.CA.dll" />
>>>>     <Content Include="Content\GlobalProperties.wxi" />
>>>>     <Content Include="Content\License.en-us.rtf" />
>>>>     <Content Include="CustomWix.targets" />
>>>>     <Content Include="Images\Banner.bmp" />
>>>>     <Content Include="Images\DEST.ICO" />
>>>>     <Content Include="Images\dialog.bmp" />
>>>>     <Content Include="Images\dialog_cust.bmp" />
>>>>     <Content Include="Images\dialog_template.bmp" />
>>>>     <Content Include="Images\Exclam.ico" />
>>>>     <Content Include="Images\folder.ico" />
>>>>     <Content Include="Images\folderNew.ico" />
>>>>     <Content Include="Images\New.ico" />
>>>>     <Content Include="Images\warn.ico" />
>>>>     <Content Include="lib\WixIIsExtension.dll" />
>>>>     <Content Include="lib\WixMsmqExtension.dll" />
>>>>     <Content Include="lib\WixUIExtension.dll" />
>>>>     <Content Include="lib\WixUtilExtension.dll" />
>>>>     <Content Include="packages.config" />
>>>>   </ItemGroup>
>>>>   <ItemGroup>
>>>>     <EmbeddedResource Include="Content\en-us.wxl" />
>>>>   </ItemGroup>
>>>>   <Import Project="CustomWiX.Targets"
>>>> Condition="Exists('CustomWiX.targets')" />
>>>>   <Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)'
>>>> != '' " />
>>>>   <Import
>>>> Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets"
>>>> Condition=" '$(WixTargetsPath)' == '' AND
>>>> Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
>>>>   <Target Name="EnsureWixToolsetInstalled" Condition="
>>>> '$(WixTargetsImported)' != 'true' ">
>>>>     <Error Text="The WiX Toolset v3.11 (or newer) build tools must be
>>>> installed to build this project. To download the WiX Toolset, see
>>>> http://wixtoolset.org/releases/" />
>>>>   </Target>
>>>> </Project>
>>>>
>>>> *.targets*
>>>>
>>>> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
>>>>   <PropertyGroup>
>>>>
>>>> <DefineConstants>HeatFldrPath=F;ProductVersion=1.11.0.345;BuildNumber=345</DefineConstants>
>>>>
>>>> <OutputName>$(MSIName)</OutputName>
>>>> <OutputPath>$(MSIPath)</OutputPath>
>>>> <SuppressPdbOutput>True</SuppressPdbOutput>
>>>>   </PropertyGroup>
>>>>   <PropertyGroup>
>>>> <WixBinPath>$(SolutionDir)\Build\wix\</WixBinPath>
>>>>     <WixToolPath>$(WixBinPath)\</WixToolPath>
>>>>     <WixTargetsPath>$(WixToolPath)Wix.targets</WixTargetsPath>
>>>>     <WixTasksPath>$(WixToolPath)wixtasks.dll</WixTasksPath>
>>>>   </PropertyGroup>
>>>>   <ItemGroup>
>>>>     <WixExtension Include="WixUtilExtension">
>>>>       <HintPath>lib\WixUtilExtension.dll</HintPath>
>>>>       <Name>WixUtilExtension</Name>
>>>>     </WixExtension>
>>>>     <WixExtension Include="WixUIExtension">
>>>>       <HintPath>lib\WixUIExtension.dll</HintPath>
>>>>       <Name>WixUIExtension</Name>
>>>>     </WixExtension>
>>>>     <WixExtension Include="WixMsmqExtension">
>>>>       <HintPath>lib\WixMsmqExtension.dll</HintPath>
>>>>       <Name>WixMsmqExtension</Name>
>>>>     </WixExtension>
>>>>     <WixExtension Include="WixIIsExtension">
>>>>       <HintPath>lib\WixIIsExtension.dll</HintPath>
>>>>       <Name>WixIIsExtension</Name>
>>>>     </WixExtension>
>>>>   </ItemGroup>
>>>>   <Target Name="HeatTarget" BeforeTargets="Build">
>>>> <Exec  Command='"$(WixToolPath)\heat.exe" dir $(HeatFldrPath) -cg
>>>> UserFeatureFiles -dr APP_DIR -gg -g1 -sfrag -sw -svb6 -srd -sreg -ke -var
>>>> var.HeatFldrPath -out "Content\UserFiles.wxs"' />
>>>>   </Target>
>>>>
>>>> </Project>
>>>>
>>>> On Fri, Dec 27, 2019 at 11:42 PM Edwin Castro <egcastr at gmail.com>
>>>> wrote:
>>>>
>>>>> There is a good chance that using a Condition attribute in one or more
>>>>> places will likely help. It will likely need to look "normal" to Visual
>>>>> Studio while still have the ability to overwrite that default when running
>>>>> from command line without Visual Studio installed.
>>>>>
>>>>> Can you share your .wixproj and your .targets?
>>>>>
>>>>> --
>>>>> Edwin G. Castro
>>>>>
>>>>>
>>>>> On Fri, Dec 27, 2019, 07:36 Ven H via wix-users <
>>>>> wix-users at lists.wixtoolset.org> wrote:
>>>>>
>>>>>> Let me give some more detail. In my WiX project, I need to run Heat
>>>>>> command
>>>>>> on a folder (not included in the project) and include the wxs content
>>>>>> into
>>>>>> an empty file I have. Then I need to pass the name of the MSI (since
>>>>>> it
>>>>>> should be configurable), the path of the MSI (since this also needs
>>>>>> to be
>>>>>> configurable) and the Build Number (since this will be part of the MSI
>>>>>> name). I also need to pass the Product Version, since this will also
>>>>>> have
>>>>>> Build number in it. Apart from this, I also need to pass the path of
>>>>>> the
>>>>>> WiX binaries (downloaded). Even though, my machine has WiXToolSet
>>>>>> installed
>>>>>> and Votive is also installed, I need to be able to build this project
>>>>>> using
>>>>>> msbuild command. So, I have included all the above mentioned
>>>>>> parameters as
>>>>>> properties (some as DefineConstants) in a separate targets file and
>>>>>> have
>>>>>> imported this targets file into the wixproj file.
>>>>>>
>>>>>> I want to be able to build the MSI both from Visual Studio and also
>>>>>> from
>>>>>> command line using MSBuild. But I am having a hard time getting both
>>>>>> working at the same time. Any help would be appreciated.
>>>>>>
>>>>>> On Fri, Dec 27, 2019 at 12:43 PM Ven H <venh.123 at gmail.com> wrote:
>>>>>>
>>>>>> > I have a setup project in Visual Studio 2019. I use Heat command in
>>>>>> that
>>>>>> > project. I followed the below link to make it working in build
>>>>>> machine,
>>>>>> > which won't have VS or WiXToolSet installed.
>>>>>> >
>>>>>> >
>>>>>> https://wixtoolset.org/documentation/manual/v3/msbuild/daily_builds.html
>>>>>> >
>>>>>> > For this, I modified the .wixproj as per the link above. But now,
>>>>>> it's no
>>>>>> > longer working in Visual Studio. Has anyone faced this issue? Has
>>>>>> anyone
>>>>>> > had success in making a WiX project build successfully in  Visual
>>>>>> Studio as
>>>>>> > well as build machine? If so, please help.
>>>>>> >
>>>>>>
>>>>>> ____________________________________________________________________
>>>>>> WiX Toolset Users Mailing List provided by FireGiant
>>>>>> http://www.firegiant.com/
>>>>>>
>>>>>



More information about the wix-users mailing list