I'm working on a WIX 3.6 Installer for a web service. But I've run into an issue when attempting to use a HeatDirectory to harvest all of the necessary output and no matter what I try I get the following error for every harvested file:
The system cannot find the file 'SourceDir\Some.dll...'
The errors occur in WcfService.wxs; the weird part is that WcfService.wxs is automatically created by the heatdirectory section in my project file (below). How can it be blowing up saying it can't find these .dll's if it has to know where they are to create WcfService.wxs in the first place? These errors even occur when I download and build a WIX Example project (as-is) from any one of the tutorials I've read.
The goal: To automate as much of the .dll inclusion as possible (i.e. utilize harvesting to handle dependency projects, etc.)
I'm running Win 7 64bit and the project is .NET 4.
Product.wxs:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="CompleteInstall" Language="1033" Version="1.0.0.0" Manufacturer="Technologies" UpgradeCode="b2ae6aa5-263f-4f9a-a250-8599a7f2cb03">
<Package InstallerVersion="200" Compressed="yes" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Directory Id="CommonDir1" Name="Common Directory 1">
<Directory Id="CommonDir2" Name="Common Directory 2">
<Directory Id="INSTALLFOLDER" Name="Install Directory"/>
</Directory>
</Directory>
</Directory>
</Directory>
<Feature Id="ProductFeature" Title="CompleteInstall" Level="1">
<ComponentGroupRef Id="WcfService_Project" />
</Feature>
<Property Id="WIXUI_INSTALLDIR">INSTALLFOLDER</Property>
<UIRef Id="WixUI_InstallDir" />
</Product>
</Wix>
Project file:
<Target Name="BeforeBuild">
<MSBuild Projects="%(ProjectReference.FullPath)" Targets="Build" Properties="Configuration=$(Configuration);Platform=x86" Condition="'%(ProjectReference.ContentProject)'=='True'" />
<PropertyGroup>
<LinkerBaseInputPaths>%(ProjectReference.RootDir)%(ProjectReference.Directory)bin\$(Platform)\$(Configuration)\</LinkerBaseInputPaths>
</PropertyGroup>
<HeatDirectory OutputFile="%(ProjectReference.Filename)-temp.xml"
Directory="%(ProjectReference.RootDir)%(ProjectReference.Directory)bin\$(Platform)\$(Configuration)\"
DirectoryRefId="INSTALLFOLDER"
ComponentGroupName="%(ProjectReference.Filename)_Project"
SuppressCom="true"
SuppressFragments="true"
SuppressRegistry="true"
SuppressRootDirectory="true"
AutoGenerateGuids="false"
GenerateGuidsNow="true"
ToolPath="$(WixToolPath)"
Condition="'%(ProjectReference.ContentProject)'=='True'" />
<XslTransformation XmlInputPaths="%(ProjectReference.Filename)-temp.xml"
XslInputPath="XslTransform.xslt"
OutputPaths="%(ProjectReference.Filename).wxs"
Condition="'%(ProjectReference.ContentProject)'=='True'" />
</Target>
WcfService.wxs:
<?xml version="1.0" encoding="utf-8"?><Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="INSTALLFOLDER">
<Component Id="cmpE6EBA3D8D6D4DB0C93E73200C78DCC51" Guid="{C88B5CF9-8807-45DF-AA6F-732437B74BB6}">
<File Id="fil0118BBA61671E80581CA9C9AA6DD3E8D" KeyPath="yes" Source="SourceDir\Some.dll" />
</Component>
</DirectoryRef>
</Fragment>
<Fragment>
<ComponentGroup Id="WcfService_Project">
<ComponentRef Id="cmpE6EBA3D8D6D4DB0C93E73200C78DCC51" />
</ComponentGroup>
</Fragment>
</Wix>
The problem was the absence of the HeatDirectory PreprocessorVariable property. I fixed the issue with the following additions to my wixproj file:
<PropertyGroup>
<DefineConstants>BasePath=%(ProjectReference.RootDir)%(ProjectReference.Directory);</DefineConstants>
</PropertyGroup>
<HeatDirectory OutputFile="%(ProjectReference.Filename).wxs"
DirectoryRefId="INSTALLFOLDER"
Directory="%(ProjectReference.RootDir)%(ProjectReference.Directory)"
ComponentGroupName="%(ProjectReference.Filename)_Project"
SuppressCom="true"
SuppressFragments="true"
SuppressRegistry="true"
SuppressRootDirectory="true"
AutoGenerateGuids="false"
GenerateGuidsNow="true"
ToolPath="$(WixToolPath)"
Condition="'%(ProjectReference.ContentProject)'=='True'"
PreprocessorVariable="var.BasePath"/>
As you can see, I needed to first define a constant variable for local use. I set the variable equal to the root path of my WCF project. Secondly I used that variable as my PreprocessorVariable. Finally I'm able to dynamically/recursively harvest the files generated from MsBuild. Next step: exclude the unnecessary files. I will refer to this link.
See below my complete wixproj:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>3.5</ProductVersion>
<ProjectGuid>{4005592f-cc0e-41a3-8e64-33b2824e7fd9}</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>MyWCF.WCF.Webservice</OutputName>
<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>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="MyWCF.WcfService.wxs" />
<Compile Include="IISConfig.wxs" />
<Compile Include="InstallUi.wxs" />
<Compile Include="Product.wxs" />
<Compile Include="UIDialogs.wxs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MyWCF.WcfService\MyWCF.WcfService.csproj">
<Name>MyWCF.WcfService</Name>
<Project>{8e528b38-2826-4793-a66d-f6ff181e1139}</Project>
<Private>True</Private>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
<ContentProject>True</ContentProject>
<DoNotHarvest>True</DoNotHarvest>
<PackageThisProject>True</PackageThisProject>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<WixExtension Include="WixIIsExtension">
<HintPath>$(WixExtDir)\WixIIsExtension.dll</HintPath>
<Name>WixIIsExtension</Name>
</WixExtension>
<WixExtension Include="WixUtilExtension">
<HintPath>$(WixExtDir)\WixUtilExtension.dll</HintPath>
<Name>WixUtilExtension</Name>
</WixExtension>
<WixExtension Include="WixUIExtension">
<HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
<Name>WixUIExtension</Name>
</WixExtension>
<WixExtension Include="WixNetFxExtension">
<HintPath>$(WixExtDir)\WixNetFxExtension.dll</HintPath>
<Name>WixNetFxExtension</Name>
</WixExtension>
</ItemGroup>
<ItemGroup>
<Content Include="ConfigurationInitialize.wxi" />
</ItemGroup>
<Import Project="$(WixTargetsPath)" />
<PropertyGroup>
<PreBuildEvent />
</PropertyGroup>
<Target Name="BeforeBuild">
<MSBuild Projects="%(ProjectReference.FullPath)" Targets="Package" Properties="Configuration=$(Configuration);Platform=$(Platform)" Condition="'%(ProjectReference.PackageThisProject)'=='True'" />
<PropertyGroup>
<DefineConstants>BasePath=%(ProjectReference.RootDir)%(ProjectReference.Directory)obj\$(Platform)\$(Configuration)\Package\PackageTmp\</DefineConstants>
</PropertyGroup>
<HeatDirectory OutputFile="%(ProjectReference.Filename).wxs"
Directory="%(ProjectReference.RootDir)%(ProjectReference.Directory)obj\$(Platform)\$(Configuration)\Package\PackageTmp"
DirectoryRefId="INSTALLFOLDER"
ComponentGroupName="%(ProjectReference.Filename)_Project"
SuppressCom="true"
SuppressFragments="true"
SuppressRegistry="true"
SuppressRootDirectory="true"
AutoGenerateGuids="false"
GenerateGuidsNow="true"
ToolPath="$(WixToolPath)" Condition="'%(ProjectReference.PackageThisProject)'=='True'"
PreprocessorVariable="var.BasePath" />
</Target>
</Project>
I was getting similar issue to yours when I moved from setting up a basic website with Wix to one of our production ones.
Assuming you were following example Paul Reynolds' example and this one Paraesthesia's example
If you look in the comments of the following page - http://blogs.planetsoftware.com.au/paul/archive/2011/02/20/creating-a-web-application-installer-with-wix-3.5-and-visual.aspx
The first comment mentions changing the beforebuild methods found in Paraesthesia's example.
<Target Name="BeforeBuild">
<MSBuild Projects="%(ProjectReference.FullPath)" Targets="Package" Properties="Configuration=$(Configuration);Platform=AnyCPU" Condition="'%(ProjectReference.WebProject)'=='True'" />
<PropertyGroup> <DefineConstants Condition="'%(ProjectReference.WebProject)'=='True'"> %(ProjectReference.Name).PackageDir=%(ProjectReference.RootDir)%(ProjectReference.Directory)obj\$(Configuration)\Package\PackageTmp\ </DefineConstants> </PropertyGroup> <HeatDirectory OutputFile="%(ProjectReference.Filename).wxs" Directory="%(ProjectReference.RootDir)%(ProjectReference.Directory)obj\$(Configuration)\Package\PackageTmp\" DirectoryRefId="INSTALLDIR" ComponentGroupName="%(ProjectReference.Filename)_Project" AutogenerateGuids="true" SuppressCom="true" SuppressFragments="true" SuppressRegistry="true" SuppressRootDirectory="true" ToolPath="$(WixToolPath)" Condition="'%(ProjectReference.WebProject)'=='True'" Transforms="%(ProjectReference.Filename).xsl" PreprocessorVariable="var.%(ProjectReference.Name).PackageDir" />
</Target>
I had to remove the transform property and change the DirectoryRefId but so far so good.
Hope that helps point you in the right direction.
Update: If you put
<PropertyGroup>
<DefineConstants Condition="'%(ProjectReference.WebProject)'=='True'">
%(ProjectReference.Name).PackageDir=%(ProjectReference.RootDir)
%(ProjectReference.Directory)obj\$(Configuration)\Package\PackageTmp\
</DefineConstants>
and add:
PreprocessorVariable="var.%(ProjectReference.Name).PackageDir"
See the comment towards the bottom. I don't do a transform, so I left that out.
to the HeatDirectory it should work with out having to have the proj file at the bottom.
This is probably going to lower my reputation, but what I find interesting is http://www.paraesthesia.com site, is I had working for one project, but when trying another it wasn't working.
After looking at the output it seemed to take the proper project for Heat and Candle, but the Light seemed to take one at random. After comparing the two projects, I noticed the working project had the project to harvest as the last project listed. When I moved the project in the .wixproj file to the last reference, it worked.
I'm using 3.5.2519 at this time. I know it is an old one but we have projects that require the Harvest to True and actually Harvest in Visual Studio.
So your WcfService.wxs includes:
<File Id="fil0118BBA61671E80581CA9C9AA6DD3E8D" KeyPath="yes" Source="SourceDir\Some.dll" />
This refers to SourceDir\Some.dll. This file must exist at the pc where you compile your project. You probably need to change the path.
Related
I am working on WiX Setup V3 project in Visual Studio 2019. I have to make this working in Visual Studio as well as from MSBuild (in Jenkins). I have authored custom target file which will be included in this project. Following is the markup of the custom target file. I cannot use the HeatDirectory task, since it lacks some flags like svb6. Hence I am using Exec command for Heat execution.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<DefineConstants>HeatFldrPath=$(FilePath);ProductVersion=$(PVersion);BuildNumber=$(BldNum)</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>
I need to make this configurable for the following parameters:
Product Version (for use in Candle command)
Build Number (This will be added to the Product Version)
Heat Directory Path
MSI Name (This will have Version along with Build Number concatenated
to it)
MSI Path (I don't want this to be bin\$(Configuration)\en-us, rather
a custom directory I specify)
My custom targets file will be imported to the .wixproj file and nothing else will be changed in the .wixproj file.
If I use DefineConstants in my custom targets file, it works with MSBuild, but not with Visual Studio. I am having a hard time passing these as parameters and getting my MSI to build from both Visual Studio and MSBuild. I tried passing $(FilePath), $(PVersion) and $(BldNum) from project properties, but no luck. I cannot hard code these values in .targets or .wixproj file, since they have to be run from both Visual Studio and MSBuild. Also, I am not able to pass OutputName and OutputPath from Visual Studio. Can anyone please help me?
PFB the wixproj file.
<?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.1.0.1"
</WixVariables>
<DefineConstants>HeatFldrPath=$(FilePath);ProductVersion=1.1.0.1;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>
I tried passing $(FilePath), $(PVersion) and $(BldNum) from project
properties, but no luck. I cannot hard code these values in .targets
or .wixproj file, since they have to be run from both Visual Studio
and MSBuild. Also, I am not able to pass OutputName and OutputPath
from Visual Studio.
The main issue is that when you set the variables in Project Properties UI, the values can only pass to the variables in the xxx.wixproj rather than CustomWiX.Targets file.
And this approach is local (modify only the properties of the xxx.wixproj file, which still be overridden by the custom target values).
In more detail, when it reloads the xxxx.wixproj which contains the custom target file, MSBuild will load the xml nodes line by line, since MSBuild properties support forward override values. Simply said, if the same value is defined later, the previous value is overwritten. And the same properties are defined in the custom target file which is imported under the those properties, so the properties in the custom targets file will always override the properties.
Besides, when you pass some variables in the project Properties UI, the values will overwrite the values in the xxx.wixprojrather than custom targets file. And then when you build again, the values in custom targets will still override the values you modified in project properties, so it won't work.
Differ from VS IDE, the msbuild command line can override the value with -p: XXX (property name)= XXXXXX, which is global, so this problem does not occur.
Suggestion
1) If you still want to modify those properties by overriding the value of the project properties, remove the same properties from the custom targets file and move them to wixproj so that they can be used directly.
2) Since the custom target file always overwrites the same properties, you can modify the specific properties directly in the custom target file without having to modify the wixproj file directly.
Update1
The wixvariables(Properties-->Build-->Define Variables) does not work in the xxxx.wixproj file but only for wix file like Product.wxsfile. If you define the property $(Filepath) in the Define Variables, it will never be used for MSBuild. So there is no way to set the properties in Property UI for msbuild Properties.
Besides, $ is used to call a property of MSBuild and MSBuild define a property only under PropertyGroup of xxx.xxxproj like <PropertyGroup><FilePath> xxx</FilePath><\PropertyGroup>.
Solution
You can customize your build by using Directory.Build.targets and remember keeping the name as the document said which is designed by that with the effect. Then you should put this file under the solution folder so that it can work for all the projects.xxx.props file will import on the top of the xxxx.xxproj, so it can not override the values and only the Directory.Build.targets which is imported at the bottom of the xx.xxproj file does.
Then you can define the variables in the file like:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<FilePath>xxxxx</FilePath>
</ProperGroup>
.........
</Project>
Hope it could help you.
I am trying to build my first uwp application. I am new to c# as well. I am using visual studio build tools 2019. I think I have done everything right but when I run msbuild, I get the following error:
"C:\Projects\C\UapHello\uaphello.csproj" (default target) (1) ->
(_ValidateAppxPackage target) ->
Package.appxmanifest(41,9): error APPX0703: Manifest references file 'Assets\Square150x150Logo.png' which is not part
of the payload. [C:\Projects\C\UapHello\uaphello.csproj]
Package.appxmanifest(42,9): error APPX0703: Manifest references file 'Assets\Square44x44Logo.png' which is not part o
f the payload. [C:\Projects\C\UapHello\uaphello.csproj]
Package.appxmanifest(27,6): error APPX0703: Manifest references file 'StoreLogo.png' which is not part of the payload
. [C:\Projects\C\UapHello\uaphello.csproj]
Package.appxmanifest(45,27): error APPX0703: Manifest references file 'Assets\SplashScreen.png' which is not part of
the payload. [C:\Projects\C\UapHello\uaphello.csproj]
I am pretty sure these files exist in said folder.
I am including my csproj and appmanifest:
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
xmlns:iot2="http://schemas.microsoft.com/appx/manifest/iot/windows10/2"
IgnorableNamespaces="uap mp uap5 iot2 desktop4">
<Identity
Name="IggyMakesThings"
Publisher="CN=IggyMakesThings, O=IggyMakesThings, L=Redmond, S=Washington, C=US"
Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="11a54d62-0d60-4e17-820d-1fa537715b3a" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.17763.0" />
</Dependencies>
<Properties>
<DisplayName>uaphello</DisplayName>
<PublisherDisplayName>IggyMakesThings</PublisherDisplayName>
<Logo>StoreLogo.png</Logo>
</Properties>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="uaphello.exe"
EntryPoint="UAPHello.App">
<uap:VisualElements
DisplayName="UAPSample"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png"
Description="UAP C# Sample"
BackgroundColor="#000000">
<uap:SplashScreen Image="Assets\SplashScreen.png" />
<uap:DefaultTile>
<uap:ShowNameOnTiles>
<uap:ShowOn Tile="square150x150Logo" />
</uap:ShowNameOnTiles>
</uap:DefaultTile>
</uap:VisualElements>
</Application>
</Applications>
</Package>
And csproj:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">Win32</Platform>
<ProjectGuid>{$guid1$}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<RootNamespace>uaphello</RootNamespace>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.17763.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<EnableDotNetNativeCompatibleProfile>true</EnableDotNetNativeCompatibleProfile>
</PropertyGroup>
<PropertyGroup>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|Win32'">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|Win32'">
<PlatformTarget>x86</PlatformTarget>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform" Version="6.2.8" />
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
</Project>
Please help
I think something missing in your .csproj file caused this issue.
Steps to reproduce same issue:
1.Create a new Blank App(Universal Windows)
2.In VS, for those .png resources:Exclude from the project
3.Copy the solution to build server where only has build tools
4.Restore the nuget packages and build the project with command like:
msbuild path/xxx.csproj(or xxx.sln) /p:Platform=X64 /p:AppxBundle=Always
5.Get the error below:
You can follow my simple steps to locate the cause of the issue.
In my opinion:
You might do some similar operation like mine. Maybe Exclude from Project, maybe delete the ItemGroup content in xx.csproj file, or what.
The result is deleting the ItemGroup for those .png files in xx.csproj. If you create a new Blank App(UWP), and check its content of .csproj file you would see:
<ItemGroup>
<Content Include="Properties\Default.rd.xml" />
<Content Include="Assets\LockScreenLogo.scale-200.png" />
<Content Include="Assets\SplashScreen.scale-200.png" />
<Content Include="Assets\Square150x150Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
</ItemGroup>
But these content is missing in your .csproj file.
These four files which are used in your appmanifest are indeed in your asserts folder.
But without the content ref in .csproj file, the build process can't find them properly.Square150x150Logo.png,Square44x44Logo.png,StoreLogo.png,SplashScreen.png
As a workaround:
So you can edit your xx.csproj file, and add the ItemGroup into it.
But I'm not certainly sure it will work. Since after my checking your .csproj file. Maybe the .png files are not the only things you excluded or removed!!
I'm not sure how many changes you've made to the project, so if above not helps, just create a new project and copy your core code into the new project.
Using Visual Studio and MSBuild I would like to be able to exclude all .js files and include all .min.js files in my deployments.
I know this can be achieved using the file properties in visual studio, but this is not an option as there are far too many files.
I have the following PublishProfile in my Visual Studio project. Everything works just fine apart from the <ItemGroup>
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit http://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<LastUsedBuildConfiguration>Delpoy-Static</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<ExcludeApp_Data>True</ExcludeApp_Data>
<publishUrl>\\***\wwwroot\***.com\static</publishUrl>
<DeleteExistingFiles>False</DeleteExistingFiles>
</PropertyGroup>
<!--This does not work, but gives the idea of what I want to achieve-->
<ItemGroup>
<Deploy Exclude="**\*.js" Include="**\*.min.js" />
</ItemGroup>
</Project>
Can this be achieved using the PublishProfile? If so, how?
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<!-- ... -->
</PropertyGroup>
<Target Name="BeforeBuild">
<ItemGroup>
<Minified Include="**\*.min.js" />
<Maxified Include="**\*.js" Exclude="#(Minified)" />
<Content Remove="#(Maxified)" />
</ItemGroup>
</Target>
</Project>
Edit:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<!-- ... -->
</PropertyGroup>
<ItemGroup>
<Minified Include="**\*.min.js" />
<Maxified Include="**\*.js" Exclude="#(Minified)" />
</ItemGroup>
<PropertyGroup>
<ExcludeFoldersFromDeployment>bin</ExcludeFoldersFromDeployment>
<ExcludeFilesFromDeployment>#(Maxified);Web.config</ExcludeFilesFromDeployment>
</PropertyGroup>
</Project>
If you want to exclude files you can place the files to be excluded in the the ExcludeFromPackageFiles item group. In your case you want to take all .js files and exclude all but those that are *.min.js. To do that in your .pubxml file add the following in your .pubxml file .
<ItemGroup>
<ExcludeFromPackageFiles Include="js\**\*.js" Exclude="js\**\*min*.js">
<FromTarget>Project</FromTarget>
</ExcludeFromPackageFiles>
</ItemGroup>
Note: this snippet assumes that your .js files are in a folder named js.
work to me:
Edit .csproj file
Find section MinifyJavaScriptAndCSS
Edit property Exclude in JS tag
Add directory or files to ignore during publish
<Target Name="MinifyJavaScriptAndCSS" AfterTargets="CopyAllFilesToSingleFolderForPackage" Condition="'$(Configuration)'=='Release'">
<ItemGroup>
<!-- Every .js file (exclude *.min.js and *.vsdoc.js files) -->
<JS Include="$(_PackageTempDir)\**\*.js" Exclude="$(_PackageTempDir)\**\*.min.js;$(_PackageTempDir)\**\*vsdoc.js;" />
<CSS Include="$(_PackageTempDir)\**\*.css" Exclude="$(_PackageTempDir)\**\*.min.css" />
</ItemGroup>
<AjaxMin JsKnownGlobalNames="jQuery,$" JsSourceFiles="#(JS)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".js" CssSourceFiles="#(CSS)" CssSourceExtensionPattern="\.css$" CssTargetExtension=".css" />
<Message Text="[pcv] $(MSBuildProjectName) -> Minified: #(JS)" Importance="high" />
<Message Text="[pcv] $(MSBuildProjectName) -> Minified: #(CSS)" Importance="high" />
I'm trying to apply a manifest to a WiX generated msi to create an exe that will immediately display a UAC prompt upon running the installer. Unfortunately I'm getting the following error upon building my installer project:
Values of attribute "level" not equal in different manifest snippets. mt.exe
I need to elevate the execution to allow custom actions that run during InstallUISequence to have admin privileges (to look up IIS app pools and web apps). I'm using Visual Studio 2012 on Windows 8.
Below is my wixproj file which shows my bootstrapper setup:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>3.5</ProductVersion>
<ProjectGuid>{d51029e8-4a79-4812-96e1-bf6b600d5d34}</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>WixInstallerExampleWebInstaller</OutputName>
<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>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>Debug</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="IisSettingsDlg.wxs" />
<Compile Include="Product.wxs" />
<Compile Include="UserInterface.wxs" />
<Compile Include="WixInstallerExampleWeb.wxs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WixInstallerExampleWeb\WixInstallerExampleWeb.csproj">
<Name>WixInstallerExampleWeb</Name>
<Project>{d23a374d-764c-40ba-b566-4d7c55319236}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLLOCATION</RefTargetDir>
<PackageThisProject>True</PackageThisProject>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<WixExtension Include="WixUtilExtension">
<HintPath>$(WixExtDir)\WixUtilExtension.dll</HintPath>
<Name>WixUtilExtension</Name>
</WixExtension>
<WixExtension Include="WixNetFxExtension">
<HintPath>$(WixExtDir)\WixNetFxExtension.dll</HintPath>
<Name>WixNetFxExtension</Name>
</WixExtension>
<WixExtension Include="WixIIsExtension">
<HintPath>$(WixExtDir)\WixIIsExtension.dll</HintPath>
<Name>WixIIsExtension</Name>
</WixExtension>
<WixExtension Include="WixUIExtension">
<HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
<Name>WixUIExtension</Name>
</WixExtension>
</ItemGroup>
<ItemGroup>
<Content Include="EULA.rtf" />
<Content Include="IisManager.CA.dll" />
<Content Include="uac.manifest" />
</ItemGroup>
<ItemGroup>
<BootstrapperFile Include="Microsoft.Windows.Installer.3.1" >
<ProductName>Windows Installer 3.1</ProductName>
</BootstrapperFile>
</ItemGroup>
<Import Project="$(WixTargetsPath)" />
<Target Name="Bootstrapper"
Inputs="$(OutDir)$(TargetFileName)"
Outputs="$(OutDir)\Setup.exe"
Condition=" '$(OutputType)'=='package' " >
<GenerateBootstrapper ApplicationName="application name"
ApplicationFile="$(TargetFileName)"
BootstrapperItems="#(BootstrapperFile)"
ComponentsLocation="Relative"
OutputPath="$(OutputPath)"
Culture="en-US"
Path="C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\Bootstrapper" />
</Target>
<Target Name="PatchSetupExe" DependsOnTargets="Bootstrapper">
<Exec Command='"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\bin\mt.exe" -manifest "$(ProjectDir)uac.manifest" -updateresource:"$(ProjectDir)$(OutputPath)Setup.exe;#1"' IgnoreExitCode='false' />
</Target>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets" />
<PropertyGroup>
<BuildDependsOn>$(BuildDependsOn);Bootstrapper;PatchSetupExe</BuildDependsOn>
</PropertyGroup>
<Target Name="BeforeBuild">
<MSBuild Projects="%(ProjectReference.FullPath)" Targets="Package" Properties="Configuration=$(Configuration);Platform=AnyCPU" Condition="'%(ProjectReference.PackageThisProject)'=='True'" />
<Copy SourceFiles="%(ProjectReference.RootDir)%(ProjectReference.Directory)obj\$(Configuration)\TransformWebConfig\transformed\web.config" OverwriteReadOnlyFiles="true" DestinationFolder="%(ProjectReference.RootDir)%(ProjectReference.Directory)obj\$(Configuration)\Package\PackageTmp\" Condition="'%(ProjectReference.PackageThisProject)'=='True'" />
<PropertyGroup>
<LinkerBaseInputPaths>%(ProjectReference.RootDir)%(ProjectReference.Directory)obj\$(Configuration)\Package\PackageTmp\</LinkerBaseInputPaths>
<DefineConstants>BasePath=%(ProjectReference.RootDir)%(ProjectReference.Directory);</DefineConstants>
</PropertyGroup>
<HeatDirectory OutputFile="%(ProjectReference.Filename).wxs" Directory="%(ProjectReference.RootDir)%(ProjectReference.Directory)obj\$(Configuration)\Package\PackageTmp\" DirectoryRefId="INSTALLLOCATION" ComponentGroupName="%(ProjectReference.Filename)_Project" SuppressCom="true" SuppressFragments="true" SuppressRegistry="true" SuppressRootDirectory="true" AutoGenerateGuids="false" GenerateGuidsNow="true" ToolPath="$(WixToolPath)" Condition="'%(ProjectReference.PackageThisProject)'=='True'" PreprocessorVariable="var.BasePath" />
</Target>
<PropertyGroup>
<PreBuildEvent />
</PropertyGroup>
<PropertyGroup>
<PostBuildEvent />
</PropertyGroup>
<!--
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="AfterBuild">
</Target>
-->
</Project>
And here is my manifest file I'm trying to apply:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="Setup" type="win32" />
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
I found one solution. Download Resource Hacker. Open your resulting executable file and browse it until you find your manifest file. You can edit it diretly in UI or you can script it in command line:
ResHacker.exe -modify old.exe,new.exe,manifestToUse.manifest,ROOTNODE,SUBNODE*
*Those NODEs are the path corresponding with resource (manifest) you are trying to update - it is the path in tree in Resource Hacker UI.
Another Hack is to modify the manifest information of the burn.exe of WiX. But this seems to be a very bad solution and I am not sure if there are any side effects. But in my case I could solve it that way because in my build process I use the WiX binaries (not the WiX setup) within my source control version system which then will not affect any other WiX projects on my machine.
I used Visual Studio´s Resource Editor to edit the manifest of burn.exe.
In my Defines.wxi I have:
<?define MajorVersion="1" ?>
<?define MinorVersion="08" ?>
<?define BuildVersion="11" ?>
In my MyProject.Setup.wixproj I have:
<OutputName>MyProject</OutputName>
<OutputType>Package</OutputType>
Is it possible to include the version variables in the filename somehow, so that my file can be named MyProject.1.08.11.msi?
This didn't work (no such variable is defined):
<OutputName>MyProject-$(MajorVersion)</OutputName>
<OutputType>Package</OutputType>
This didn't work (no such variable is defined):
<Target Name="AfterBuild" Condition="'$(Configuration)' == 'Release'">
<Copy SourceFiles="$(OutputPath)$(OutputName).msi" DestinationFiles="C:\$(OutputName)-$(MajorVersion).msi" />
</Target>
It seems very clear to me that $(MajorVersion) is not the correct way of fetching the definition from the Defines.wxi file. What is?
Update
I tried to put this in MyProject.Setup.wixproj:
<InstallerMajorVersion>7</InstallerMajorVersion>
<InstallerMinorVersion>7</InstallerMinorVersion>
<InstallerBuildNumber>7</InstallerBuildNumber>
...
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>PrebuildPath=..\..\obj\prebuild\web\;InstallerMajorVersion=$(InstallerMajorVersion);InstallerMinorVersion=$(InstallerMinorVersion);InstallerBuildNumber=$(InstallerBuildNumber)</DefineConstants>
</PropertyGroup>
And this in Defines.wxi:
<?define MajorVersion="$(var.InstallerMajorVersion)" ?>
<?define MinorVersion="$(var.InstallerMinorVersion)" ?>
<?define BuildVersion="$(var.InstallerBuildNumber)" ?>
<?define Revision="0" ?>
<?define VersionNumber="$(var.InstallerMajorVersion).$(var.InstallerMinorVersion).$(var.InstallerBuildNumber)" ?>
Didn't work either. Got these error messages:
The Product/#Version attribute's value, '..', is not a valid version.
Legal version values should look like 'x.x.x.x' where x is an integer
from 0 to 65534.
The Product/#Version attribute was not found; it is
required.
This is what I ended up with, and it works!
Setup.Version.proj
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<InstallerMajorVersion>55</InstallerMajorVersion>
<InstallerMinorVersion>66</InstallerMinorVersion>
<InstallerBuildVersion>$(BuildNumber)</InstallerBuildVersion>
<InstallerBuildVersion Condition="$(InstallerBuildVersion) == ''">0</InstallerBuildVersion>
</PropertyGroup>
</Project>
MyProject.Setup.wixproj
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="Setup.Version.proj" />
<PropertyGroup>
<OutputName>MyProject_$(InstallerMajorVersion)_$(InstallerMinorVersion)_$(InstallerBuildVersion)</OutputName>
<OutputType>Package</OutputType>
<DefineConstants>InstallerMajorVersion=$(InstallerMajorVersion);InstallerMinorVersion=$(InstallerMinorVersion);InstallerBuildVersion=$(InstallerBuildVersion)</DefineConstants>
...
Defines.wxi
<?define MajorVersion="$(var.InstallerMajorVersion)" ?>
<?define MinorVersion="$(var.InstallerMinorVersion)" ?>
<?define BuildVersion="$(var.InstallerBuildVersion)" ?>
This common task should be simplified in future versions of WiX!
This solution combines #Wimmel's and this post. It draws the version from a target .exe, and otherwise does not store version numbers in files; it doesn't rename the output file in post-build. But, it is necessary to update the property ProjectDefineConstants, from which the candle arguments are derived (in wix.targets). Otherwise, updating only the TargetPath property does not change the inputs to candle.exe.
*.wixproj:
<Import Project="$(WixTargetsPath)" />
<Target Name="BeforeBuild">
<!-- Read the version from the to-be-installed .exe -->
<GetAssemblyIdentity AssemblyFiles="path.to.primary.exe">
<Output TaskParameter="Assemblies" ItemName="AsmInfo" />
</GetAssemblyIdentity>
<!-- Create the MSBuild property $(VersionNumber) -->
<CreateProperty Value="%(AsmInfo.Version)">
<Output TaskParameter="Value" PropertyName="VersionNumber" />
</CreateProperty>
<!-- Create the WiX preprocessor variable $(var.VersionNumber) -->
<CreateProperty Value="$(DefineConstants);VersionNumber=$(VersionNumber)">
<Output TaskParameter="Value" PropertyName="DefineConstants" />
</CreateProperty>
<!-- Update the MSBuild properties $(TargetName), etc. -->
<CreateProperty Value="$(SolutionName)-$(Platform)-$(VersionNumber)">
<Output TaskParameter="Value" PropertyName="TargetName" />
</CreateProperty>
<CreateProperty Value="$(TargetName)$(TargetExt)">
<Output TaskParameter="Value" PropertyName="TargetFileName" />
</CreateProperty>
<CreateProperty Value="$(TargetName)$(TargetPdbExt)">
<Output TaskParameter="Value" PropertyName="TargetPdbName" />
</CreateProperty>
<CreateProperty Value="$(TargetDir)$(TargetFileName)">
<Output TaskParameter="Value" PropertyName="TargetPath" />
</CreateProperty>
<CreateProperty Value="$(TargetPdbDir)$(TargetPdbName)">
<Output TaskParameter="Value" PropertyName="TargetPdbPath" />
</CreateProperty>
<!-- Update the MSBuild property from which candle.exe args are derived -->
<CreateProperty Value="
Configuration=$(ConfigurationName);
OutDir=$(OutDir);
Platform=$(PlatformName);
ProjectDir=$(ProjectDir);
ProjectExt=$(ProjectExt);
ProjectFileName=$(ProjectFileName);
ProjectName=$(ProjectName);
ProjectPath=$(ProjectPath);
TargetDir=$(TargetDir);
TargetExt=$(TargetExt);
TargetFileName=$(TargetFileName);
TargetName=$(TargetName);
TargetPath=$(TargetPath);
">
<Output TaskParameter="Value" PropertyName="ProjectDefineConstants" />
</CreateProperty>
</Target>
*.wxs
<Product Id="*" Version="$(var.VersionNumber)" ... >
...
</Product>
In your .wixproj file. Add the following section just before the </Project> tag.
<!-- rename the output msi with Version number -->
<Target Name="AfterBuild">
<GetAssemblyIdentity AssemblyFiles="[Path of the main assembly with the assembly version number you want to use]">
<Output TaskParameter="Assemblies" ItemName="AssemblyVersion"/>
</GetAssemblyIdentity>
<Copy SourceFiles=".\bin\$(Configuration)\$(OutputName).msi" DestinationFiles=".\bin\$(Configuration)\$(OutputName)_%(AssemblyVersion.Version).msi" />
<Delete Files=".\bin\$(Configuration)\$(OutputName).msi" />
</Target>
This works for me.
It is not possible to read the .wxi file from the .wixproj file. So you have to use another way to specify the version. I can give an example where I read the version from a assembly included in the installer, and use that version to rename the msi;
Open the .wixproj file in an editor and add a ReadVersion target:
<Target Name="ReadVersion">
<GetAssemblyIdentity AssemblyFiles="bin\program.exe">
<Output TaskParameter="Assemblies" ItemName="MyAssemblyIdentities" />
</GetAssemblyIdentity>
<Message Text="AssemblyVersion = %(MyAssemblyIdentities.Version)" />
<CreateProperty Value="$(TargetName) %(MyAssemblyIdentities.Version)">
<Output TaskParameter="Value" PropertyName="TargetName" />
</CreateProperty>
<CreateProperty Value="$(TargetName)$(TargetExt)">
<Output TaskParameter="Value" PropertyName="TargetFileName" />
</CreateProperty>
<CreateProperty Value="$(OutDir)$(TargetFileName)">
<Output TaskParameter="Value" PropertyName="TargetPath" />
</CreateProperty>
</Target>
This reads the version from bin\program.exe, displays it for debugging purposes, and changes the TargetName, TargetFileName and TargetPath.
After the line containing <Import Project="$(WixTargetsPath)" />, add the following to inject this target into the build process:
<PropertyGroup>
<BuildDependsOn>ReadVersion;$(BuildDependsOn)</BuildDependsOn>
</PropertyGroup>
One way would be to define the variables in your MSBuild script, and have it update Defines.wxi at build time, as in this example.
In your MSBuild script, you could define the version properties as follows:
<PropertyGroup>
<MajorVersion>1</MajorVersion>
<MinorVersion>08</MinorVersion>
<BuildVersion>11</BuildVersion>
<WixConfigPath>.\Defines.wxi</WixConfigPath>
<_VariableDefinitions>
<Root>
<VariableDefinition Name="MajorVersion" NewValue="$(MajorVersion)" />
<VariableDefinition Name="MinorVersion" NewValue="$(MinorVersion)" />
<VariableDefinition Name="BuildVersion" NewValue="$(BuildVersion)" />
</Root>
</_VariableDefinitions>
</PropertyGroup>
<Target Name="UpdateWixVars">
<WixVarSubstitution SourceFile="$(WixConfigPath)" VariableDefinitions="$(_VariableDefinitions)"/>
</Target>
Then running the UpdateWixVars target will update the version numbers in Defines.wxi with the version numbers specified in your MSBuild project.
Note that I could not find an actual compiled dll with this custom build task, so I had to create it by:
Download the source from here. Build it and name the file Tranxition.BuildTasks.dll.
Add the reference to the build task like so:
<UsingTask TaskName="WixVarSubstitution"
AssemblyFile="$(MSBuildExtensionsPath)\Tranxition\Tranxition.BuildTasks.dll"/>
You can accomplish this seamlessly by implementing these two answers:
First, update your project's AfterBuild task to rename the WIX-built MSI: https://stackoverflow.com/a/10716409/374198
Then, update your WIX project to automatically use the verison number of the assembly you're packaging: https://stackoverflow.com/a/641094/374198
The other answers are much too complex!
PS: If you want to drop the fourth digit, following semantic versioning, you can do it like this:
<Target Name="AfterBuild">
<GetAssemblyIdentity AssemblyFiles="..\Path\To\MyProject\bin\$(Platform)\$(Configuration)\MyProject.dll">
<Output TaskParameter="Assemblies" ItemName="AssemblyInfo" />
</GetAssemblyIdentity>
<PropertyGroup>
<In>%(AssemblyInfo.Version)</In>
<Pattern>^(\d+.\d+.\d+)</Pattern>
<AssemblyVersion>$([System.Text.RegularExpressions.Regex]::Match($(In), $(Pattern)))</AssemblyVersion>
</PropertyGroup>
<Move SourceFiles="bin\$(Platform)\$(Configuration)\MyProject.msi" DestinationFiles="bin\$(Platform)\$(Configuration)\CodeGenerator-$(AssemblyVersion).$(Platform).msi" />
</Target>
This will create an MSI named, for example, MyProject-1.2.3.x64.msi. See this answer for more.
This is a full example of a wixproj file where you can set a version number in the UI and use that to modify the output msi file name.
In Visual Studio (e.g. 2015):
define a version number in "Define preprocessor variables" in the
project properties window. I've entered VersionNumber=1.14 for this
example;
unload your project in the solution explorer;
right click your project in the solution explorer and select edit yourproject.wixproj file;
add code in the Target Name="BeforeBuild" element as shown below.
<?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>PROJECT-GUID</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>my project</OutputName>
<OutputType>Package</OutputType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<!-- These constants can be set in the UI -->
<DefineConstants>VersionNumber=1.14</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>VersionNumber=1.14</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="Product.wxs" />
</ItemGroup>
<ItemGroup>
<WixExtension Include="WixUIExtension">
<HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
<Name>WixUIExtension</Name>
</WixExtension>
</ItemGroup>
<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="BeforeBuild">
<!-- This extracts the version number from a setting in the UI -->
<!-- This method comes from: geekswithblogs.net/alexhildyard/archive/2013/03/09/passing-data-between-msbuild-and-wix.aspx -->
<ItemGroup>
<DefineConstantsKVPairs Include="$(DefineConstants)" />
</ItemGroup>
<!-- Evaluate each key/value pair with task batching, then make a conditional assignment -->
<PropertyGroup>
<VersionNumber Condition="$([System.String]::new('%(DefineConstantsKVPairs.Identity)').Contains('VersionNumber='))">$([System.String]::new('%(DefineConstantsKVPairs.Identity)').Split('=')[1])</VersionNumber>
</PropertyGroup>
<CreateProperty Value="$(OutputName)-$(VersionNumber)">
<Output TaskParameter="Value" PropertyName="TargetName" />
</CreateProperty>
<CreateProperty Value="$(TargetName)$(TargetExt)">
<Output TaskParameter="Value" PropertyName="TargetFileName" />
</CreateProperty>
<CreateProperty Value="$(TargetDir)$(TargetFileName)">
<Output TaskParameter="Value" PropertyName="TargetPath" />
</CreateProperty>
</Target>
</Project>