I'm trying to achieve the following with MSBuild: my main project (MyProject.csproj
) should include a couple Reference
items, but the path to one of those Reference
s is the value of the SomeProperty
property, which is set by a Target. Specifically, the value for SomeProperty
is parsed from a file using ReadLinesFromFileTask
.
Here is the high-level structure of MyProject.csproj
:
<Project>
<Target Name="CreateSomeProperty">
<!-- Tasks that ultimately set $(SomeProperty) by parsing a value with ReadLinesFromFileTask -->
</Target>
<ItemGroup>
<Reference Include="$(SomeProperty)" />
<!-- Other Reference items -->
</ItemGroup>
</Project>
Unfortunately, this setup is not working. I see those little yellow triangles under the Dependencies
node of MyProject
in the VS Solution Explorer, since the project is looking for a DLL at a path with missing characters. Similarly, when I build the project, I get a bunch of The type or namespace name could not be found
errors, even though I still see the output from a Message
Task inside my Target. Presumably, the CreatePathProperty
Target is running during the execution phase, after the Reference
items have already failed to load during the evaluation phase.
Is there a way to make a setup like this work? I've tried setting BeforeTargets="Build"
in the Target
element, and setting InitialTargets="CreateSomeProperty"
in the Project
element, but nothing seems to work. Any help would be much appreciated!
Can an MSBuild Item use a Property set by a Target?
Yes, I'm sure it's possible if you're in .net framework project with old csproj format
and what you want is a supported scenario in VS2017(Only did the test in VS2017).
Tips:
Normally msbuild
reads the Properties
and Items
before it executes your custom target. So we should use something like BeforeTargets="BeforeResolveReferences"
to make sure the correct order in this scenario is custom target runs=>create the property=>msbuild reads the info about references and the property
.
Otherwise the order(wrong order when BeforeTargets="Build"
or what) should be: Msbuild reads the info about references(now the property is not defined yet)=>the target runs and creates the property
.
Solution: Add this script to the bottom of your xx.csproj.
<!-- Make sure it executes before msbuild reads the ItemGroup above and loads the references -->
<Target Name="MyTest" BeforeTargets="BeforeResolveReferences">
<ItemGroup>
<!-- Define a TestFile to represent the file I read -->
<TestFile Include="D:\test.txt" />
</ItemGroup>
<!-- Pass the file to read to the ReadLinesFromFile task -->
<ReadLinesFromFile File="@(TestFile)">
<!--Create the Property that represents the normal hintpath(SomePath\DLLName.dll)-->
<Output TaskParameter="Lines" PropertyName="HintPathFromFile" />
</ReadLinesFromFile>
<!-- Output the HintPath in output log to check if the path is right -->
<Message Text="$(HintPathFromFile)" Importance="high" />
<ItemGroup>
<Reference Include="TestReference">
<!--It actually equals:<HintPath>D:\AssemblyFolder\TestReference.dll</HintPath>-->
<HintPath>$(HintPathFromFile)</HintPath>
</Reference>
</ItemGroup>
</Target>
In addition:
I did the test with test.txt
file whose content is:
I'm not sure about the actual content(and format) of your file, but if you only have path like D:\AssemblyFolder\
in that file, you should pass the D:\AssemblyFolder\+YourAssemblyName.dll
to <HintPath>
metadata. Cause the default reference
format with hintpath
looks like this:
<Reference Include="ClassLibrary1">
<HintPath>path\ClassLibrary1.dll</HintPath>
</Reference>
Pay attention to the path format! Hope my answer helps :)
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