Public/DotNetHelpers.ps1
|
function Get-DotNetTool { <# .SYNOPSIS List installed .NET tools. .DESCRIPTION Parses the output of 'dotnet tool list' into typed DotNetTool objects. By default lists globally installed tools. Use -Local for local manifest tools. .PARAMETER Name Filter by package ID. Supports wildcards. .PARAMETER Local List tools from the local tool manifest instead of global. .EXAMPLE Get-DotNetTool Lists all globally installed .NET tools. .EXAMPLE Get-DotNetTool -Name dotnet-ef* Lists global tools matching the filter. .EXAMPLE Get-DotNetTool -Local Lists tools from the local tool manifest. #> [OutputType('DotNetTool')] [CmdletBinding()] param( [Parameter(Position = 0)] [string]$Name = '*', [switch]$Local ) $scope = if ($Local) { '--local' } else { '-g' } Invoke-InLocation -Location ~ -ScriptBlock { dotnet tool list $scope 2>$null | Select-Object -Skip 2 | ForEach-Object { $parts = $_ -split '\s{2,}' if ($parts.Count -ge 3) { $tool = [PSCustomObject]@{ PSTypeName = 'DotNetTool' PackageId = $parts[0].Trim() Version = $parts[1].Trim() Commands = $parts[2].Trim() Global = -not $Local } if ($tool.PackageId -like $Name) { $tool } } } } } function Update-DotNetTool { <# .SYNOPSIS Update one or more .NET tools to the latest version. .DESCRIPTION Wraps 'dotnet tool update' for global or local tools. Accepts pipeline input from Get-DotNetTool. Returns typed result objects. .PARAMETER InputObject A DotNetTool object from Get-DotNetTool. .PARAMETER Name The package ID to update. .PARAMETER Local Update a local tool instead of global. .EXAMPLE Get-DotNetTool | Update-DotNetTool Updates all globally installed .NET tools. .EXAMPLE Update-DotNetTool -Name dotnet-ef Updates a specific tool by name. #> [OutputType('DotNetToolUpdateResult')] [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'ByObject')] param( [Parameter(ParameterSetName = 'ByObject', ValueFromPipeline, Mandatory)] [PSObject]$InputObject, [Parameter(ParameterSetName = 'ByName', Position = 0, Mandatory)] [string]$Name, [Parameter(ParameterSetName = 'ByName')] [switch]$Local ) process { $toolName = if ($PSCmdlet.ParameterSetName -eq 'ByName') { $Name } else { $InputObject.PackageId } $isGlobal = if ($PSCmdlet.ParameterSetName -eq 'ByName') { -not $Local } else { $InputObject.Global } $scope = if ($isGlobal) { '-g' } else { '--local' } if ($PSCmdlet.ShouldProcess($toolName, 'dotnet tool update')) { Write-Verbose "Updating $toolName" $previousVersion = if ($PSCmdlet.ParameterSetName -eq 'ByObject') { $InputObject.Version } else { $null } $output = dotnet tool update $toolName $scope 2>&1 $output | ForEach-Object { Write-Verbose $_ } $outputText = $output -join "`n" # Parse the new version from output $newVersion = if ($outputText -match "version '([^']+)'\.\s*$") { $Matches[1] } elseif ($outputText -match "version '([^']+)' to version '([^']+)'") { $Matches[2] } else { $null } $updated = $outputText -match 'was successfully updated from version' [PSCustomObject]@{ PSTypeName = 'DotNetToolUpdateResult' PackageId = $toolName Version = $newVersion Updated = $updated } } } } function Install-DotNetTool { <# .SYNOPSIS Install a .NET global tool. .DESCRIPTION Wraps 'dotnet tool install -g'. Idempotent — skips if already installed. .PARAMETER Name The package ID to install. .EXAMPLE Install-DotNetTool -Name dotnet-ef Installs dotnet-ef globally. #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Position = 0, Mandatory)] [ValidateNotNullOrEmpty()] [string]$Name ) if ($PSCmdlet.ShouldProcess($Name, 'dotnet tool install -g')) { $existing = Get-DotNetTool -Name $Name if ($existing) { Write-Verbose "Tool '$Name' is already installed (v$($existing.Version))." return } dotnet tool install -g $Name 2>&1 | ForEach-Object { Write-Verbose $_ } if ($LASTEXITCODE -ne 0) { Write-Error "Failed to install tool: $Name" } } } function Uninstall-DotNetTool { <# .SYNOPSIS Uninstall a .NET global tool. .DESCRIPTION Wraps 'dotnet tool uninstall -g'. Accepts pipeline input from Get-DotNetTool. .PARAMETER InputObject A DotNetTool object from Get-DotNetTool. .PARAMETER Name The package ID to uninstall. .EXAMPLE Uninstall-DotNetTool -Name dotnet-ef Uninstalls dotnet-ef globally. .EXAMPLE Get-DotNetTool old-tool | Uninstall-DotNetTool Uninstalls via pipeline. #> [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'ByObject')] param( [Parameter(ParameterSetName = 'ByObject', ValueFromPipeline, Mandatory)] [PSObject]$InputObject, [Parameter(ParameterSetName = 'ByName', Position = 0, Mandatory)] [string]$Name ) process { $toolName = if ($PSCmdlet.ParameterSetName -eq 'ByName') { $Name } else { $InputObject.PackageId } if ($PSCmdlet.ShouldProcess($toolName, 'dotnet tool uninstall -g')) { dotnet tool uninstall -g $toolName 2>&1 | ForEach-Object { Write-Verbose $_ } if ($LASTEXITCODE -ne 0) { Write-Error "Failed to uninstall tool: $toolName" } } } } |