v4.3: Fix issues #123, #124, #125, #126 - #127
Merged
Merged
Conversation
…exit, caching, UPN encoding (#123) - Promote required permissions to module scope; fix Switch-Tenant connecting with empty scopes (F11) - Refresh assignment filter lookup and clear group cache on tenant switch (F24) - Paginate Get-GroupMemberships transitiveMemberOf results (F12) - Set-Environment returns null instead of killing the PowerShell session (F15) - Cache Get-GroupInfo lookups per tenant (F26) - URL-encode UPNs so guest accounts with # resolve (F27) - Paginate Get-AssignmentFailures policy and status fetches (F20) - Export-ResultsIfRequested takes ExportToCSV/ParameterMode as explicit parameters (F17)
…tent misclassification, broken exports, empty-group checks, pagination (#123) - Escape single quotes in group-name OData filters (F9) - App Protection policies now filtered by actual group membership instead of undefined GroupId (F13) - Use tracked winning assignment for app intent classification (F14) - Fix nested Add-ExportData parenthesization producing junk CSV rows in three cmdlets; fix wrong Device entry and invalid -GetExtra argument in group export (F22) - Get-IntuneEmptyGroup: App Protection section now actually tests for empty groups; populate the six endpoint security categories that were displayed but never fetched; add missing Account Protection display section (F18, F19) - Compare-IntuneGroupAssignment: paginate Settings Catalog, Compliance, and Apps fetches (F25) - Update-IntuneSettingDefinition writes to LocalApplicationData instead of the module install directory; Search-IntuneSetting prefers the user copy (F28)
Enables common parameters (-Verbose, -ErrorAction) and PSCmdlet error handling in private helpers. Verified no caller-scope variable reads break under advanced-function scoping.
…es missing from HTML report (#123) - Add -ClientSecretCredential (PSCredential) to Connect/Invoke, preferred over plain-string -ClientSecret which is retained for compatibility (F6) - Derive version banner from module metadata instead of a duplicated literal (F29) - HTML-encode all Graph-derived values in HTML report table cells (F21) - Remove html-export.ps1 redefinitions of module functions and variables; rename its divergent Get-AssignmentInfo to Get-HtmlAssignmentInfo; the removed local template mapping carried a typo that silently dropped EDR policies from HTML reports (F23) - Register script: cross-platform temp path and cleanup of the temporary client secret when certificate upload fails (F30)
Get-IntuneGroupAssignment collected exclusion reasons for apps but only added an app to the output when an inclusion assignment supplied the intent, so exclusion-only apps were silently dropped. The intent of the excluding assignment is now used as a fallback. Compare-IntuneGroupAssignment now marks excluded apps with the [EXCLUDED] suffix used by its other sections. Verified against live tenant data: a group excluded from a required app now appears under Required Apps with reason Group Exclusion.
- Replace stale auto-update claim with the actual PSGallery version check - Document -AccessToken (Option 4: pre-fetched token) and -ClientSecretCredential auth paths - Options 12/13 and cmdlet reference now say user and/or device; add -DeviceNames examples - Register script grants all 9 validated permissions (GUIDs verified against the Graph service principal) plus documented DeviceManagementServiceConfig.Read.All - Register script next-steps output uses the module cmdlets instead of the removed v3 script
…n URI helper (#123) Foundations for decomposing the ten near-identical category-walk cmdlets: - Get-IntuneCategoryDefinition: per-audience category registry; progress totals derive from the list, audience-specific settings catalog filters preserved verbatim - Invoke-IntuneCategoryScan: shared fetch/error/progress engine; per-category failures continue the run and populate the error stream; entity sets cached once per run including the endpoint security intents fallback (retained deliberately: live verification found assigned macOS intents with no configurationPolicies counterpart) - Get-AppProtectionAssignmentUri: single home for the per-type assignments URI switch, now also used by Get-IntuneAssignments - 27 new Pester tests covering caching, dedup, error contracts, and label duality
613 -> 144 lines. Adds Add-CategoryExportData, the registry-driven export helper. Legacy output quirks reproduced verbatim (ES intent wording, Autopilot/ESP summary format, App Protection All Devices drop). Entity sets now fetched once per run instead of up to 7 times.
544 -> 285 lines. Name matching runs as an entity prefilter so assignment fetches still happen only for matched policies (mock-verified: identical fetch sets old vs new). Console and CSV output byte-identical on fixtures.
…ne (#123) 699 -> 188 lines. All Users predicate via Get-AllTargetReason preserved, including single-intent app copy and ES-in-Settings-Catalog duplication. CSV output byte-identical on fixtures; progress lines now numbered.
…gine (#123) 682 -> 158 lines. All Devices predicate preserved including first-match intent for apps and legacy double-listing of ES policies under Settings Catalog. CSV byte-identical on fixtures.
…123) 1440 -> 381 lines. Entity sets now fetched once per run instead of per user (configurationPolicies: 14 fetches -> 1 for two users). App Protection membership filtering (F13), winning-assignment intent (F14), and excluded-app display preserved and regression-tested. Export rows byte-identical on fixtures. 9 new tests.
…#123) 1015 -> 395 lines. Platform compatibility filtering, Windows-conditional Autopilot/ESP/Windows 365 fetching, F14 intent selection, and excluded-app display all preserved and fixture-verified (byte-identical output for Windows and macOS devices). Entity fetches now once per run. Also fixes multi-device input, which was broken: the local split result was assigned into the type-constrained DeviceNames parameter variable, collapsing 'PC-1,PC-2' into a single bogus lookup. 12 new tests.
…ine (#123) 699 -> 435 lines. Legacy semantics preserved exactly: intents-only endpoint security scope (prefiltered), per-assignment app entries with EXCLUDED/INHERITED/filter suffixes, shell scripts kept as a local fetch for their divergent groupAssignments endpoint. CSV and matrix output byte-identical on fixtures; Graph calls 58 -> 40 for a two-group run. 15 new tests.
…#123) 1035 -> 449 lines. Simulated-membership delta logic unchanged; user-only, device-only, combined, and scope-tag runs all byte-identical on fixtures. Entity sets fetched once per run (configurationPolicies 7 -> 1). 12 new tests.
Sweeps the non-migrated files (Get-IntuneEmptyGroup, Get-IntuneUnassignedPolicy, Get-IntuneUserDeviceAssignment, Test cmdlet group lookup, html-export) so no bare GraphEndpoint interpolation remains anywhere in the module.
Get-IntuneUnassignedPolicy, Get-IntuneUserDeviceAssignment, and html-export.ps1 now use Get-AppProtectionAssignmentUri, List-based pagination, and protected category fetches that continue on failure. Get-IntuneUserDeviceAssignment fetches configurationPolicies and intents once per run instead of 13 times.
PSScriptAnalyzer ResultsFound 0 error(s) and 5 warning(s). See the workflow run for details. |
This was referenced Jul 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves #123, #124, #126. Addresses #125 (see the verification note below on why the intents fallback is retained).
Summary
#126 - Excluded apps now shown in group checks
Get-IntuneGroupAssignment collected exclusion reasons for apps but dropped the app when no inclusion assignment supplied an intent. The excluding assignment's intent is now used as a fallback, so exclusion-only apps appear in their intent bucket with reason "Group Exclusion" / "Inherited Exclusion (via X)". Compare-IntuneGroupAssignment marks excluded apps with the [EXCLUDED] suffix used by its other sections. Verified against live tenant data: a group excluded from a required app now appears under Required Apps.
#123 - All 30 findings addressed, including the decomposition
#124 - Docs and register script aligned
README auth options (adds pre-fetched token and client secret credential), user-and/or-device wording for options 12/13, register script grants all nine validated permissions plus documented DeviceManagementServiceConfig.Read.All, and its next-steps output uses the module cmdlets. Permission GUIDs were verified against the Microsoft Graph service principal appRoles via live Graph calls; two GUIDs previously suggested in the issue comments (DeviceManagementScripts.Read.All, DeviceManagementRBAC.Read.All) were wrong and are corrected here.
#125 - Intents fallback retained deliberately
Live verification before removal found an assigned macOS FileVault policy that exists only as a deviceManagement/intent, with no configurationPolicies counterpart: the MC955748 auto-migration covered Windows endpoint security policies only. Removing the fallback would silently drop live macOS legacy policies from every report. Instead, the fallback is centralized in the scan engine (intents and templates fetched once per run instead of six-plus times per cmdlet), which delivers the API-call reduction the issue aimed for without the regression. Removal can be revisited when Microsoft migrates the remaining macOS intents.
Verification