How do I use Powershell to add/remove references to a csproj?

后端 未结 2 656
清歌不尽
清歌不尽 2020-12-06 01:53

In relation to this previous question I am trying to create a batch file which as part must remove and add a reference to an XML *.csproj file. I have looked

相关标签:
2条回答
  • 2020-12-06 02:02

    For posterities sake I will give the complete powershell scripts to add and remove references to csproj files. Please vote up Andy Arismedi's answer if you find this useful as he helped me find it. Feel free to give me a +1 also while you're at it ;-)

    AddReference.ps1

    # Calling convension:
    #   AddReference.PS1 "Mycsproj.csproj", 
    #                    "MyNewDllToReference.dll", 
    #                    "MyNewDllToReference"
    param([String]$path, [String]$dllRef, [String]$refName)
    
    $proj = [xml](Get-Content $path)
    [System.Console]::WriteLine("")
    [System.Console]::WriteLine("AddReference {0} on {1}", $refName, $path)
    
    # Create the following hierarchy
    #  <Reference Include='{0}'>
    #     <HintPath>{1}</HintPath>
    #  </Reference>
    # where (0) is $refName and {1} is $dllRef
    
    $xmlns = "http://schemas.microsoft.com/developer/msbuild/2003"
    $itemGroup = $proj.CreateElement("ItemGroup", $xmlns);
    $proj.Project.AppendChild($itemGroup);
    
    $referenceNode = $proj.CreateElement("Reference", $xmlns);
    $referenceNode.SetAttribute("Include", $refName);
    $itemGroup.AppendChild($referenceNode)
    
    $hintPath = $proj.CreateElement("HintPath", $xmlns);
    $hintPath.InnerXml = $dllRef
    $referenceNode.AppendChild($hintPath)
    
    $proj.Save($path)
    

    RemoveReference.ps1

    # Calling Convention
    #   RemoveReference.ps1 "MyCsProj.csproj" 
    #   "..\SomeDirectory\SomeProjectReferenceToRemove.dll"
    param($path, $Reference)
    
    $XPath = [string]::Format("//a:ProjectReference[@Include='{0}']", $Reference)   
    
    [System.Console]::WriteLine("");
    [System.Console]::WriteLine("XPATH IS {0}", $XPath) 
    [System.Console]::WriteLine("");
    
    $proj = [xml](Get-Content $path)
    [System.Console]::WriteLine("Loaded project {0} into {1}", $path, $proj)
    
    [System.Xml.XmlNamespaceManager] $nsmgr = $proj.NameTable
    $nsmgr.AddNamespace('a','http://schemas.microsoft.com/developer/msbuild/2003')
    $node = $proj.SelectSingleNode($XPath, $nsmgr)
    
    if (!$node)
    { 
        [System.Console]::WriteLine("");
        [System.Console]::WriteLine("Cannot find node with XPath {0}", $XPath) 
        [System.Console]::WriteLine("");
        exit
    }
    
    [System.Console]::WriteLine("Removing node {0}", $node)
    $node.ParentNode.RemoveChild($node);
    
    $proj.Save($path)
    
    0 讨论(0)
  • 2020-12-06 02:21

    I think the problem is that your XML file has a default namespace xmlns="http://schemas.microsoft.com/developer/msbuild/2003". This causes problems with XPath. So you XPath //ProjectReference will return 0 nodes. There are two ways to solve this:

    1. Use a namespace manager.
    2. Use namespace agnostic XPath.

    Here's is how you could use a namespace manager:

    $nsmgr = New-Object System.Xml.XmlNamespaceManager -ArgumentList $proj.NameTable
    $nsmgr.AddNamespace('a','http://schemas.microsoft.com/developer/msbuild/2003')
    $nodes = $proj.SelectNodes('//a:ProjectReference', $nsmgr)
    

    Or:

    Select-Xml '//a:ProjectReference' -Namespace $nsmgr
    

    Here's how to do it using namespace agnostic XPath:

    $nodes = $proj.SelectNodes('//*[local-name()="ProjectReference"]')
    

    Or:

    $nodes = Select-Xml '//*[local-name()="ProjectReference"]'
    

    The second approach can be dangerous because if there were more than one namespace it could select the wrong nodes but not it your case.

    0 讨论(0)
提交回复
热议问题