Files
IntuneManagement/Public/Get-Setting.ps1
T

124 lines
4.5 KiB
PowerShell

<#
.SYNOPSIS
Read an IntuneManagement setting by key.
.DESCRIPTION
Exported as Get-IMSetting.
The public read side of the settings system. A key is all that is needed - the
storage path is taken from the setting's registration, so automation never has
to know that "GraphPageSize" lives under "IntuneManager" or that the store is a
registry key on Windows and a JSON file everywhere else.
Resolution order is the same one the application itself uses: the value for the
connected tenant, then the global value, then the value the setting was
registered with. -Scope pins it to one level.
With no -Key, every registered setting is returned.
.PARAMETER Key
The setting key. Accepts pipeline input. Omit to return all registered settings.
.PARAMETER Scope
Effective (default) resolves tenant, then global, then the registered default.
Global reads the global value only. Tenant reads the tenant value only.
A scoped read returns $null when nothing is stored at that scope - it does NOT
fall back to the registered default, so "not overridden here" stays
distinguishable from "overridden to the same value as the default". With
-Detailed the Source of such a read is 'NotSet'. Tenant scope needs a tenant:
it reports an error rather than a value when none is connected and no -TenantID
is given.
.PARAMETER TenantID
Which tenant to resolve against. Defaults to the connected tenant.
.PARAMETER SubPath
Storage path for a key that is not a registered setting (the hidden keys such as
ExportReplaceTokens, and per-feature state). Required in that case - an
unregistered key has no registration to take a path from. Reported and ignored
for a registered one, exactly as on Set-IMSetting.
An unregistered key has no registered default, so its Source is Tenant, Global
or NotSet - never Default - and no type normalization is applied: the value
comes back as the string the store holds.
.PARAMETER Detailed
Return the value together with where it came from (Tenant, Global, Default or
NotSet), its type, its storage path and its registered default, instead of just
the value.
.EXAMPLE
Get-IMSetting ExportFolder
.EXAMPLE
Get-IMSetting UseBatchAPI -Detailed
Shows whether the value in effect was set for this tenant, set globally, or is
just the default - which is what to check before changing it.
.EXAMPLE
'AddCompanyName','AddObjectType' | Get-IMSetting
.EXAMPLE
Get-IMSetting | Where-Object Source -ne 'Default'
Every setting that has actually been configured.
.EXAMPLE
Set-IMSetting ExportReplaceTokens 'TenantId' -SubPath 'IntuneManager'
Get-IMSetting ExportReplaceTokens -SubPath 'IntuneManager'
Reading back a hidden key needs the same path the write used.
.LINK
Set-IMSetting
.LINK
Get-IMSettingDefinition
.LINK
Get-IMSettingsStore
#>
function Get-Setting
{
[CmdletBinding()]
param(
[Parameter(Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[string]$Key,
[ValidateSet("Effective", "Global", "Tenant")]
[string]$Scope = "Effective",
[string]$TenantID,
# $null, not "": "" is the root of the store, so "not supplied" and "the
# root" have to stay distinguishable. Same convention as Set-IMSetting.
$SubPath = $null,
[switch]$Detailed
)
process
{
# No key = every registered setting. A bare list of values would be
# meaningless without the keys beside them, so that form is always detailed.
$keys = @($Key)
if(-not $Key)
{
$keys = @(Get-SettingsSections | ForEach-Object { $_.Values } | ForEach-Object Key)
$Detailed = $true
# Enumerating the registered settings takes every path from its own
# registration; there is nothing for a single -SubPath to apply to.
if($null -ne $SubPath) { Write-Log "Ignoring -SubPath '$SubPath': it applies to a single unregistered -Key, not to a listing of registered settings" 2 }
$SubPath = $null
}
foreach($settingKey in $keys)
{
$resolved = Resolve-SettingValue -Key $settingKey -TenantID $TenantID -SubPath $SubPath `
-GlobalOnly:($Scope -eq "Global") -TenantOnly:($Scope -eq "Tenant")
if(-not $resolved) { continue }
if($Detailed) { $resolved }
else { $resolved.Value }
}
}
}