This sanitized, read-only engineering sample contains no tenant IDs, company prefixes, internal URLs, or organization-specific paths. Graph tools use delegated interactive authentication. The account picker opens in the browser or Windows authentication broker. Device-code authentication is intentionally not used.
- Windows PowerShell 5.1, 64-bit
- Microsoft.Graph.Authentication for Graph-based tools
- An Intune role that permits the requested read operations
- Consent for the delegated scopes listed below
Get-IntuneUpdateRingCoverage.ps1expects..\Shared\IntuneToolkit.Common.psm1relative to its own folder (i.e. one level up, underShared). Keep the toolkit's folder structure intact when copying scripts elsewhere.
DeviceManagementConfiguration.Read.AllGroup.Read.AllDirectory.Read.AllDevice.Read.All only with -ExpandGroupMembers
.\Get-IntuneUpdateRingCoverage.ps1 -ExpandGroupMembersOutput is written beneath the current user's Documents folder unless -OutputRoot is supplied. The Autopilot collector defaults to a folder on the current user's Desktop. No company-specific path is hard coded.
Get-IntuneUpdateRingCoverage.ps1 creates an UpdateRingAnalyzer folder under -OutputRoot (or the default) containing:
RingSettings.csv- every Windows Update for Business ring found, with its key deferral/deadline/restart settings.RingAssignments.csv- each ring's group/filter assignments (always produced).DeviceRingMembership.csv- devices expanded from assigned groups, one row per (device, ring) pairing. Only produced with-ExpandGroupMembers.PotentialSettingConflicts.csv- devices covered by more than one ring where a setting differs between those rings, matched by ring ID (not display name) so two rings sharing a name are never conflated. Only produced with-ExpandGroupMembers.
The shared module calls Connect-MgGraph -Scopes <scopes> -ContextScope Process -NoWelcome. It disconnects any existing Graph context first and then opens interactive account selection. Do not add -UseDeviceAuthentication.
- Assignment applicability is an engineering inference, not Intune's final policy engine result.
- Filters, exclusions, user-versus-device context, licensing, applicability rules, and service-side processing can change the effective result.
- Large tenants can require substantial time and Graph requests when group membership expansion is enabled.
Get-IntuneUpdateRingCoverage.ps1calls Microsoft Graph v1.0 endpoints only. Other tools in this toolkit may use beta endpoints - test before production use and review changes to the API regardless of version.
These are quirks of IntuneToolkit.Common.psm1 as currently implemented, not of Microsoft Graph itself. Worth knowing before modifying this script or writing a new one against the same module:
Get-ToolkitCollectionreturns the raw OData response, not a flattened item list. It hands back the whole response object (aHashtablewith@odata.context,value, and@odata.nextLinkwhen more pages remain) rather than an array of the actual items. This script wraps every call in a localGet-ToolkitGraphItemshelper that unwrapsvalueand follows@odata.nextLinkuntil exhausted.- Items in
valueareHashtableobjects, notPSCustomObject. Dot-notation reads (e.g.$item.displayName) work via PowerShell's dictionary-key fallback, but.PSObject.Properties.Name -contains 'foo'does not - for aHashtable, that only lists the class's own real members (Count,Keys,Values, etc.), never the dictionary's actual keys. This script uses a localGet-ToolkitValuehelper that checksContainsKey/indexes directly instead, for any "does this field exist" check. Resolve-ToolkitTargetreads some assignment-target fields unconditionally. Graph omits fields likedeviceAndAppManagementAssignmentFilterTypefrom the JSON entirely when they don't apply (e.g. no filter on that assignment) rather than sending them as null, and the module's function doesn't guard against a genuinely-missing key. Note that this script's ownSet-StrictModesetting does not reach into the module's functions either way - functions imported from a module run in the module's own scope chain, so the module enforces whatever strict-mode behavior it sets internally, independent of the calling script. The fix is on the data side: a localConvertTo-ToolkitAssignmentTargethelper pads the target with$nulldefaults for the standard assignment-target schema fields (groupId,deviceAndAppManagementAssignmentFilterId,deviceAndAppManagementAssignmentFilterType) before it's passed toResolve-ToolkitTarget.
If Resolve-ToolkitTarget throws a similar "property cannot be found" error on a different field name in your tenant, add that field to the padding list in ConvertTo-ToolkitAssignmentTarget rather than relaxing strict mode in this script - relaxing strict mode here has no effect on the module's own enforcement.
Sample data uses fictional devices, groups, users, IDs, and application names. Do not publish real exports. Review logs and CSVs before sharing them outside your organization.