I'm a new to MSBuild and wanted to play around with it a bit, but I just cannot figure out why this isn't working.
So my solution has two projects: "Model" and "BuildTasks". BuildTasks just has a single class:
using Microsoft.Build.Utilities; namespace BuildTasks { public class Test : Task { public override bool Execute() { Log.LogMessage( "FASDfasdf" ); return true; } } }
And then in the Model.csproj I've added this:
<UsingTask TaskName="BuildTasks.Test" AssemblyFile="$(SolutionDir)src\BuildTasks\bin\BuildTasks.dll" /> <Target Name="AfterBuild"> <Test /> </Target>
I've set up the build order so "BuildTasks" gets built before "Model". But when I try to build Model I get this error:
The "BuildTasks.Test" task could not be loaded from the assembly C:\WIP\TestSolution\src\BuildTasks\bin\BuildTasks.dll. Could not load file or assembly 'file:///C:\WIP\TestSolution\src\BuildTasks\bin\BuildTasks.dll' or one of its dependencies. The system cannot find the file specified. Confirm that the <UsingTask> declaration is correct, and that the assembly and all its dependencies are available.
This file definitely exists, so why can't MSBuild find it?
I've even tried hard-coding "C:\WIP\TestSolution" in place of "$(SolutionDir)" and get the same error. However, if I copy that .dll to my desktop and hard-code the path to my desktop, it DOES work, which I can't figure out why.
EDIT: I don't have the path wrong. I modified the Debug/Release builds for BuildTasks to output the .dll to just the bin folder since I didn't want Debug/Release to have different paths.
To install MSBuild on a system that doesn't have Visual Studio, go to Build Tools for Visual Studio 2022 on the downloads page. Another way of getting MSBuild is to install the . NET SDK.
Visual Studio determines the build order and calls into MSBuild separately (as needed), all completely under Visual Studio's control. Another difference arises when MSBuild is invoked with a solution file, MSBuild parses the solution file, creates a standard XML input file, evaluates it, and executes it as a project.
MSBuild lets you set properties on the command line by using the -property (or -p) switch. These global property values override property values that are set in the project file. This includes environment properties, but does not include reserved properties, which cannot be changed.
To run MSBuild at a command prompt, pass a project file to MSBuild.exe, together with the appropriate command-line options. Command-line options let you set properties, execute specific targets, and set other options that control the build process.
We tried this and we found that you have to place the UsingTask at the top of the project file (and have all your paths right). However once thats in place and the task loads up it will only work once. After that the build starts failing because it cant copy the DLL that the task is in. We are actually running a post build task thats inside the same assembly/project that we are building.
What we did to solve this is to launch a separate MSBuild process on a seperate MSBuild file to run the Post Build tasks. That way the DLL is not loaded until after its built and copied to the bin directory.
<Target Name="AfterBuild"> <Exec Command="$(MSBuildBinPath)\MSBuild.exe "$(MSBuildProjectDirectory)\PostBuild.msbuild" /property:SomeProperty=$(SomeProperty)" /> </Target>
Note that you can pass properties into this sub-build task on the command line.
And the PostBuild.msbuild looks like this:
<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="PostBuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> <UsingTask TaskName="PostBuild" AssemblyFile="$(MSBuildProjectDirectory)\bin\AssemblyThatJustBuiltAndContainsBuildTask.dll" /> <PropertyGroup> <SomeProperty>SomePropertyDefaultValue</SomeProperty> </PropertyGroup> <Target Name="PostBuild"> <MyPostBuildTask SomeProperty="$(SomeProperty)" /> </Target> </Project>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With