PowerProfile.Commands.PSConfig.psm1
#Requires -Version 5.1 function Set-PSConfig { <# .SYNOPSIS Add/change/remove a PowerShell configuration item .DESCRIPTION Adds an item to the PowerShell configuration .PARAMETER Name Key name of the configuration item .PARAMETER Value Value of the configuration item .PARAMETER Scope Set the AllUsers (shared/LocalMachine) configuration instead of CurrentUser (per-user) configuration. .PARAMETER Remove Removes the desired configuration item .PARAMETER Registry Enforce to use the configuration from Windows Registry. .PARAMETER Json Enforce to use the configuration from powershell.config.json. .PARAMETER PassThru Returns an object with the PowerShell configuration. By default, this function does not generate any output. .INPUTS PSObject .OUTPUTS PSObject. Only when using -PassThru parameter. .LINK https://PowerProfile.sh/ #> [CmdletBinding(DefaultParameterSetName='SetKey')] Param( [Parameter(Mandatory=$True,Position=0,ParameterSetName='SetKey')] [Parameter(Mandatory=$True,Position=0,ParameterSetName='RemoveKey')] [ValidateScript({ ($_ -cmatch '\.ExecutionPolicy$') -or ($_ -ceq 'PSModulePath') -or ($_ -ceq 'ExperimentalFeatures') -or ($_ -ceq 'LogIdentity') -or ($_ -ceq 'LogLevel') -or ($_ -ceq 'LogChannels') -or ($_ -ceq 'LogKeywords') -or ($_ -ceq 'WindowsPowerShellCompatibilityModuleDenyList') -or $(throw "Unknown PowerShell configuration key '$_'. Valid keys are: *.ExecutionPolicy PSModulePath ExperimentalFeatures LogIdentity LogLevel LogChannels LogKeywords") })] [string]$Name, [Parameter(Mandatory=$True,Position=1,ParameterSetName='SetKey')] [AllowEmptyString()] [AllowNull()] $Value, [Parameter(ParameterSetName='SetKey')] [Parameter(ParameterSetName='RemoveKey')] [ValidateSet('CurrentUser','AllUsers')] [string]${Scope}='CurrentUser', [Parameter(Mandatory=$True,ParameterSetName='RemoveKey')] [switch]$Remove, [switch]$Registry, [switch]$Json, [switch]$PassThru ) if ($Registry -and $Json) { if ($IsCoreCLR -or -not $IsWindows) { Write-Verbose 'Implicitly enforcing JSON configuration' $Registry = $false } else { Write-Verbose 'Implicitly enforcing Registry configuration' $Json = $false } } elseif ($IsWindows -and -not $IsCoreCLR -and -not $Registry -and -not $Json) { Write-Verbose 'Windows PowerShell detected, assuming Registry configuration' $Registry = $true } if ($Registry) { if (-Not $IsWindows) { throw 'Registry is only available on Windows machines.' } if ($Scope -eq 'AllUsers') { $path = 'Registry::HKEY_LOCAL_MACHINE' } else { $path = 'Registry::HKEY_CURRENT_USER' } $path += '\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell\' if (-Not (Test-Path $path)) { Write-Verbose "Creating new path $path" $null = New-Item -Path $path -Force -ErrorAction Stop } $null = New-ItemProperty -Path $path -Name $Name -Value $Value -Force -ErrorAction Stop if ($PassThru) { return (Get-PSConfig -Scope $Scope -Registry) } } else { if (-Not $IsCoreCLR) { throw 'Windows PowerShell does not use powershell.config.json configuration files.' } $psconfig = Get-PSConfig -Scope $Scope -Json if ($psconfig -is [System.Management.Automation.PSObject]) { if ($Value -eq [bool]::TrueString -or $Value -eq [bool]::FalseString) { $Value = [System.Convert]::ToBoolean($Value) } if ($Remove) { $psconfig.PSObject.Properties.Remove($Name) } elseif ($null -eq $psconfig.PSObject.Properties.Item($Name)) { $psconfig | Add-Member -MemberType NoteProperty -Name $Name -Value $Value } else { $psconfig.$Name = $Value } } else { $psconfig = New-Object PSObject if (-Not $Remove) { Write-Verbose 'Generating new configuration object' $psconfig | Add-Member -MemberType NoteProperty -Name $Name -Value $Value } } if ($Scope -eq 'AllUsers') { $path = [System.IO.Path]::Combine($PSHOME,'powershell.config.json') } else { $path = [System.IO.Path]::Combine((Split-Path $PROFILE.CurrentUserCurrentHost),'powershell.config.json') } if (($psconfig.PSObject.Properties).Count -gt 0) { $baseDir = Split-Path -Path $path if (-Not ([System.IO.Directory]::Exists($baseDir))) { Write-Verbose "Creating new directory $baseDir" $null = New-Item -Type Container -Force $baseDir -ErrorAction Stop } Write-Verbose "Serializing configuration object to $path" ConvertTo-Json $psconfig -Compress | Set-Content -Path $path -Encoding ASCII } elseif ([System.IO.File]::Exists($path)) { Write-Verbose "Deleting empty configuration file $path" Remove-Item -Path $path } if ($PassThru) { return $psconfig } } } function Get-PSConfig { <# .SYNOPSIS Get PowerShell JSON configuration .DESCRIPTION Reads the PowerShell configuration .PARAMETER Name Return the value of a specific configuration item only .PARAMETER Scope Read the AllUsers (shared/LocalMachine) configuration instead of CurrentUser (per-user) configuration. .PARAMETER Registry Enforce to use the configuration from Windows Registry. .PARAMETER Json Enforce to use the configuration from powershell.config.json. .INPUTS PSObject .OUTPUTS String, when specifying $Name, otherwise PSObject. .LINK https://PowerProfile.sh/ #> [CmdletBinding()] Param( [Parameter(Position=0)] [string]$Name, [ValidateSet('CurrentUser','AllUsers')] [string]${Scope}='CurrentUser', [switch]$Registry, [switch]$Json ) if ($Registry -and $Json) { if ($IsCoreCLR -or -not $IsWindows) { $Registry = $false } else { $Json = $false } } elseif ($IsWindows -and -not $IsCoreCLR -and -not $Registry -and -not $Json) { $Registry = $true } if ($Registry) { if (-Not $IsWindows) { throw 'Registry is only available on Windows machines.' } if ($Scope -eq 'AllUsers') { $path = 'Registry::HKEY_LOCAL_MACHINE' } else { $path = 'Registry::HKEY_CURRENT_USER' } $path += '\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell\' if ($Name) { return (Get-ItemProperty -Path $path -Name $Name -ErrorAction Ignore) } $dir = Get-Item -Path $path -ErrorAction Ignore if ($dir) { $property = Get-ItemProperty -Path $path $psconfig = New-Object PSObject foreach ($Name in $dir.Property) { $psconfig | Add-Member -MemberType NoteProperty -Name $Name -Value $property.$Name } } } else { if (-Not $IsCoreCLR) { throw 'Windows PowerShell does not use powershell.config.json configuration files.' } if ($Scope -eq 'AllUsers') { $path = [System.IO.Path]::Combine($PSHOME,'powershell.config.json') } else { $path = [System.IO.Path]::Combine((Split-Path $PROFILE.CurrentUserCurrentHost),'powershell.config.json') } if ([System.IO.File]::Exists($path)) { $psconfig = [System.IO.File]::ReadAllText($path) | ConvertFrom-Json -ErrorAction Ignore } } if ($psconfig -is [System.Management.Automation.PSObject]) { if ($Name) { return $psconfig.$Name } else { return $psconfig } } return $null } function Remove-PSConfig { <# .SYNOPSIS Remove PowerShell configuration item .DESCRIPTION Removes a configuration item from powershell.config.json .PARAMETER Name Key name of the configuration item .PARAMETER Scope Set the AllUsers (shared/LocalMachine) configuration instead of CurrentUser (per-user) configuration. .PARAMETER Registry Enforce to use the configuration from Windows Registry. .PARAMETER Json Enforce to use the configuration from powershell.config.json. .PARAMETER PassThru Returns an object with the PowerShell configuration. By default, this function does not generate any output. .PARAMETER Clear Deletes the powershell.config.json file to clear the entire PowerShell configuration. .INPUTS PSObject .OUTPUTS PSObject. Only when using -PassThru parameter. .LINK https://PowerProfile.sh/ #> [CmdletBinding()] [OutputType([System.Management.Automation.PSObject])] Param( [Parameter(Mandatory=$True,ParameterSetName='Clear')] [switch]$Clear, [Parameter(Mandatory=$True,Position=0,ParameterSetName='Remove')] [string]$Name, [Parameter(ParameterSetName='Remove')] [Parameter(ParameterSetName='Clear')] [ValidateSet('CurrentUser','AllUsers')] [string]${Scope}='CurrentUser', [Parameter(ParameterSetName='Remove')] [switch]$Registry, [Parameter(ParameterSetName='Remove')] [switch]$Json, [Parameter(ParameterSetName='Remove')] [switch]$PassThru ) if ($Clear) { If ($Registry) { throw 'PowerShell configuration in Registry cannot be cleared at once.' } if ($Scope -eq 'AllUsers') { $path = [System.IO.Path]::Combine($PSHOME,'powershell.config.json') } else { $path = [System.IO.Path]::Combine((Split-Path $PROFILE.CurrentUserCurrentHost),'powershell.config.json') } if ([System.IO.File]::Exists($path)) { Remove-Item -Path $path -Force -ErrorAction Ignore } return } Try { $psconfig = Set-PSConfig -Remove -Name $Name -Scope $Scope -Registry:$Registry -Json:$Json -PassThru:$PassThru } Catch { Write-Error $_.Exception.Message return } if ($PassThru) { return $psconfig } } |