I'm using WIX 3.8 to create my setup file. This is my Product.wxs
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="{D16E42B5-3C6F-4EE5-B2F4-727BF8B74A92}" Name="My setup" Language="1033" Version="1.0.0.0" Manufacturer="Me" UpgradeCode="9279b740-8419-45c4-9538-6a45f8e949c7">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<Media Id="1" Cabinet="WCF.cab" EmbedCab="yes" />
<Feature Id="ProductFeature" Title="Wcf.Setup" Level="1">
<ComponentGroupRef Id="WCFComponents" />
</Feature>
<Property Id="WIXUI_INSTALLDIR" Value="INETPUB" />
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="INETPUB" Name="Inetpub">
<Directory Id="INSTALLFOLDER" Name="WCF">
</Directory>
</Directory>
</Directory>
</Fragment>
</Wix>
And here is the build file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebSiteSource>..\WCF\</WebSiteSource>
<SetupF>..\Setup\</SetupF>
<PublishF>publish\</PublishF>
<Publish>$(SetupF)$(PublishF)</Publish>
<WebSiteContentCode>WebSiteContent.wxs</WebSiteContentCode>
<WebSiteContentObject>WebSiteContent.wixobj</WebSiteContentObject>
<MsiOut>bin\Release\WCF.msi</MsiOut>
<WixPath>C:\PROGRA~2\WIXTOO~1.8\bin\</WixPath>
</PropertyGroup>
<ItemGroup>
<WebSiteContent Include="$(WebSiteContentCode)" />
</ItemGroup>
<ItemGroup>
<WixCode Include="Product.wxs" />
<WixCode Include="$(WebSiteContentCode)" />
</ItemGroup>
<ItemGroup>
<WixObject Include="Product.wixobj" />
<WixObject Include="$(WebSiteContentObject)" />
</ItemGroup>
<Target Name="Build">
<MSBuild
Projects="..\TMS.sln"
Targets="ReBuild"
Properties="Configuration=Release" />
</Target>
<Target Name="PublishWebsite">
<Message Text="Removing publish directory: $(SetupF)"/>
<RemoveDir Directories="$(SetupF)" ContinueOnError="false" />
<Message Text="Start to publish website" Importance="high" />
<MSBuild
Projects="..\\WCF\WCF.csproj"
Targets="ResolveReferences;_CopyWebApplication"
Properties="OutDir=$(Publish)bin\;WebProjectOutputDir=
$(Publish);Configuration=Release" />
</Target>
<Target Name="Harvest">
<Exec
Command='$(WixPath)heat dir $(Publish) -dr INSTALLFOLDER -ke -srd -cg WCFComponents -var var.publishDir -gg -out $(WebSiteContentCode)'
ContinueOnError="false"
WorkingDirectory="." />
</Target>
<Target Name="WIX">
<Exec
Command='"$(WixPath)candle" -ext WixIISExtension -ext WixUtilExtension -ext WixSqlExtension -dpublishDir=$(Publish) -dMyWebResourceDir=. #(WixCode, ' ')'
ContinueOnError="false"
WorkingDirectory="." />
<Exec
Command='"$(WixPath)light" -ext WixIISExtension -ext WixUIExtension -ext WixUtilExtension -ext WixSqlExtension -out $(MsiOut) #(WixObject, ' ')'
ContinueOnError="false"
WorkingDirectory="." />
<Message Text="Install package has been created." />
</Target>
<Target Name="DeleteTmpFiles">
<RemoveDir Directories="$(Publish)" ContinueOnError="false" />
<RemoveDir Directories="$(SetupF)" ContinueOnError="false" />
<Delete Files="#(WixObject);#(WebSiteContent)" />
</Target>
</Project>
I always receive the error message: Product.wxs(10): error LGHT0094: Unresolved reference to symbol 'WixComponentGroup:WCFComponents' in section 'Product:{D16E42B5-3C6F-4EE5-B2F4-727BF8B74A92}'.
I copied exactly the source code from this topic http://blog.bartdemeyer.be/2013/10/create-an-installer-for-website-with-wix-part-1/ to my project but the source code from here runs property but mine doesn't work.
Could you please help me to solve this problem? Thanks a lot.
I solved this problem by removing Build parameter from command line.
It should be:
msbuild setup.build /t:Build;PublishWebSite;Harvest;WIX;DeleteTmpFiles
The reason is you can’t build your solution because MyProject.Setup can’t be built.
Related
I need to create an MSI for distribution, the old story but new situation. I don't use Visual Studio, only the Wix Toolset (3.11.2.4516). My files are under the msi folder:
MyFolder
|
---msi
| |
| ---Sample1.txt
| |
| ---Sample2.txt
|
---build.bat
|
---Product.wxs
Basically, I do harvest those files from the msi folder into an msi.wxs:
heat dir msi -cg MsiFilesGroup -dr MsiDir -gg -sfrag -srd -out msi.wxs
and I get a ComponentGroup called MsiFilesGroup. The main part (Product.wxs) defines an interactive WixUI to guide the user during the installation.
These Product.wxs defines a feature what references the above files:
<?xml version="1.0" encoding="utf-8" ?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="B858BC76-AD11-45c3-A300-D1C6B73DFF56" Name="Pruders" Language="1033" Version="0.0.0.0"
UpgradeCode="{FA34F953-F659-4633-B8D2-893BF7A63642}" Manufacturer="Microsoft Corporation">
<Package Description="Test WIXUI_INSTALLDIR" Comments="TestWIXUI_INSTALLDIR"
InstallerVersion="200" Compressed="yes" />
<Media Id="1" Cabinet="product.cab" EmbedCab="yes" />
<Feature Id="TestFileProductFeature" Title="Test File Product Feature" Level="1">
<ComponentRef Id="MsiFilesGroup" />
</Feature>
<Property Id="SQLCLRTYPES">
<RegistrySearch Id="SqlClrTypesSearch" Root="HKLM" Type="raw"
Key="SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
Name="KeyName1"/>
</Property>
<Property Id="WIXUI_INSTALLDIR" Value="TESTFILEPRODUCTDIR" />
<Property Id="WixAppFolder" Value="WixPerMachineFolder" />
<Property Id="buttonGroup" Value="1" />
<UIRef Id="WixUI_InstallDir" />
</Product>
</Wix>
If I use ComponentRef for referencing I get this error:
error LGHT0094 : Unresolved reference to symbol 'Component:MsiFilesGroup'
in section 'Product:{B858BC76-AD11-45C3-A300-D1C6B73DFF56}'
If I use ComponentGroup, it fails in this way:
Product.wxs(8) : error CNDL0005 : The Feature element contains an unexpected child element 'ComponentGroup'.
light.exe : error LGHT0103 : The system cannot find the file 'Product.wixobj' with type 'Source'.
Any hint would be a greate help.
The build.bat contains the calls of Wix commands, as it follows:
#echo off
del *.msi
del *.wix*
del msi.wxs
heat dir msi -cg MsiFilesGroup -dr MsiDir -gg -sfrag -srd -out msi.wxs
candle msi.wxs
candle Product.wxs
light -ext WixUIExtension msi.wixobj Product.wixobj -out Product.msi
It is the light.exe command that you are lacking, and there are a number of other things you need to adjust as well.
Here are two slightly modified and simplified batch and WiX sources. Notice the two *.wixobj files fed to light.exe and the -var var.sourcefolder added in there to set the source directory:
Suggested "Build.cmd":
#echo off
heat dir msi -cg MsiFilesGroup -dr INSTALLFOLDER -gg -sfrag -srd -suid -var var.sourcefolder -out msi.wxs
candle -dsourcefolder="msi" msi.wxs >> Build.log
candle Product.wxs >> Build.log
light -ext WixUIExtension Product.wixobj msi.wixobj -out Product.msi >> Build.log
rem pause
Suggested (simplified) "Product.wxs" - I find that only the Mondo dialog set is working "on its own" without any modification or fiddling:
<?xml version="1.0" encoding="utf-8" ?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="B858BC76-AD11-45c3-A300-D1C6B73DFF56" Name="Pruders" Language="1033" Version="0.0.0.0"
UpgradeCode="{FA34F953-F659-4633-B8D2-893BF7A63642}" Manufacturer="Microsoft Corporation">
<Package Description="Test WIXUI_INSTALLDIR" Comments="TestWIXUI_INSTALLDIR"
InstallerVersion="200" Compressed="yes" />
<Media Id="1" Cabinet="product.cab" EmbedCab="yes" />
<Feature Id="TestFileProductFeature" Title="Test File Product Feature" Level="1">
<ComponentGroupRef Id="MsiFilesGroup" />
</Feature>
<UIRef Id="WixUI_Mondo" />
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="Test Folder" />
</Directory>
</Directory>
</Fragment>
</Wix>
From my understanding, using DependsOnTargets is necessary to pass ItemGroup between targets. I am not sure if there are other ways to pass targets without DependsOnTargets.
I have tested that ItemGroup cannot pass from CallTarget or MSBuild task. A workaround solution is convert the ItemGroup to property (flatten it) and use Properties to pass over.
I define a ItemGroup of File. The File has Value metadata. I would like to execute target and remove one File item for each recursive loop. Here is my script:
<Target Name="MyGroup">
<ItemGroup>
<File Include="5">
<Value>5a</Value>
</File>
<File Include="4">
<Value>4a</Value>
</File>
<File Include="3">
<Value>3a</Value>
</File>
<File Include="2">
<Value>2a</Value>
</File>
<File Include="1">
<Value>1a</Value>
</File>
</ItemGroup>
</Target>
<Target Name="Recursive" DependsOnTargets="MyGroup" Condition="$(Value) > 0">
<ItemGroup>
<File Remove="$(Value)" />
</ItemGroup>
<PropertyGroup>
<Value>$([MSBuild]::Subtract($(Value), 1))</Value>
</PropertyGroup>
<Message Text="File: #(File->'%(Value)') Value=$(Value)" Importance="High" />
<MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=$(Value)"/>
</Target>
<Target Name="Build" DependsOnTargets="MyGroup">
<MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=5" />
</Target>
The output is:
File: 4a;3a;2a;1a Value=4
File: 5a;3a;2a;1a Value=3
File: 5a;4a;2a;1a Value=2
File: 5a;4a;3a;1a Value=1
File: 5a;4a;3a;2a Value=0
I expect the output to be:
File: 4a;3a;2a;1a Value=4
File: 3a;2a;1a Value=3
File: 2a;1a Value=2
File: 1a Value=1
File: Value=0
Is there a solution?
Not really, you are trying to circumvent idea of msbuild to build target only once (unless inputs\outputs changes).
And you can't pass itemgroups between MSBuild contexts (when you call MSBuild task - new context is created). Also in your script - ItemGroup is scoped to target - you need to define it globally so it'll be available to other targets.
What you can do is:
Define Global property Value with condition to use the one passed to script if exists.
Change ItemGroup from MyGroup target to global scope.
Define conditions on each element of itemgroup to be emitted depending on the value of Value property
e.g. your script will be something like this:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Value Condition="$(Value) == ''">5</Value>
</PropertyGroup>
<ItemGroup>
<File Include="5" Condition="$(Value) >5">
<Value>5a</Value>
</File>
<File Include="4" Condition="$(Value) >4">
<Value>4a</Value>
</File>
<File Include="3" Condition="$(Value) >3">
<Value>3a</Value>
</File>
<File Include="2" Condition="$(Value) >2">
<Value>2a</Value>
</File>
<File Include="1" Condition="$(Value) >1">
<Value>1a</Value>
</File>
</ItemGroup>
<Target Name="Recursive" Condition="$(Value) >0">
<PropertyGroup>
<Value>$([MSBuild]::Subtract($(Value), 1))</Value>
</PropertyGroup>
<Message Text="File: #(File->'%(Value)') Value=$(Value)" Importance="High" />
<MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=$(Value)"/>
</Target>
<Target Name="Build">
<MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=5" />
</Target>
</Project>
As Alexey Shcherbak points out, we can't pass ItemGroup from MSBuild task. I resolve my problem by introducing a new property Done to keep a list of item that has processed.
<Target Name="MyGroup">
<ItemGroup>
<File Include="5">
<Value>5a</Value>
</File>
<File Include="4">
<Value>4a</Value>
</File>
<File Include="3">
<Value>3a</Value>
</File>
<File Include="2">
<Value>2a</Value>
</File>
<File Include="1">
<Value>1a</Value>
</File>
</ItemGroup>
</Target>
<Target Name="Recursive" DependsOnTargets="MyGroup" Condition="$(Value) > 0" >
<ItemGroup>
<File Remove="$(Value)" />
<File Remove="$(Done)" />
</ItemGroup>
<Message Text="File: #(File->'%(Value)') Value=$(Value)" Importance="High" />
<PropertyGroup>
<Done>$(Done);$(Value)</Done>
<Value>$([MSBuild]::Subtract($(Value), 1))</Value>
</PropertyGroup>
<MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=$(Value);Done=$(Done)" />
</Target>
<Target Name="Build" DependsOnTargets="MyGroup">
<MSBuild Projects="$(MSBuildProjectFile)" Targets="Recursive" Properties="Value=5" />
</Target>
I am trying to run multiple commands on a list of files based on a pattern (all files of form *.config under sub directories of a given directory), like so:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="BuildSolution" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="TransformXml"
AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<TransformConfiguration>Release</TransformConfiguration>
<PublishFolder>$(OutDir)_PublishedWebsites</PublishFolder>
</PropertyGroup>
<Target Name="BuildSolution">
<MSBuild Projects="$(MSBuildProjectDirectory)\SolutionName.sln"
ContinueOnError="false"
Properties="PublishProfile=$(TransformConfiguration);DeployOnBuild=true" />
</Target>
<ItemGroup>
<ConfigFiles Include="$(PublishFolder)\**\*.config" />
</ItemGroup>
<Target Name="TransformWebConfig" AfterTargets="BuildSolution"
Condition="'#(ConfigFiles)'!=''"
Outputs="%(ConfigFiles.Identity)">
<PropertyGroup>
<ConfigFile>%(ConfigFiles.Identity)</ConfigFile>
<BackupFile>$([System.IO.Path]::ChangeExtension($(ConfigFile),".Source.config"))</BackupFile>
<TransformFile>$([System.IO.Path]::ChangeExtension($(ConfigFile),$(TransformConfiguration) + ".Source.config"))</TransformFile>
</PropertyGroup>
<Message Text="$(ConfigFile)" />
<Message Text="$(BackupFile)" />
<Message Text="$(TransformFile)" />
<Copy SourceFiles="$(ConfigFile)"
DestinationFiles="$(BackupFile)" />
<Exec Command="attrib -r $(ConfigFile)" />
<TransformXml Source="$(BackupFile)"
Transform="$(TransformFile)"
Destination="$(ConfigFile)"
StackTrace="false" />
</Target>
</Project>
However, the batch processing of the matching files is not performed.
From outputs I have added I see that the property $(PublishFolder) points to the correct directory, however, the item #(ConfigFiles) is left empty.
I also tried manually listing the directory names and configuration file names like so:
<ItemGroup>
<Sites Include="Site1" />
<Sites Include="Site2" />
</ItemGroup>
<ItemGroup>
<ConfigFiles Include="Web" />
<ConfigFiles Include="NLog" />
</ItemGroup>
<Target Name="TransformWebConfig" AfterTargets="BuildSolution">
<PropertyGroup>
<SiteConfigFile>$(PublishFolder)\%(Sites.Identity)\%(ConfigFiles.Identity)</SiteConfigFile>
</PropertyGroup>
<Message Text="$(SiteConfigFile)" />
<Copy SourceFiles="$(SiteConfigFile).config"
DestinationFiles="$(SiteConfigFile).Source.config"/>
<Exec Command="attrib -r $(SiteConfigFile).config" />
<TransformXml Source="$(SiteConfigFile).Source.config"
Transform="$(SiteConfigFile).$(TransformConfiguration).config"
Destination="$(SiteConfigFile).config"
StackTrace="false" />
</Target>
However, in this case, the transform is only applied on one file in one site.
Any idea what to do to get this working?
Similar questions and MSDN references I have gone through:
MSBUild: Copy files with a name based on the original (following a pattern)
MSBuild multiple outputpath
How to invoke the same msbuild target twice with different parameters from within msbuild project file itself
msbuild array iteration
http://msdn.microsoft.com/en-us/library/ms171454.aspx
Edit:
Moving the ItemGroup under the task enabled reading the file list after the files were created, however, now only the first file from the list is transformed:
<ItemGroup>
<ConfigFiles Include="$(PublishFolder)\**\Web.config;$(PublishFolder)\**\NLog.config"
Exclude="$(PublishFolder)\**\Packages.config;$(PublishFolder)\**\*.*.config;$(PublishFolder)\**\bin\*.config" />
</ItemGroup>
<PropertyGroup>
<ConfigFile>%(ConfigFiles.Identity)</ConfigFile>
<BackupFile>$([System.IO.Path]::ChangeExtension($(ConfigFile),".Source.config"))</BackupFile>
<TransformFilePrefix>$([System.String]::Concat($(TransformConfiguration), ".config"))</TransformFilePrefix>
<TransformFile>$([System.IO.Path]::ChangeExtension($(ConfigFile), $(TransformFilePrefix)))</TransformFile>
</PropertyGroup>
<Message Text="$(PublishFolder)" />
<Message Text="#(ConfigFiles)" />
<Message Text="$(ConfigFile)" />
<Message Text="$(BackupFile)" />
<Message Text="$(TransformFile)" />
<Copy SourceFiles="$(ConfigFile)"
DestinationFiles="$(BackupFile)" />
<Exec Command="attrib -r $(ConfigFile)" />
<TransformXml Source="$(BackupFile)"
Transform="$(TransformFile)"
Destination="$(ConfigFile)"
StackTrace="false" />
Found the solution:
Create one target for creating the item group:
<Target Name="ListWebConfigs" AfterTargets="BuildSolution">
<ItemGroup>
<ConfigFiles Include="$(PublishFolder)\**\Web.config;$(PublishFolder)\**\NLog.config"
Exclude="$(PublishFolder)\**\Packages.config;$(PublishFolder)\**\*.*.config;$(PublishFolder)\**\bin\*.config" />
</ItemGroup>
<Message Text="$(PublishFolder)" />
<Message Text="#(ConfigFiles)" />
</Target>
Then another for the actual transforms:
<!-- \x to prevent MSBuild from skipping "because all output files are up-to-date" -->
<Target Name="TransformWebConfig" AfterTargets="ListWebConfigs" Inputs="#(ConfigFiles)" Outputs="%(ConfigFiles.Identity)\x">
<PropertyGroup>
<ConfigFile>%(ConfigFiles.Identity)</ConfigFile>
<BackupFile>$([System.IO.Path]::ChangeExtension($(ConfigFile),".Source.config"))</BackupFile>
<TransformFilePrefix>$([System.String]::Concat($(TransformConfiguration), ".config"))</TransformFilePrefix>
<TransformFile>$([System.IO.Path]::ChangeExtension($(ConfigFile), $(TransformFilePrefix)))</TransformFile>
</PropertyGroup>
<Message Text="$(PublishFolder)" />
<Message Text="#(ConfigFiles)" />
<Message Text="$(ConfigFile)" />
<Message Text="$(BackupFile)" />
<Message Text="$(TransformFile)" />
<Copy SourceFiles="$(ConfigFile)" DestinationFiles="$(BackupFile)" />
<Exec Command="attrib -r $(ConfigFile)" />
<TransformXml Source="$(BackupFile)"
Transform="$(TransformFile)"
Destination="$(ConfigFile)"
StackTrace="false" />
</Target>
In my AfterBuild script I use the following method to upload the files to the deployment server:
<MSBuild.ExtensionPack.Communication.Ftp
TaskAction="UploadFiles"
Host="localhost"
FileNames="$(SomeFolder)\$(FileToUpload)"
UserName="myUserName"
UserPassword="myPassword"
RemoteDirectoryName="/" />
How can I load these credentials from a text file or an external source? What are the alternatives? I don't want to hard-code ftp credentials into my cproj files.
I used GranadaCoders method to answer my own question:
<MSBuild.ExtensionPack.Xml.XmlFile TaskAction="ReadAttribute" File="$(FTP_Credentials_File)" XPath="/parameters/setParameter[#name='host']/#value">
<Output PropertyName="FtpHost" TaskParameter="Value"/>
</MSBuild.ExtensionPack.Xml.XmlFile>
<MSBuild.ExtensionPack.Xml.XmlFile TaskAction="ReadAttribute" File="$(FTP_Credentials_File)" XPath="/parameters/setParameter[#name='username']/#value">
<Output PropertyName="FtpUserName" TaskParameter="Value"/>
</MSBuild.ExtensionPack.Xml.XmlFile>
<MSBuild.ExtensionPack.Xml.XmlFile TaskAction="ReadAttribute" File="$(FTP_Credentials_File)" XPath="/parameters/setParameter[#name='password']/#value">
<Output PropertyName="FtpPassword" TaskParameter="Value"/>
</MSBuild.ExtensionPack.Xml.XmlFile>
<Message Text="Attempting to uploade $(GeneratedZipFile) to $(FtpHost) as read from $(FTP_Credentials_File) ..." Importance="high" />
<MSBuild.ExtensionPack.Communication.Ftp TaskAction="UploadFiles" Condition="Exists('$(FTP_Credentials_File)')" Host="$(FtpHost)" FileNames="$(PublicFolderToDropZip)\$(GeneratedZipFile)" UserName="$(FtpUserName)" UserPassword="$(FtpPassword)" RemoteDirectoryName="/" />
Put the values in an external xml file.
Read the values from the xml file into a variable.
Parameters.xml
<?xml version="1.0" encoding="utf-8"?>
<parameters>
<setParameter name="LineNumber1" value="PeanutsAreCool" />
<setParameter name="LineNumber2" value="" />
</parameters>
MyMsbuild_MsBuildExtensions.proj
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="AllTargetsWrapped">
<Import Project="$(MSBuildExtensionsPath)\ExtensionPack\4.0\MSBuild.ExtensionPack.tasks"/>
<PropertyGroup>
<!-- Always declare some kind of "base directory" and then work off of that in the majority of cases -->
<WorkingCheckout>.</WorkingCheckout>
</PropertyGroup>
<Target Name="AllTargetsWrapped">
<CallTarget Targets="ReadXmlPeekValue" />
</Target>
<Target Name="ReadXmlPeekValue">
<!-- ReadAttribute -->
<MSBuild.ExtensionPack.Xml.XmlFile TaskAction="ReadAttribute" File="$(WorkingCheckout)\Parameters.xml" XPath="/parameters/setParameter[#name='LineNumber1']/#value">
<Output PropertyName="MyValue1" TaskParameter="Value"/>
</MSBuild.ExtensionPack.Xml.XmlFile>
<Message Text="MyValue1 = $(MyValue1)"/>
</Target>
</Project>
OR
MyMsbuild_WithCommunityTasks.proj
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="AllTargetsWrapped">
<!--
<UsingTask AssemblyFile="$(ProgramFiles)\MSBuild\MSBuild.Community.Tasks.dll" TaskName="Version"/>
-->
<Import Project="$(MSBuildExtensionsPath32)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
<PropertyGroup>
<!-- Always declare some kind of "base directory" and then work off of that in the majority of cases -->
<WorkingCheckout>.</WorkingCheckout>
</PropertyGroup>
<Target Name="AllTargetsWrapped">
<CallTarget Targets="ReadXmlPeekValue" />
</Target>
<Target Name="ReadXmlPeekValue">
<!-- you do not need a namespace for this example, but I left it in for future reference -->
<XmlPeek Namespaces="<Namespace Prefix='peanutNamespace' Uri='http://schemas.microsoft.com/developer/msbuild/2003'/>"
XmlInputPath=".\Parameters.xml"
Query="/parameters/setParameter[#name='LineNumber1']/#value">
<Output TaskParameter="Result" ItemName="Peeked" />
</XmlPeek>
<Message Text="#(Peeked)"/>
<XmlPeek Namespaces="<Namespace Prefix='peanutNamespace' Uri='http://schemas.microsoft.com/developer/msbuild/2003'/>"
XmlInputPath=".\Parameters.xml"
Query="/parameters/setParameter[#name='LineNumber1']/#value">
<Output TaskParameter="Result" PropertyName="PeekedSingle" />
</XmlPeek>
<Message Text="PeekedSingle = $(PeekedSingle) "/>
</Target>
</Project>
EDIT:
You can add some basic error checking for the values.
See URL here:
http://tutorials.csharp-online.net/MSBuild:_By_Example%E2%80%94Dealing_with_MSBuild_Errors
Short example.. note the condition..and how it checks for an empty string.
<Error Text="Unable to connect to webserver" Code="Deploy" Condition=" '$(WebURL)' == '' "/>
I am using WIX with MSBuild. I am trying to copy a com library and a .ttf file to two different locations and I want to register the com library using WIX. When I run it using Visual Build Pro I don't see any errors or warnings and I can see the copy scripts being added to setup files. But the files are not copied to the specified directory after installing the setup.
Build.msbuild with <Target> as below:
<Target Name="Setup">
<!-- Setup the source directory structure as it should appear on the target machine -->
<ItemGroup>
<DeployFiles Include="$(Includes)" Exclude="$(Excludes)" />
<PostHarvestFiles Include="$(PostHarvestIncludes)" Exclude="$(PostHarvestExcludes)" />
</ItemGroup>
<MakeDir Directories="$(OutputDir)" />
<MakeDir Directories="$(FinalOutputDir)" />
<MakeDir Directories="$(FilesToInstallDir)" />
<!-- Harvest the newly created directory structure for the MSI -->
<Copy SourceFiles="#(DeployFiles)" DestinationFiles="#(DeployFiles->'$(FilesToInstallDir)\%(RecursiveDir)%(Filename)%(Extension)')" />
<Exec Command='$(BuildToolsDir)\Wix\heat.exe dir "$(FilesToInstallDir)" -dr INSTALLDIR -gg -cg FilesToInstall -sfrag -srd -sreg -out "$(MSBuildThisFileDirectory)Files.wxs" -var var.BaseDir' />
<Copy Condition="'%(Extension)' == '.ttf'" SourceFiles="#(PostHarvestFiles)" DestinationFiles="#(PostHarvestFiles->'$(FilesToInstallDir)\%(RecursiveDir)%(Filename)%(Extension)')" />
<!-- Harvest the old renderer DLL. This is a COM object and needs special handling -->
<Copy Condition="'%(Extension)' == '.dll'" SourceFiles="#(PostHarvestFiles)" DestinationFiles="#(PostHarvestFiles->'$(ComFilesToInstallDir)\%(RecursiveDir)%(Filename)%(Extension)')" />
<Exec Command='$(BuildToolsDir)\Wix\heat.exe file "$(ComFilesToInstallDir)\ComSrv.dll" -dr COMINSTALLDIR -ag -cg COMObjectsToInstall -out "$(MSBuildThisFileDirectory)COMDlls.wxs" -var var.ExternalsDir' />
</Target>
<Target Name="CompileWix" DependsOnTargets="Setup">
<!-- Create the Wix object files for linking in the next task -->
<ItemGroup>
<WixFiles Include="$(SourceDir)\Installer-Website\*.wxs" />
</ItemGroup>
<!-- Compile the Wix object files -->
<Exec Command="$(BuildToolsDir)\Wix\candle.exe -dBaseDir="$(FilesToInstallDir)" -dBuildToolsDir="$(BuildToolsDir)" -dExternalsDir="$(SourceDir)\ExternalAssembly" -dFinalVersion=$(FinalVersion) -ext WiXNetFxExtension -ext WixIisExtension -out $(OutputDir)\ #(WixFiles->'%(Filename)% (Extension)',' ')" />
</Target>
<Target Name="BuildMsi" DependsOnTargets="CompileWix">
<!-- Link the Wix object files into the final MSI -->
<ItemGroup>
<WixObjectFiles Include="$(OutputDir)\*.wixobj" />
</ItemGroup>
<!-- Link the Wix object files into the final MSI -->
<Exec Command="$(BuildToolsDir)\Wix\light.exe -cultures:en-us -loc "$(MSBuildThisFileDirectory)WebAppInstallDlg_en-us.wxl" -sice:ICE17 -sice:ICE38 -sice:ICE43 -sice:ICE57 -sice:ICE64 -ext WixUIExtension -ext WiXNetFxExtension -ext WixIisExtension -out $(OutputDir)\$(MsiName) #(WixObjectFiles->'%(FullPath)',' ')" />
<Copy SourceFiles="$(OutputDir)\$(MsiName)" DestinationFolder="$(FinalOutputDir)" />
</Target>
Product.wxs file with Directory as below:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="INSTALLDIR" Name="$(var.BaseProductName)">
<Directory Id="FontsFolder">
<Component Id="cmp_FontsToInstall" Guid="{C286A08B-28CB-4A62-9BF8-833A6B141CB4}">
<File Id="fil82FBA6D3A96B47C48C72FA2F03739758" KeyPath="yes" TrueType="yes" Source="$(var.BaseDir)\OOCA.ttf" />
</Component>
</Directory>
<Directory Id="COMINSTALLDIR" >
<Component Id="COMObjectsToInstall" Guid="{5BAD46DE-D6AB-42D0-A13E-2407F8FBC97B}" >
<File Id="filE617B0B38D366E756290A5B22F2660C4" KeyPath="yes" TrueType="no" Source="$(var.BaseDir)\bin\ComSrv.dll" />
</Component>
</Directory>
.
.
.
.
</Directory>
</Directory>
I am new to this MSBuild and Wix. Can any one please point out what was is wrong in my script.
Thanks MikeR. I have included the files. But name of the property (PostHarvestIncludes) I have used is not spelled correctly. It is solved.