Using PowerShell to automate setting CopyLocal to false

 

It’s been stressed that CopyLocal is slow and evil, so I wanted to see what the impact was on our codebase.

First we need to load the project file and pull out the references sections.

[xml]$s = get-content $projectFile

$references = $s.Project.ItemGroup | Where-Object { $_.Reference -ne $null }
$projectReferences = $s.Project.ItemGroup | Where-Object { $_.ProjectReference -ne $null }

Next we can iterate through the child nodes, and if they are missing the Private tag, add it in.

foreach($reference in $references.ChildNodes)
{ 
    if($reference.Private -eq $null)
    {
        [System.Xml.XmlElement]$copyLocal = $s.CreateElement("Private", "http://schemas.microsoft.com/developer/msbuild/2003")
        $copyLocal.InnerText = "False"
        [Void]$reference.AppendChild($copyLocal) 
    }
}

We can do a similar thing with the project references if your solution builds into a single folder.

foreach($reference in $projectReferences.ChildNodes)
{ 
    if($reference.Private -eq $null)
    {
        [System.Xml.XmlElement]$copyLocal = $s.CreateElement("Private", "http://schemas.microsoft.com/developer/msbuild/2003")
        $copyLocal.InnerText = "False"
        [Void]$reference.AppendChild($copyLocal) 
    }
}

Then all we need to do is save the file and we are done!

$s.save($projectFile)

If you want to apply this too all the project files in a directory, recursively then you could do:

Get-ChildItem $directory -include *.csproj,*.vbproj -Recurse | foreach ($_) { 
    Set-CopyLocalFalse $_.fullname $true
}

You can find the source for this in the SlightlyPosher distribution, or look at the source for the file.

Preliminary tests on our build time dropped from 6:30 minutes to 3:48 minutes thanks to this!

June 22 2011
Comments are closed