Detokenising multiple files using msbuild - property not found error - msbuild

I have the following piece of code to replace all tokens in a given set of files:
(I'm using the msbuild extensions detokenise task).
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="MSBuild.ExtensionPack.FileSystem.Detokenise" AssemblyFile="Extensions/MSBuild.ExtensionPack.dll"/>
<PropertyGroup>
<someValueToReplace>New Value</someValueToReplace>
</PropertyGroup>
<ItemGroup>
<TextFiles Include="test1.txt"/>
<TextFiles Include="test2.txt"/>
</ItemGroup>
<Target Name="Build">
<Detokenise TaskAction="Detokenise" TextEncoding="ASCII" TargetFiles="#(TextFiles)"/>
</Target>
</Project>
Unfortunately I get the following error:
(I don't get this error if only one item exist in the ItemGroup).
(Note that I don't want to explicitly inject the tokens that I want replaced).
"C:\Users\v\Desktop\msbuildSample\detokenise.xml" (default target) (1) ->
(Build target) ->
C:\Users\v\Desktop\msbuildSample\detokenise.xml(10,3): error : Property not found: toReplace
C:\Users\v\Desktop\msbuildSample\detokenise.xml(10,3): error : ArgumentException: Review error log\r
C:\Users\v\Desktop\msbuildSample\detokenise.xml(10,3): error :

My mistake .. I thought it was a bug in msbuild .. actually the issue was exactly what the error message indicated -- I was trying to replace a variable called toReplace -- but it wasn't defined.

Related

MSBuild not finding the DLL

I emit a console app with Mono.Cecil and I want to integrate MSBuild into the build process. But then when I run dotnet build on my custom project file, MSBuild throws an error saying Expected file "obj\Debug\net5.0\refint\test.dll" does not exist. It's trying to find the generated assembly inside the refint folder. When the assembly gets generated inside obj\Debug\net5.0\test.dll as it should. Is there a way I can change the path where MSBuild looks for the output assembly? Everything on the side of the IL generator works, I even get a runnable exe inside the build folder. Here's my project file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<OutputType>Exe</OutputType>
<DefaultLanguageSourceExtension>.ao</DefaultLanguageSourceExtension>
<OutputPath>C:\Users\filip\source\alto\samples\test\obj\Debug\net5.0\</OutputPath>
</PropertyGroup>
<Target Name="CreateManifestResourceNames" />
<Target Name="CoreCompile" DependsOnTargets="$(CoreCompileDependsOn)">
<Exec Command="dotnet run --project "$(MSBuildThisFileDirectory)\..\..\src\aoc\aoc.csproj" -- #(Compile->'$(MSBuildThisFileDirectory)', ' ') /o "#(IntermediateAssembly)" #(ReferencePath->' /r "%(Identity)"', ' ')"
WorkingDirectory="$(MSBuildProjectDirectory)" />
</Target>
</Project>
Thank you in advance.
I didn't read the whole error message.
C:\Program Files\dotnet\sdk\6.0.100-preview.7.21379.14\Microsoft.Common.CurrentVersion.targets(4527,5): error : Expected file "obj\Debug\net5.0\refint\test.dll" does not exist.
It actually points me to a file where the error was thrown. This is where:
<!-- Copy the reference assembly build product (.dll or .exe). -->
<CopyRefAssembly
SourcePath="#(IntermediateRefAssembly)"
DestinationPath="$(TargetRefPath)"
Condition="'$(ProduceReferenceAssembly)' == 'true' and '$(CopyBuildOutputToOutputDirectory)' == 'true' and '$(SkipCopyBuildProduct)' != 'true'"
>
<Output TaskParameter="DestinationPath" ItemName="ReferenceAssembly"/>
<Output TaskParameter="DestinationPath" ItemName="FileWrites"/>
</CopyRefAssembly>
It's trying to make a reference assembly when I don't need one. So I just set the ProduceReferenceAssembly property to false, since I don't need one.

How to get around this "Internal PatchWiz Error occurred Cannot create folder" error when building WiX PCP patching targets in parallel?

I am trying to build a pair of WiX patch projects (the Patch Creation ones..) in parallel however my 64-bit configuration one always fails with PatchWiz errors:
INFO: Passed all of the main control parameter validation to PatchWiz, now calling the next 5 phases.
INFO: Phase I: Entered validation and processing phase.
ERROR: Internal PatchWiz Error occurred.
ERROR: The Last Error Received is: 0x20 (32)
INFO: Temporary folder is about to be cleaned out and deleted: C:\Users\TestUser\AppData\Local\Temp\~pcw_tmp.tmp
ERROR: Internal PatchWiz Error occurred.
ERROR: The Last Error Received is: 0x91 (145)
ERROR: During cleanup, could not delete the temporary folder: C:\Users\TestUser\AppData\Local\Temp\~pcw_tmp.tmp.
ERROR: The Last Error Received is: 0x91 (145)
I tried:
cleaning temp folder before running.
switching the configuration order.
adding a sleep/timeout between executions
with no luck.
Here is my build.proj I am executing:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="packages\MSBuild.Extension.Pack.1.8.0\build\net40\MSBuild.Extension.Pack.targets" Condition="Exists('packages\MSBuild.Extension.Pack.1.8.0\build\net40\MSBuild.Extension.Pack.targets')" />
<PropertyGroup>
<ProductVersion>1.1.2</ProductVersion>
</PropertyGroup>
<Target Name="Compile32">
<MSBuild Targets="Build" Projects="Hotfix_Patch.wixproj"
Properties="Configuration=Debug;Platform=x86;ProductVersion=$(ProductVersion)" />
</Target>
<Target Name="Compile64">
<MSBuild Targets="Build" Projects="Hotfix_Patch.wixproj"
Properties="Configuration=Debug;Platform=x64;ProductVersion=$(ProductVersion)" />
</Target>
<Target Name="Build" >
<MSBuild.ExtensionPack.Framework.Parallel TaskAction="BuildTargetsInParallel" Targets="Compile64;Compile32"/>
</Target>
</Project>
Am I at the mercy of PatchWiz? Or is there something I might be doing wrong? Any hack ideas? (and don't say I'm doing it wrong by Patching/MSP in the first place! I realize that! Aside from this I'm a Major Upgrade MSI kind of guy).
The second patch creation process is trying to trample over the first's temp files luckily C:\Users\TestUser\AppData\Local\Temp\~pcw_tmp.tmp. is just a default. You can to specify another buildarch specific temp folder:-
If using MSIMSP.exe use /f on your cmd line
see msimsp.exe docs here
If using patchwiz directly, it's a parameter of UICreatePatchPackage see PatchWiz docs here
p.s. Was a good day when I found this out :)

The "CompressorTask" task was not found

Scripts.xml:
<UsingTask
TaskName="CompressorTask"
AssemblyFile="Yahoo.Yui.Compressor.dll" />
<PropertyGroup>
<JavaScriptOutputFile Condition=" '$(JavaScriptOutputFile)'=='' ">..\..\site.com\javascript\offerta.min.js</JavaScriptOutputFile>
</PropertyGroup>
<Target Name="ScriptTask">
<ItemGroup>
<JavaScriptFiles Include="..\..\site.com\javascript\offerta.js"/>
</ItemGroup>
<CompressorTask
JavaScriptFiles="#(JavaScriptFiles)"
ObfuscateJavaScript="True"
PreserveAllSemicolons="True"
DisableOptimizations="False"
EncodingType="utf-8"
DeleteJavaScriptFiles="false"
LineBreakPosition="-1"
JavaScriptOutputFile="$(JavaScriptOutputFile)"
LoggingType="HardcoreBringItOn"
ThreadCulture="en-us"
IsEvalIgnored="false" />
</Target>
I run it using a bat file:
C:\Windows\Microsoft.NET\Framework\v3.5\msbuild.exe Scripts.xml
pause
I'm getting:
"F:\Checkouts\Offerta\trunk\build\site.com\Scripts.xml" (default target) (1)
->
(ScriptTask target) ->
F:\Checkouts\Offerta\trunk\build\site.com\Scripts.xml(16,7): error MSB4036:
The "CompressorTask" task was not found. Check the following: 1.) The name of
the task in the project file is the same as the name of the task class. 2.) The
task class is "public" and implements the Microsoft.Build.Framework.ITask inte
rface. 3.) The task is correctly declared with in the project file,
or in the *.tasks files located in the "C:\Windows\Microsoft.NET\Framework\v2.
0.50727" directory.
What am I doing wrong? I'm using Yahoo.Yui.Compressor v1.6.0.0.zip (for .NET 3.5). Why is msbuild reporting "C:\Windows\Microsoft.NET\Framework\v2.0.50727" when I explicity run C:\Windows\Microsoft.NET\Framework\v3.5\msbuild.exe?
Use Yahoo.Yui.Compressor.MsBuildTask.dll version 1.6.0.1
Unfortunaltelly this version is available only via Nuget Library
Details at: http://yuicompressor.codeplex.com/discussions/272802

Property scope using msbuild extension pack detokenise

Im trying to use the msbuild extensions pack to fix up the configuration of our app on deploy,
i want to be able to pass a property (ENV) which will load my environment specific config file to use with the detokeniser, and fix up my application configs.
Like this:
<UsingTask TaskName="MSBuild.ExtensionPack.FileSystem.Detokenise"
AssemblyFile=".\Tools\MSBuild Extension Pack 4.0.3.0\MSBuild.ExtensionPack.dll"/>
<Import Project=".\Environments\$(Env).properties"/>
<Target Name="Build" >
<ItemGroup>
<SourceTemplates Include=".\Templates\**\*.*"/>
</ItemGroup>
<RemoveDir Directories=".\Temp"/>
<MakeDir Directories=".\Temp"/>
<Message Text="#(SourceTemplates)"/>
<Copy SourceFiles="#(SourceTemplates)"
DestinationFolder=".\Temp\%(RecursiveDir)" />
<ItemGroup>
<TargetTemplates Include=".\Temp\**\*.*"/>
</ItemGroup>
<MSBuild.ExtensionPack.FileSystem.Detokenise
TaskAction="Detokenise"
TargetFiles="#(TargetTemplates)"/>
</Target>
So i call this using
msbuild Detokenise.msbuild /p:Env=Prod
Msbuild knows about my file and i have access to its properties, but when the detokeniser runs i get the error:
Detokenise Task Execution Completed [15:07:50]
C:\Source\1.2\Build\Detokenise.msbuild(27,3):
error : InvalidProjectFileException: The imported project "C:\Source\1.2\Build\Environments\.properties" was not found.
Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.
C:\Source\1.2\Build\Detokenise.msbuild\r
C:\Source\1.2\Build\Detokenise.msbuild(27,3): error :
All works fine if i hard code it-
Any ideas how to solve this. I thought of doing some text replacement on the msbuild before i execute...
You could try to assign this parameter to a local property:
<PropertyGroup Condition="'$(Env)'=='Prod'">
<TargetEnv>Prod</TargetEnv>
</PropertyGroup>
<!-- add other environments as needed -->
<PropertyGroup Condition="'$(Env)'=='Test'">
<TargetEnv>Test</TargetEnv>
</PropertyGroup>
<Import Project=".\Environments\$(TargetEnv).properties"/>
You could also try to enclose your parameter value in quotes:
msbuild Detokenise.msbuild /p:"Env=Prod"
As is your problem can't be reproduced, so it may be a side effect of other parameters not shown in your sample code.
I've seen a number of other questions where a similar problems was happening:
Visual Studio Ignoring MSBuild file (csproj) Customizations

msbuild exec task call msbuild

I need to call exec and build a wix setup project.
Currently I have the following in my TFSbuild.proj
<PropertyGroup>
<WebRoot>$(DropLocation)\Latest\x86\Release\_PublishedWebsites\Web</WebRoot>
<DBRoot>$(DropLocation)\Latest\x86\Release\Database</DBRoot>
</PropertyGroup>
<PropertyGroup>
<Msbuildexe>"msbuild"</Msbuildexe>
<Configuration>"/p:Configuration:"Release""</Configuration>
<DefineConstants>" /p:DefineConstants:"WebRoot=$(WebRoot);DBRoot=$(DBRoot)""</DefineConstants>
<WixSolution>"$(MSBuildProjectDirectory)\Setup\Setup.sln"</WixSolution>
</PropertyGroup>
<Message Text="Bulding setup solution" />
<Message Text="$(Msbuildexe) $(Configuration) $(DefineConstants) $(WixSolution)" />
<Exec Command="$(Msbuildexe) $(Configuration) $(DefineConstants) $(WixSolution)" />
I've tried to simply as much as possible so I don't get confused where the " are meant to be. When I run this the debug message (2nd last command) outputs
"msbuild"
"/p:Configuration:"Release"" "
/p:DefineConstants:"WebRoot=\server\drops\app\Installer Build\Latest\x86\Release_PublishedWebsites\Web;DBRoot=\server\drops\app\Installer Build\Latest\x86\Release\Database""
"f:\builds\app\Installer Build\BuildType\Setup\Setup.sln"
And I get the following error in the log
'"msbuild"' is not recognized as an
internal or external command,
operable program or batch file.
f:\builds\app\Installer
Build\BuildType\TFSBuild.proj(538,5):
error MSB3073: The command ""msbuild"
"/p:Configuration:"Release"" "
/p:DefineConstants:"WebRoot=\server\drops\app\Installer Build\Latest\x86\Release_PublishedWebsites\Web;DBRoot=\server\drops\app\Installer Build\Latest\x86\Release\Database""
"f:\builds\app\Installer
Build\BuildType\Setup\Setup.sln""
exited with code 9009.
I'm not sure if this is being caused by not being able to call the msbuild command from the command line or a " issue. If it is because I can't call msbuild from the command line like this how would I go about referencing it, is there a property that points to it?
To start with, you don't need most of the quotes, especially if the paths you are using don't contain spaces, but I'd trim it down to this, allowing for spaces in the paths for $(WebRoot), $(DbRoot) and $(MSBuildProjectDirectory):
<PropertyGroup>
<WebRoot>$(DropLocation)\Latest\x86\Release\_PublishedWebsites\Web</WebRoot>
<DBRoot>$(DropLocation)\Latest\x86\Release\Database</DBRoot>
</PropertyGroup>
<PropertyGroup>
<MsbuildExe>{still-needs-a-path-to}\msbuild</MsbuildExe>
<Configuration>/p:Configuration:Release</Configuration>
<DefineConstants>/p:DefineConstants:"WebRoot=$(WebRoot);DBRoot=$(DBRoot)"</DefineConstants>
<WixSolution>"$(MSBuildProjectDirectory)\Setup\Setup.sln"</WixSolution>
</PropertyGroup>
<Message
Text="Bulding setup solution"
/>
<Message
Text="$(MsbuildExe) $(Configuration) $(DefineConstants) $(WixSolution)"
/>
<Exec
Command="$(MsbuildExe) $(Configuration) $(DefineConstants) $(WixSolution)"
/>
However, you still won't be able to execute MSBuild with this, since the path to MSBuild isn't specified. It is typically found in the $(WINDIR)\Framework\Microsoft.Net\v4.0.30319 folder. There are a few ways to get this, either encode it directly, rely on an environment variable (that has to be set up somehow), use the predefined $(MSBuildBinPath), or extract it from the registry using the MSBuild registry syntax, which would look like this:
$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\4.0\MSBuildToolsPath)
However, it isn't clear why you are running MSBuild using Exec rather than just using the MSBuild task. Change the line with Exec to this:
<MSBuild
Project="$(WixSolution)"
Properties="$(DefineConstants)"
/>
removing your declaration for <Configuration> and changing <DefineConstants> to this:
<DefineConstants>Configuration=$(Configuration);WebRoot=$(WebRoot);DBRoot=$(DBRoot)</DefineConstants>
Following up on my comment I'd suggest you try using the MSBuild Task instead of Exec:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="BuildWiXSolution">
<!-- Include the custom build targets installed with WiX -->
<Import Project="$(MSBuildExtensionsPath)\Wix\Wix.targets"/>
<PropertyGroup>
<WebRoot>$(DropLocation)\Latest\x86\Release\_PublishedWebsites\Web</WebRoot>
<DBRoot>$(DropLocation)\Latest\x86\Release\Database</DBRoot>
</PropertyGroup>
<ItemGroup>
<WiXSolution Include="$(MSBuildProjectDirectory)\Setup\Setup.sln">
<Properties>Configuration=Release</Properties>
<AdditionalProperties>WebRoot=$(WebRoot);DBRoot=$(DBRoot)</AdditionalProperties>
</WiXSolution>
</ItemGroup>
<Target Name="BuildWiXSolution">
<MSBuild Projects="#(WiXSolution)" />
</Target>
</Project>
It allows you to keep configuration properties and additional properties together with your Wix solution.