function Get-GraphDocumentation { <# .SYNOPSIS Document one Intune/Entra policy object and return the per-object result. .DESCRIPTION Public, UI-independent entry point for documenting a single PolicyObject. Returns the PSCustomObject the output providers consume — does not write any files itself. Use Start-GraphBulkDocumentation for a batch run that also drives output providers. Dispatch: 1. Looks up a per-@odata.type custom handler in [DocumentationRegistry] 2. If none claims the object, falls back to the schema-driven input- provider chain (Settings Catalog / ADMX / Intent / Compliance V2 / generic Profile) 3. If no provider matches either, returns an empty result with InputType='NoProvider' rather than throwing Phase 2 wires the dispatch shape; handlers and input providers are populated in phases 4 and 3. .PARAMETER PolicyObject The IntunePolicyBase-derived object to document. .PARAMETER Language Language code for translatable strings. Defaults to 'en'. .PARAMETER Options Hashtable of engine-wide flags. Recognized keys: IncludeScripts [bool] include embedded script bodies (default true) ExcludeScriptSignature [bool] strip script signing blocks (default false) IncludePolicyId [bool] include policy ID in basic info (default false) ExcludeAssignments [bool] omit assignment rows (default false) PropertySeparator [string] separator for property collections ObjectSeparator [string] separator for object collections SkipNotConfigured [bool] omit empty or unconfigured settings and basic properties SkipDefaultValues [bool] omit default or unconfigured values SkipDisabled [bool] omit disabled settings SetUnconfiguredValue [bool] substitute declared unconfigured values SetDefaultValue [bool] substitute declared defaults NotConfiguredText [string] notConfigured | empty | asis ValueOutputProperty [string] value | valueWithLabel for ADMX settings SkipDocumentInfo [bool] omit the document-info header every output provider writes at the top of a Full document (Organization / Generated by / Generated date) SourceTenantUnavailable [bool] the source tenant of an export is unreachable: skip source-tenant-specific lookups (assignments, scope-tag/filter/app names, etc.). Generic Intune schema is still resolved from any connected tenant. (Legacy alias: OfflineDocumentation.) Outputs [hashtable] explicit per-provider output options .OUTPUTS PSCustomObject — see [DocumentationContext]::ToResult for the contract. .EXAMPLE $policy = Get-GraphPolicies -PolicyType ConditionalAccessType | Select-Object -First 1 $doc = Get-GraphDocumentation -PolicyObject $policy $doc.FilteredSettings | Format-Table Name, Value #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)] $PolicyObject, [string]$Language = 'en', [hashtable]$Options ) process { # Save/restore the module-wide language: Set-CurrentDocumentationContext # points Get-LanguageString at $Context.Language for the doc run; other # consumers (policy classes, compare) must not inherit it afterwards. $prevLang = $script:CurrentLanguage try { # Use the module-singleton context so cross-batch caches (ScopeTags, # CachedCfgSettings, CfgCategories, ADMXCategories) amortize across # successive Get-GraphDocumentation calls — same behavior as the bulk # path. ResetForObject inside Invoke-DocumentationForObject clears the # per-object accumulators; the caches persist. $ctx = Get-DocContextSingleton -Options $Options Set-DocumentationContextRunOptions -Context $ctx -Options $Options -Language $Language # Ensure the object is hydrated before dispatch. Handlers / input # providers read fully populated JsonObject + sub-resources; a row # straight out of Get-GraphPolicies typically isn't full. Single-row # hydrate path takes the direct-GET branch in Invoke-PolicyHydrate. # Skip for file-loaded objects / source-tenant-unavailable docs — those # have no token and Invoke-PolicyHydrate would issue Graph calls under the # default token, hitting either an auth error or the wrong tenant. if ($PolicyObject -and $PolicyObject.PSObject.Properties['_IsFullObject'] -and -not $PolicyObject._IsFullObject -and $PolicyObject.Id -and $PolicyObject.PolicyType -and $PolicyObject.IsFromFile -ne $true -and -not $ctx.SourceTenantUnavailable) { Invoke-PolicyHydrate -Policies @($PolicyObject) } Invoke-DocumentationForObject -PolicyObject $PolicyObject -Context $ctx } finally { $script:CurrentLanguage = $prevLang } } }