title: using msbuild within PowerShell to edit a csproj on the install event in NuGet
body: <p>I saw a great example for what I'm trying to do on <a href="http://blogs.clariusconsulting.net/kzu/how-to-add-an-msbuild-import-to-a-project-on-nuget-install/" rel="nofollow">Daniel Cazzulino's Blog</a> at Clarius. I’d like to do something similar to what he did.</p>
  
  <p>I am trying to deliver some basic <strong>T4 templates</strong> via <strong>NuGet</strong> and have a problem because each of them have an entry in the <strong>csproj</strong> file that says <code>&lt;Generator&gt;TextTemplatingFileGenerator&lt;/Generator&gt;</code> which makes them all run independently which is not desireable. If the value read like this <code>&lt;Generator&gt;&lt;/Generator&gt;</code>, then everything would be ok. </p>
  
  <p>I would like to remove this setting using the <strong>msbuild</strong> like you modified the <strong>csproj</strong> in the example above. 
  I have written a <strong>PowerShell</strong> script to remove the offending value, but it requires unloading the project. <strong>Msbuild</strong> seems better suited for this task, but I’m unfamiliar with it. I’ve done some searching, but am still in the dark.</p>
  
  <p>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 <strong>msbuild</strong> xml traversing methods.</p>
  
  <p>Here’s the <strong>PowerShell</strong> script that I wrote with @Keith Hill's help:</p>
  
  <pre><code>$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)
  }
  </code></pre>
  
  <p>Any suggestions on how to do this in msbuild?</p>
  
  <p>Here's Daniel's code (it exists within the Install.ps1 file that is a part of the NuGet install life-cycle):</p>
  
  <pre><code>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()
  </code></pre>