Last active
December 23, 2022 04:52
-
-
Save Wind010/e836e72d326116bb551580a384debaff to your computer and use it in GitHub Desktop.
Update the TargetFramework/TargetFrameworks tag in .csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### | |
# Usage: | |
# Test/DryRun and just report what would have changed. | |
# UpdateTargetFrameworks.ps1 -TargetFrameworks @('net6.0') -UpdateWithXmlDoc $true -Path "SomePath" -DryRun $true | |
# Do the update with XPATH via XmlDocument: | |
# UpdateTargetFrameworks.ps1 @('net6.0') $true | |
# Do the update with replace: | |
# UpdateTargetFrameworks.ps1 @('net6.0') $false | |
### | |
param( | |
[Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$false)] | |
[array] | |
$TargetFrameworks, | |
[Parameter(Mandatory=$false, Position=1, ValueFromPipeline=$false)] | |
[bool] | |
$UpdateWithXmlDoc = $true, | |
[Parameter(Mandatory=$false, Position=2, ValueFromPipeline=$false)] | |
[string] | |
$Path = ".", | |
[Parameter(Mandatory=$false, Position=3, ValueFromPipeline=$false)] | |
[bool] | |
$DryRun = $false | |
) | |
$ErrorActionPreference = 'Stop' | |
$supportedTargetFrameworks = @('net7.0', 'net6.0', 'net5.0', 'netstandard2.1', 'netcoreapp3.1') | |
$supportedTargetFrameworks = [System.Collections.Generic.HashSet[string]]$supportedTargetFrameworks | |
function Initialize() | |
{ | |
if ( -not ([System.Collections.Generic.HashSet[string]]$TargetFrameworks).IsSubSetOf($supportedTargetFrameworks)) | |
{ | |
Write-Error "$TargetFrameworks contains unsupported framework. Only $supportedTargetFrameworks are supported." | |
} | |
[string] $targetFrameworksValue = "" | |
if ($TargetFrameworks.Length -eq 0) | |
{ | |
Write-Error "At least one TargetFramework must be defined." | |
} | |
if ($TargetFrameworks.Length -eq 1) | |
{ | |
$targetFrameworksValue = $TargetFrameworks[0] | |
} | |
else | |
{ | |
$targetFrameworksValue = $TargetFrameworks.Join(';') | |
} | |
return $targetFrameworksValue | |
} | |
function UpdateWithXmlDocument() | |
{ | |
[Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$false)] | |
[string] $projectPaths, | |
[Parameter(Mandatory=$true, Position=1, ValueFromPipeline=$false)] | |
[string] $targetFrameworksValue | |
foreach($_ in $projectPaths) | |
{ | |
[string] $path = $_.FullName | |
$xml = New-Object System.Xml.XmlDocument | |
$xml.Load($path) | |
$ErrorActionPreference = 'SilentlyContinue' | |
$targetFrameworkNode = $xml.SelectSingleNode("//Project/PropertyGroup/TargetFramework") | |
#$targetFrameworkNode = $propertyGroup.SelectSingleNode("TargetFramework") | |
$ErrorActionPreference = 'Stop' | |
# TargetFramework | |
if ($targetFrameworkNode) | |
{ | |
if ($TargetFrameworks.Length -gt 1) | |
{ | |
$newNode = $xml.CreateElement("TargetFrameworks") | |
$newNode.InnerText = $targetFrameworksValue | |
Write-Host "Setting from '$($newNode.OuterXml)' to '$($newNode.OuterXml)' for '$path'..." | |
$targetFrameworkNode = $newNode | |
} | |
elseif( -not ($targetFrameworkNode.InnerText -like $targetFrameworksValue)) | |
{ | |
Write-Output "Updating from '$($targetFrameworkNode.OuterXml)' to '$targetFrameworksValue' for '$path'..." | |
$targetFrameworkNode.InnerText = $targetFrameworksValue | |
} | |
else | |
{ | |
Write-Host "Skipping '$path' since TargetFramework matches source='$($targetFrameworkNode.InnerText)' and target='$targetFrameworksValue'" | |
} | |
continue | |
} | |
else | |
{ | |
$ErrorActionPreference = 'SilentlyContinue' | |
$targetFrameworksNode = $xml.SelectSingleNode("//Project/PropertyGroup/TargetFrameworks") | |
$ErrorActionPreference = 'Stop' | |
} | |
# TargetFrameworks | |
if ($targetFrameworksNode) | |
{ | |
if ($TargetFrameworks.Length -eq 1) | |
{ | |
$newNode = $xml.CreateElement("TargetFramework") | |
$newNode.InnerText = $targetFrameworksValue | |
Write-Host "Setting from '$($targetFrameworksNode.OuterXml)' to '$($newNode.OuterXml)' for '$path'..." | |
$targetFrameworksNode = $newNode | |
} | |
elseif( -not [System.Collections.Generic.HashSet[string]]$targetFrameworksValueNode.InnerText -eq [System.Collections.Generic.HashSet[string]] $TargetFrameworks) | |
{ | |
Write-Output "Updating from '$($targetFrameworksValueNode.OuterXml) to '$targetFrameworksValue' for $path" | |
$targetFrameworksNode.InnerText = $targetFrameworksValue | |
} | |
else | |
{ | |
Write-Host "Skipping '$path' since TargetFrameworks matches source='$($targetFrameworksNode.InnerText)' and target='$targetFrameworksValue'" | |
} | |
continue | |
} | |
else | |
{ | |
Write-Error "Expected TargetFramework or TargetFrameworks under //Project/PropertyGroup in '$path'" | |
} | |
if ($dryRun) | |
{ | |
Write-Host "Dry Run was set. Nothing changed." | |
continue | |
} | |
$xml.Save($pathobject) | |
} | |
} | |
[string] $targetFrameworksValue = Initialize | |
$projectPaths = Get-ChildItem -include *.csproj -Recurse -Path $Path | |
if ($UpdateWithXmlDoc) | |
{ | |
UpdateWithXmlDocument $projectPaths $targetFrameworksValue | |
} | |
else | |
{ | |
$pattern = '<TargetFramework(s)?>.*' # Use single quotes to avoid string interpolation. Python equivalent of r""/r''. | |
$targetFrameworkTag = "<TargetFramework>$targetFrameworksValue</TargetFramework>" | |
if ($TargetFrameworks.Length -gt 1) | |
{ | |
$targetFrameworkTag = $targetFrameworkTag.Replace("TargetFramework", "TargetFrameworks") | |
} | |
$projectPaths | % { | |
Write-Host "Processing '$_' and replacing TargetFramework with $targetFrameworkTag..." | |
(Get-Content $_.FullName) -Replace $pattern, $targetFrameworkTag | Set-Content -Encoding UTF8 -Path $_.FullName | |
Write-Output (Get-Content $_.FullName) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment