TransformXml task failed while packaging - msbuild

Hi when I try to do packaging stuff in MSBuild and build the solution.
<Target Name="BeforeBuild">
<MSBuild Projects="%(ProjectReference.FullPath)" Targets="Package" Properties="Configuration=$(Configuration);Platform=AnyCPU" Condition="'%(ProjectReference.WebProject)'=='True'" />
<ItemGroup>
<LinkerBindInputPaths Include="%(ProjectReference.RootDir)%(ProjectReference.Directory)obj\$(Configuration)\Package\PackageTmp\" />
</ItemGroup>
</Target>
Was getting "TransformXml" task failed error.Not sure How to fix it.
Error 3 The "TransformXml" task failed unexpectedly.
System.UriFormatException: Invalid URI: The URI is empty.
at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
at System.Uri..ctor(String uriString)
at Microsoft.Web.Publishing.Tasks.TransformXml.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__20.MoveNext() C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.Publishing.targets 1496 6 SCBUDirectMSI

Related

How to copy all json file to new folder by MsBuild?

Steps to reproduce
On windows it works fine with this command :
<PropertyGroup>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<PreBuildEvent>IF NOT EXIST "$(TargetDir)DataFiles" MKDIR "$(TargetDir)DataFiles"</PreBuildEvent>
<PostBuildEvent>FOR /R "$(SolutionDir)\Api.Tests\Scenarios" %25%25f IN (*.json) DO COPY "%25%25f" "$(TargetDir)DataFiles\" /Y</PostBuildEvent>
</PropertyGroup>
On linux , I have this kind of error
Build FAILED.
[12:44:39][Step 1/1]
[12:44:39][Step 1/1] /usr/share/dotnet/sdk/2.1.302/Microsoft.Common.CurrentVersion.targets(1331,5): error MSB3073: The command "IF NOT EXIST "DataFiles" MKDIR "DataFiles"" exited with code 127. [/opt/jetbrains/buildAgent/work/4fc9032bf5656724/Api.Tests/Api.Tests/Api.Tests.csproj]
[12:44:39][Step 1/1] 0 Warning(s)
[12:44:39][Step 1/1] 1 Error(s)
Your post build event uses CMD.EXE specific code - also known as (Windows) BATCH commands. In other words it is platform specific.
Best thing is to use MSBuild built-in features to copy files:
Remove the PreBuildEvent and PostBuildEvents properties
Add the following inside the "Project" tag of your project file (best at the end).
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);_CopyAuxFiles
</BuildDependsOn>
</PropertyGroup>
<Target Name="_CopyAuxFiles">
<MakeDir Directories="$(TargetDir)DataFiles"/>
<ItemGroup>
<Files Include="$(SolutionDir)\Api.Tests\Scenarios\*.json"/>
</ItemGroup>
<CopyFile SourceFiles="#(Files)" DestinationFolder="$(TargetDir)DataFiles"/>
</Target>
You might need to replace "$(TargetDir)" with "$(OutputPath)".
I have resolved it by
<Target Name="CopyScenarios" AfterTargets="Build">
<ItemGroup>
<Scenarios Include="$(ProjectDir)/Scenarios/**/*.json" />
</ItemGroup>
<Copy SourceFiles="#(Scenarios)" DestinationFiles="#(Scenarios->'$(TargetDir)DataFiles/%(Filename)%(Extension)')" SkipUnchangedFiles="false" />
</Target>

Files in ItemGroup not detected by AfterBuild Target

What the question should have been:
Here is the content of my ModuleCompilation.targets file :
<ItemGroup>
<ConfigFilesToMove Include="bin\$(Configuration)\*.config"/>
</ItemGroup>
<Target Name="AfterBuild">
<Message Text="Message for AfterBuild" />
<Move SourceFiles="#(ConfigFilesToMove)" DestinationFolder="bin\$(Configuration)\Configuration\" />
</Target>
The Message is written to the console but the files are not moved, how come ?
Original question (you can ignore):
I have included an Import in my csproj file to import a task from another file :
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\ModuleCompilation.targets" />
Now, here is the content of my ModuleCompilation.targets file :
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="AfterBuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<BaseFiles Include="bin\$(Configuration)\Libraries\ModuleBase*"/>
<ConfigFilesToMove Include="bin\$(Configuration)\*.config"/>
<OtherFilesToMove Include="bin\$(Configuration)\*" Exclude="bin\$(Configuration)\$(MSBuildProjectName)*" />
</ItemGroup>
<Target Name="AfterBuild">
<Message Text="AfterBuild" />
<Move SourceFiles="#(ConfigFilesToMove)" DestinationFolder="bin\$(Configuration)\Configuration\" />
<Move SourceFiles="#(OtherFilesToMove)" DestinationFolder="bin\$(Configuration)\Libraries\" />
<Message Text="bin\$(Configuration)\Libraries\ModuleBase*" />
<Delete Files="#(BaseFiles)" />
</Target>
</Project>
When I build or rebuild, I do have the "AfterBuild" message in my console, and the files are all indeed generated, but they haven't moved from the Debug folder to where I want them to be.
If I rebuild my projet, the files are moved, I guess because there already were present, but I want to files to be generated and then to be moved, I don't want to have them to be already present !
I must be missing something really obvious, can you help me please ?
Edit:
Ok so I've made some tests and this works :
<ConfigFilesToMove Include="bin\Debug\App.config"/>
While this doesn't:
<ConfigFilesToMove Include="bin\Debug\*.config"/>
Does anyone knowns why ?
Edit 2:
This is really weird, here is my code :
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Files Include="$(OutputPath)*.config"/>
<Pouet Include="bin\Debug\*.dll"/>
</ItemGroup>
<Target Name="AfterBuild">
<Message Text="#(Pouet)" />
<Message Text="pouetss" Condition="Exists(#(Pouet))"/>
<Message Text="nooo" Condition="!Exists(#(Pouet))"/>
<MakeDir Directories="$(OutputPath)Configuration\" />
<Copy SourceFiles="#(Pouet)" DestinationFolder="$(OutputPath)Configuration\" />
</Target>
</Project>
Here is what the log from MSBuild says :
1>Target "AfterBuild: (TargetId:75)" in file "C:\Tests\ModuleTest\Modules\ModuleCompilation.targets" from project "C:\Tests\ModuleTest\Modules\FirstModule\FirstModule.csproj" (target "Build" depends on it):
1>Task "Message" (TaskId:47)
1>Done executing task "Message". (TaskId:47)
1>Task "Message" skipped, due to false condition; (Exists(#(Pouet))) was evaluated as (Exists()).
1>Task "Message" (TaskId:48)
1> Task Parameter:Text=nooo (TaskId:48)
1> nooo (TaskId:48)
1>Done executing task "Message". (TaskId:48)
1>Task "MakeDir" (TaskId:49)
1> Task Parameter:Directories=bin\Debug\Configuration\ (TaskId:49)
1> Creating directory "bin\Debug\Configuration\". (TaskId:49)
1>Done executing task "MakeDir". (TaskId:49)
1>Task "Copy" (TaskId:50)
1> Task Parameter:DestinationFolder=bin\Debug\Configuration\ (TaskId:50)
1>Done executing task "Copy". (TaskId:50)
1>Done building target "AfterBuild" in project "FirstModule.csproj".: (TargetId:75)
So MSBuild ignores every value that contains a wildcard ?
Problem :
ItemGroup created outside of a Target are resolved before any Target is run, so you can't target files that a Target will create
Solution :
I changed my code to :
<Target Name="AfterBuild">
<ItemGroup>
<ConfigFilesToMove Include="bin\$(Configuration)\*.config"/>
</ItemGroup>
<Message Text="Message for AfterBuild" />
<Move SourceFiles="#(ConfigFilesToMove)" DestinationFolder="bin\$(Configuration)\Configuration\" />
</Target>
And now my files are detected because the ItemGroup is resolved after the files are created.

MSBuild /m:4 fails because it builds the same project twice

My team has a large solution (~500 csproj's). We use VS2012, and build using TFS Build, which uses MSBuild 4. Currently we build serially, but we want to build in parallel (using msbuild /maxcpucount:4). However, when I try it on my 4-proc machine, I get a weird failure:
11:2>CSC : fatal error CS0042: Unexpected error creating debug information file 'C:\Common\obj\Debug\Common.PDB' -- 'C:\Common\obj\Debug\Common.pdb: The process cannot access the file because it is being used by another process. [C:\Common\Common.csproj]
Looking at the log, 2 msbuild nodes were trying to build that same csproj, and thus colliding on writing some output:
10>Project "C:\Utils\Utils.csproj" (10) is building "C:\Common\Common.csproj" (11) on node 4 (default targets).
46:2>Project "C:\Objects\Objects.csproj" (46:2) is building "C:\Common\Common.csproj" (11:2) on node 1 (default targets).
Why would MSBuild try to build the same project twice?
Cause: Someone was calling <MSBuild Projects="Common.csproj" Properties="..." />. Then, MSBuild thinks that it should build Common.csproj again with those different properties, and it happened to occur at the same time with the regular compilation of Common.csproj.
Fix: Call <MSBuild ... /> without those unneeded properties.
Test:
Common.targets
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build">
<Message Importance="high" Text="Build in $(MSBuildThisFile)" />
</Target>
<Target Name="After" DependsOnTargets="Build">
<Message Importance="high" Text="After in $(MSBuildThisFile)" />
</Target>
</Project>
Other.targets
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build">
<Message Importance="high" Text="Build in $(MSBuildThisFile)" />
<MSBuild Projects="common.targets" Targets="Build" /> <!-- regular builds -->
<MSBuild Projects="common.targets" <!-- custom invocation with properties -->
Targets="After"
Properties="myprop=myvalue"
/>
</Target>
</Project>
Run:
> msbuild other.targets /clp:verbosity=minimal
Build in other.targets
Build in common.targets
Build in common.targets <<<< Common.targets Build is invoked again
After in common.targets
And indeed, removing Properties="myprop=myvalue" solves the issue.
I found someone had added two project references (from the same project) and that apparently caused msbuild to build twice also.. something to watch out for

What's this MSDeploy NullReferenceException?

When I run MSDeploy from a build script, I get this NullReferenceException. The funny thing is, the project deploys. This has been driving me crazy. Note: This is a web site project, not a web application project.
I'm using this in my build targets file:
<ItemGroup>
<DeploySource Include="DirPath">
<Path>C:\TFS\MySiteBranch\PrecompiledWeb\Source</Path>
<ComputerName>myComputer</ComputerName>
<UserName>anAdminAccount</UserName>
<Password>itsPassword</Password>
</DeploySource>
</ItemGroup>
<ItemGroup>
<TestDeployDest Include="DirPath">
<Path>C:\TFS_Build\POC\Test</Path>
<ComputerName>myComputer</ComputerName>
<UserName>anAdminAccount</UserName>
<Password>itsPassword</Password>
</TestDeployDest>
</ItemGroup>
<Target name="Deploy">
<PropertyGroup>
<WhatIf Condition="'$(WhatIf)'==''">false</WhatIf>
<MSDeployPath Condition="'$(MSDeployPath)'==''">C:\Program Files\IIS\Microsoft Web Deploy V2</MSDeployPath>
</PropertyGroup>
<MSDeploy Condition="'#(TestDeployDest)'!=''"
Whatif="$(WhatIf)"
Verb="sync"
Source="#(DeploySource)"
Destination="#(TestDeployDest)"
ExePath="$(MSDeployPath)"
/>
</target>
Here's the error:
"C:\TFS\MySiteBranch\Source\source.csproj" (Deploy target) (1) ->
(Deploy target) ->
C:\TFS\MySiteBranch\Source\Deploy.Targets(54,3): error MSB4018: The "MSDeploy" task failed unexpectedly.\r [C:\TFS\MySiteBranch\Source\source.csproj]
C:\TFS\MySiteBranch\Source\Deploy.Targets(54,3): error MSB4018: System.NullReferenceException: Object reference not set to an instance of an object.\r [C:\TFS\MySiteBranch\Source\source.csproj]
C:\TFS\MySiteBranch\Source\Deploy.Targets(54,3): error MSB4018: at Microsoft.Web.Publishing.Tasks.Common.Utility.MsDeployEndOfExecuteMessage(Boolean bSuccess, String destType, String destRoot, TaskLoggingHelper Log)\r [C:\TFS\MySiteBranch\Source\source.csproj]
C:\TFS\MySiteBranch\Source\Deploy.Targets(54,3): error MSB4018: at Microsoft.Web.Publishing.Tasks.MSDeploy.Execute()\r [C:\TFS\MySiteBranch\Source\source.csproj]
C:\TFS\MySiteBranch\Source\Deploy.Targets(54,3): error MSB4018: at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()\r [C:\TFS\MySiteBranch\Source\source.csproj]
C:\TFS\MySiteBranch\Source\Deploy.Targets(54,3): error MSB4018: at Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(ITaskExecutionHost taskExecutio
Any ideas for something I can try?
Try using ContinueOnError="true" on the MSDeploy Elements as the following code:
<ItemGroup>
<DeploySource Include="DirPath">
<Path>C:\TFS\MySiteBranch\PrecompiledWeb\Source</Path>
<ComputerName>myComputer</ComputerName>
<UserName>anAdminAccount</UserName>
<Password>itsPassword</Password>
</DeploySource>
</ItemGroup>
<ItemGroup>
<TestDeployDest Include="DirPath">
<Path>C:\TFS_Build\POC\Test</Path>
<ComputerName>myComputer</ComputerName>
<UserName>anAdminAccount</UserName>
<Password>itsPassword</Password>
</TestDeployDest>
</ItemGroup>
<Target name="Deploy">
<PropertyGroup>
<WhatIf Condition="'$(WhatIf)'==''">false</WhatIf>
<MSDeployPath Condition="'$(MSDeployPath)'==''">C:\Program Files\IIS\Microsoft Web Deploy V2</MSDeployPath>
</PropertyGroup>
<MSDeploy ContinueOnError="true" Condition="'#(TestDeployDest)'!=''"
Whatif="$(WhatIf)"
Verb="sync"
Source="#(DeploySource)"
Destination="#(TestDeployDest)"
ExePath="$(MSDeployPath)"
/>
</target>
I had the same issue; and was just able to address it using the fix described here:
http://forums.iis.net/p/1187159/2016131.aspx#2016131
For me, using the VSMSDeploy task is not an option, as we run x64 servers and web apps. Visual Studio only runs x86 versions of msbuild and msdeploy, and so VSMSDeploy only works for x86 servers and sites. I'm using the appHostConfig provider to store IIS config, and appHostConfig can't sync an x64 site to an x86 instance of msdeploy.
I just ran into the same thing. I wasn't able to figure out what the problem was, but I was able to work around it by using VSMSDeploy instead of MSDeploy. Both tasks are in the same DLL and there are examples of using it in Microsoft.Web.Publishing.targets.
I was able to get the deploy working with a Web Deploy Project.

MSBuild transform not evaluating wildcards

I am having some trouble with a MSBuild file that I am trying to compile some custom libraries.
<PropertyGroup>
<FullVersion>10.8.0.0</FullVersion>
</PropertyGroup>
<ItemGroup>
<LibsToBuild Include=".\Lib1">
<Bin>bin\*.*</Bin>
<Project>Library 1</Project>
<Build>ReleaseNoProtect</Build>
<Version>CurrentVersion</Version>
</LibsToBuild>
<LibsToBuild Include=".\Lib2">
<Bin>bin\*.*</Bin>
<Project>Library 2</Project>
<Build>ReleaseLibrary</Build>
<Version>CurrentVersion</Version>
</LibsToBuild>
</ItemGroup>
<ItemGroup>
<LibsToCopy Include="#(LibsToBuild->'%(FullPath)\%(Version)\%(Bin)')" />
</ItemGroup>
<Target Name="BuildLibs">
<MSBuild
Projects="#(LibsToBuild->'%(FullPath)\%(Version)\Build\Build.proj')"
Targets="%(LibsToBuild.Build)"
Properties="Configuration=Release;APP_VERSION=$(FullVersion);PROJECT_NAME=%(LibsToBuild.Project)"
/>
<Copy
SourceFiles="#(LibsToCopy)"
DestinationFiles="#(LibsToCopy->'.\Libraries\CurrentVersion\%(RecursiveDir)%(Filename)%(Extension)')"
/>
<!--
<Exec Command='xcopy /y #(LibsToCopy) .\Libraries\CurrentVersion' />
-->
</Target>
When I run this through MSBuild, all of the compiles work, but the copy files does not. MSBuild complains with the following errors:
Copying file from "X:\Projects\Lib1\Master\bin\*.*" to ".\Libraries\CurrentVersion\*.*".
X:\Projects\Test Release.build(35,3): error MSB3021: Unable to copy file "X:\Projects\Lib1\Master\bin\*.*" to ".\Libraries\CurrentVersion\*.*". Illegal characters in path.
Copying file from "X:\Projects\Lib2\Master\bin\*.*" to ".\Libraries\CurrentVersion\*.*".
X:\Projects\Test Release.build(35,3): error MSB3021: Unable to copy file "X:\Projects\Lib1\Master\bin\*.*" to ".\Libraries\CurrentVersion\*.*". Illegal characters in path.
I am unable to figure out why the transform in the "LibsToCopy" ItemGroup isn't expanding the filename wildcards.
I have also attempted to use xcopy, but it doesn't like the wildcards either.
Thanks!
Dave
I had a similar problem. Try this, just before the <Copy> task
<CreateItem Include="#(LibsToBuild->'%(FullPath)\%(Version)\%(Bin)')">
<Output TaskParameter="Include" ItemName="LibsToCopy" />
</CreateItem>
Unfortunately the documentation says CreateItem task is deprecated, so I don't know how to solve tis problem in the future.