using msbuild within PowerShell to edit a csproj on the install event in NuGet
I saw a great example for what I'm trying to do on Daniel Cazzulino's Blog at Clarius. I’d like to do something similar to what he did.
I am trying to deliver some basic T4 templates via NuGet and have a problem because each of them have an entry in the csproj file that says <Generator>TextTemplatingFileGenerator</Generator>
which makes them all run independently which is not desireable. If the value read like this <Generator></Generator>
, then everything would be ok.
I would like to remove this setting using the msbuild like you modified the csproj in the ex开发者_高级运维ample above. I have written a PowerShell script to remove the offending value, but it requires unloading the project. Msbuild seems better suited for this task, but I’m unfamiliar with it. I’ve done some searching, but am still in the dark.
The difference between what he did and what I want to do is that he added something and I want to edit something, but I don't know how to locate the info using the msbuild xml traversing methods.
Here’s the PowerShell script that I wrote with @Keith Hill's help:
$ns = @{msb = 'http://schemas.microsoft.com/developer/msbuild/2003'}
$results = 0
$xml = [xml](gc $projName)
$xml | Select-Xml "//msb:Generator" -Namespace $ns |
Foreach {
$_.Node.set_InnerText('')
$results = 1
}
if($results -eq 1){
$xml.Save($project.FullName)
}
Any suggestions on how to do this in msbuild?
Here's Daniel's code (it exists within the Install.ps1 file that is a part of the NuGet install life-cycle):
param($installPath, $toolsPath, $package, $project)
# This is the MSBuild targets file to add
$targetsFile = [System.IO.Path]::Combine($toolsPath, 'Funq.Build.targets')
# Need to load MSBuild assembly if it's not loaded yet.
Add-Type -AssemblyName 'Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
# Grab the loaded MSBuild project for the project
$msbuild = [Microsoft.Build.Evaluation.ProjectCollection]::GlobalProjectCollection.GetLoadedProjects($project.FullName) | Select-Object -First 1
# Make the path to the targets file relative.
$projectUri = new-object Uri('file://' + $project.FullName)
$targetUri = new-object Uri('file://' + $targetsFile)
$relativePath = $projectUri.MakeRelativeUri($targetUri).ToString().Replace([System.IO.Path]::AltDirectorySeparatorChar, [System.IO.Path]::DirectorySeparatorChar)
# Add the import and save the project
$msbuild.Xml.AddImport($relativePath) | out-null
$project.Save()
You could do this using the XmlPoke Task:
<Project DefaultTargets="PokeGenerator">
<ItemGroup>
<MyProjectFile Include="$(MSBuildProjectDirectory)\MyProject.csproj" />
</ItemGroup>
<Target Name="PokeGenerator">
<XmlPoke XmlInputPath="%(ProjectConfigFile.FullPath)"
Query="/x:Project/x:ItemGroup/x:Compile/x:Generator"
Namespaces="<Namespace Prefix='x' Uri='http://schemas.microsoft.com/developer/msbuild/2003' />"
Value="%0a" />
</Target>
</Project>
You just need to modify the XmlInputPath
and Query
parameters to fit to your needs.
The gotchas are that you have to declare a namespace prefix even if the project file doesn't use any namespace prefix and that you need to provide a value to poke into the selected element - I figured a newline won't hurt.
精彩评论