128 lines
5.2 KiB
PowerShell
128 lines
5.2 KiB
PowerShell
function Set-AppSettingPrivateJson {
|
|
<#
|
|
.SYNOPSIS
|
|
Sets an appSetting Key/Value pair in the specified file.
|
|
This does so according to the JSON appSettings.json expected schema.
|
|
|
|
.DESCRIPTION
|
|
Sets an appSetting Key/Value pair in the specified file.
|
|
This does so according to the JSON appSettings.json expected schema.
|
|
Can connect to remote computers as well.
|
|
|
|
.PARAMETER Key
|
|
[string] The appSetting key
|
|
|
|
.PARAMETER Value
|
|
[string] The appSetting value to set, if it's different than the existing file
|
|
|
|
.PARAMETER filePath
|
|
[string] The location to change settings in. Defaults to the global 64bit machine.config file.
|
|
|
|
.PARAMETER Force
|
|
[switch] Allow forcing the write of the process. This is due to the option for ShouldProcess.
|
|
|
|
.PARAMETER UpdateOnly
|
|
[switch] Only updates a key's value if it exists. Will not create the missing AppSetting key.
|
|
#>
|
|
[CmdletBinding(SupportsShouldProcess, ConfirmImpact='None')]
|
|
param (
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$Key,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[AllowEmptyString()]
|
|
[string]$Value,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[Alias("Path")]
|
|
[string]$FilePath,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[switch]$Force,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[switch]$UpdateOnly
|
|
)
|
|
|
|
$logLead = (Get-LogLeadName)
|
|
$dirty = $false
|
|
|
|
$json = (ConvertFrom-Json -InputObject (Get-Content -Path $FilePath -Raw))
|
|
|
|
# appsettings.json has a magic trick for us
|
|
# if I specify Parent:Child then I'm looking for something like
|
|
# { "Parent": { "Child": value } }
|
|
# if I specify Parent.Child then I'm looking for something like
|
|
# { "Parent.Child": value }
|
|
# So we want to be able to do a depth search by the colon'd parts
|
|
$keyNodeList = $Key.Split(':')
|
|
if (Test-IsCollectionNullOrEmpty $keyNodeList) {
|
|
throw "$logLead : For config file [$FilePath] - No valid key specified - Can not continue. Key was [$Key]"
|
|
}
|
|
foreach($node in $keyNodeList) {
|
|
if ([string]::IsNullOrWhiteSpace($node)) {
|
|
throw "$logLead : For config file [$FilePath] - Found invalid node element [$node] in Key path [$Key]"
|
|
}
|
|
}
|
|
|
|
$lastNode = "<root>"
|
|
$tempNode = $json
|
|
foreach($node in $keyNodeList) {
|
|
Write-Verbose "$logLead : Checking `$tempNode [$tempNode] for property `$node [$node]"
|
|
|
|
# If the UpdateOnly switch is specified, and an AppSetting was not found, early out of saving anything.
|
|
if ($UpdateOnly -and ($null -eq $tempNode.$node)) {
|
|
Write-Warning "$logLead : For config file [$FilePath] - Could not find specified Key [$Key]. Not creating AppSetting node because UpdateOnly was specified. Exiting.."
|
|
return
|
|
}
|
|
|
|
# TODO: This doesn't handle the case of "the existing node is a value and the asked-for value is a complex object"
|
|
# Right now this just does nothing in that case, but it should error or warn
|
|
|
|
if ($null -eq $tempNode.$node) {
|
|
# If this is not the last entry in the list, keep adding subobjects so we can add values
|
|
if ($node -ne $keyNodeList[-1]) {
|
|
Write-Host "$logLead : Could not find sub-element with key [$node]. Adding one so we can add sub-elements."
|
|
$tempNode | Add-Member -MemberType NoteProperty -Name $node -Value (New-Object -TypeName "PSCustomObject")
|
|
} else {
|
|
# Otherwise set it to the value that we wanted to add since we didn't have a value yet anyways
|
|
Write-Host "$logLead : Could not find appSetting Key [$node]. Creating one and setting value to [$Value]."
|
|
$tempNode | Add-Member -MemberType NoteProperty -Name $node -Value $Value
|
|
}
|
|
$dirty = $true
|
|
} else {
|
|
# if it's the last node in our list and the value doesn't match, set the value here
|
|
if ($node -eq $keyNodeList[-1]) {
|
|
if ($tempNode.$node -cne $Value) {
|
|
Write-Host "$logLead : Found appSetting [$node], changing value from [$($tempNode.$node)] to [$Value]."
|
|
$tempNode.$node = $Value
|
|
$dirty = $true
|
|
}
|
|
} else{
|
|
if ($tempNode.$node.GetType().Name -ne "PSCustomObject") {
|
|
Write-Error "$logLead : Asked to add a subproperty [$node] to element [$lastNode] but the element [$lastNode] can not take properties"
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
$tempNode = $tempNode.$node
|
|
$lastNode = $node
|
|
}
|
|
|
|
# Only useful when debugging. Don't write typically.
|
|
$debugFinalValue = ConvertTo-Json -InputObject $json -Depth 100 -Compress:$true
|
|
Write-Host "$logLead [$debugFinalValue]"
|
|
|
|
if($dirty) {
|
|
Write-Verbose "$logLead : Saving config to path [$FilePath]"
|
|
|
|
if ($Force -or $PSCmdlet.ShouldProcess("Ready to write the file [$FilePath] contents?")) {
|
|
Set-Content -Path $FilePath -Value ($json | Format-Json)
|
|
} else {
|
|
Write-Host "$logLead : When confirmed, will write to file [$FilePath]"
|
|
}
|
|
} else {
|
|
Write-Verbose "$logLead : No value changes were made to $FilePath. Not updating the file."
|
|
}
|
|
} |