Private/Get-TemplateDisplayNames.ps1
|
function Get-TemplateDisplayNames { <# .SYNOPSIS Extracts display names from template JSON files into a case-insensitive HashSet. .DESCRIPTION Loads JSON template files from a directory and extracts display names using the appropriate property for each resource type. Returns a case-insensitive HashSet[string] of known template names for use as a safety gate in delete operations. .PARAMETER Path The directory path containing template JSON files. .PARAMETER NameProperty The JSON property to extract as the display name. Defaults to 'displayName'. Use 'name' for resources that use the name property (e.g., configurationPolicies). .PARAMETER ArrayProperty If templates contain a nested array of objects (e.g., 'filters' or 'groups'), specify the array property name. Names will be extracted from each array element. .PARAMETER Recurse If specified, searches subdirectories recursively. .PARAMETER UseFileName If specified, uses the file basename (without extension) as the name instead of a JSON property. Used for Conditional Access templates. .PARAMETER Prefix Optional prefix to prepend to each name. Used for Conditional Access templates that add a prefix to file basenames. .OUTPUTS [System.Collections.Generic.HashSet[string]] Case-insensitive HashSet of display names. .EXAMPLE Get-TemplateDisplayNames -Path './Templates/MobileApps' -Recurse .EXAMPLE Get-TemplateDisplayNames -Path './Templates/Filters' -ArrayProperty 'filters' -Recurse #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$Path, [Parameter()] [string]$NameProperty = 'displayName', [Parameter()] [string]$ArrayProperty, [Parameter()] [switch]$Recurse, [Parameter()] [switch]$UseFileName, [Parameter()] [string]$Prefix ) $names = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase) if (-not (Test-Path -Path $Path)) { Write-Verbose "Template path not found: $Path" return , $names } $templateFiles = Get-ChildItem -Path $Path -Filter "*.json" -File -Recurse:$Recurse if (-not $templateFiles -or $templateFiles.Count -eq 0) { Write-Verbose "No template files found in: $Path" return , $names } foreach ($file in $templateFiles) { if ($UseFileName) { $name = "$Prefix$([System.IO.Path]::GetFileNameWithoutExtension($file.Name))" [void]$names.Add($name) continue } try { $content = Get-Content -Path $file.FullName -Raw | ConvertFrom-Json -ErrorAction Stop } catch { Write-Verbose "Failed to parse template: $($file.Name)" continue } if ($ArrayProperty -and $content.$ArrayProperty) { foreach ($item in $content.$ArrayProperty) { $itemName = $item.$NameProperty if ($itemName) { [void]$names.Add($itemName) } } } else { $name = $content.$NameProperty if (-not $name -and $NameProperty -eq 'displayName') { $name = $content.name } if ($name) { [void]$names.Add($name) } } } Write-Verbose "Loaded $($names.Count) template name(s) from $Path" # Comma operator prevents PowerShell from enumerating the HashSet on output. # Without it, an empty HashSet is enumerated to nothing and the caller gets $null. return , $names } |