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!