@@ -49,6 +49,14 @@ function Get-CIPPDrift {
4949 # Skip invalid templates
5050 }
5151 } | Sort-Object - Property displayName
52+
53+ # Build GUID-indexed hashtable for faster lookups
54+ $IntuneTemplateLookup = @ {}
55+ foreach ($Template in $AllIntuneTemplates ) {
56+ if ($Template.GUID ) {
57+ $IntuneTemplateLookup [$Template.GUID ] = $Template
58+ }
59+ }
5260 }
5361 # Load all CA templates
5462 if ($ConditionalAccessCapable ) {
@@ -63,6 +71,14 @@ function Get-CIPPDrift {
6371 # Skip invalid templates
6472 }
6573 } | Sort-Object - Property displayName
74+
75+ # Build GUID-indexed hashtable for faster lookups
76+ $CATemplateLookup = @ {}
77+ foreach ($Template in $AllCATemplates ) {
78+ if ($Template.GUID ) {
79+ $CATemplateLookup [$Template.GUID ] = $Template
80+ }
81+ }
6682 }
6783
6884 try {
@@ -95,36 +111,39 @@ function Get-CIPPDrift {
95111 if ($Alignment.ComparisonDetails ) {
96112 foreach ($ComparisonItem in $Alignment.ComparisonDetails ) {
97113 if ($ComparisonItem.Compliant -ne $true ) {
98- $Status = if ($ExistingDriftStates.ContainsKey ($ComparisonItem.StandardName )) {
99- $ExistingDriftStates [$ComparisonItem.StandardName ].Status
114+ # Cache the existing drift state lookup
115+ $ExistingDriftState = if ($ExistingDriftStates.ContainsKey ($ComparisonItem.StandardName )) {
116+ $ExistingDriftStates [$ComparisonItem.StandardName ]
100117 } else {
101- ' New '
118+ $null
102119 }
103- # Reset displayName and description for each deviation to prevent carryover from previous iterations
120+
121+ $Status = if ($ExistingDriftState ) { $ExistingDriftState.Status } else { ' New' }
104122 $displayName = $null
105123 $standardDescription = $null
124+
106125 # if the $ComparisonItem.StandardName contains *intuneTemplate*, then it's an Intune policy deviation, and we need to grab the correct displayname from the template table
107126 if ($ComparisonItem.StandardName -like ' *intuneTemplate*' ) {
108- $CompareGuid = $ComparisonItem.StandardName.Split ( ' .' ) | Select-Object - Index 2
127+ $CompareGuid = ( $ComparisonItem.StandardName -split ' \ .' )[ 2 ]
109128 Write-Verbose " Extracted GUID: $CompareGuid "
110- $Template = $AllIntuneTemplates | Where-Object { $_ .GUID -eq " $ CompareGuid" }
129+ $Template = $IntuneTemplateLookup [ $ CompareGuid]
111130 if ($Template ) {
112131 $displayName = $Template.displayName
113132 $standardDescription = $Template.description
114133 }
115134 }
116135 # Handle Conditional Access templates
117136 if ($ComparisonItem.StandardName -like ' *ConditionalAccessTemplate*' ) {
118- $CompareGuid = $ComparisonItem.StandardName.Split ( ' .' ) | Select-Object - Index 2
137+ $CompareGuid = ( $ComparisonItem.StandardName -split ' \ .' )[ 2 ]
119138 Write-Verbose " Extracted CA GUID: $CompareGuid "
120- $Template = $AllCATemplates | Where-Object { $_ .GUID -eq " $ CompareGuid" }
139+ $Template = $CATemplateLookup [ $ CompareGuid]
121140 if ($Template ) {
122141 $displayName = $Template.displayName
123142 $standardDescription = $Template.description
124143 }
125144 }
126- $reason = if ($ExistingDriftStates .ContainsKey ( $ComparisonItem .StandardName )) { $ExistingDriftStates [ $ComparisonItem .StandardName ]. Reason }
127- $User = if ($ExistingDriftStates .ContainsKey ( $ComparisonItem .StandardName )) { $ExistingDriftStates [ $ComparisonItem .StandardName ]. User }
145+ $reason = if ($ExistingDriftState ) { $ExistingDriftState . Reason } else { $null }
146+ $User = if ($ExistingDriftState ) { $ExistingDriftState . User } else { $null }
128147 $StandardsDeviations.Add ([PSCustomObject ]@ {
129148 standardName = $ComparisonItem.StandardName
130149 standardDisplayName = $displayName
@@ -256,22 +275,26 @@ function Get-CIPPDrift {
256275 }
257276 }
258277
278+ # Build hashtable lookup for template policies
279+ $TemplatePolicyLookup = @ {}
280+ foreach ($TemplatePolicy in $TemplateIntuneTemplates ) {
281+ $names = @ (
282+ $TemplatePolicy.displayName ,
283+ $TemplatePolicy.name
284+ ) | Where-Object { $_ }
285+ foreach ($name in $names ) {
286+ $TemplatePolicyLookup [$name ] = $true
287+ }
288+ }
289+
259290 # Check for extra Intune policies not in template
260291 foreach ($TenantPolicy in $TenantIntunePolicies ) {
261- $PolicyFound = $false
262292 $tenantPolicy.policy | Add-Member - MemberType NoteProperty - Name ' URLName' - Value $TenantPolicy.Type - Force
263293 $TenantPolicyName = if ($TenantPolicy.Policy.displayName ) { $TenantPolicy.Policy.displayName } else { $TenantPolicy.Policy.name }
264- foreach ($TemplatePolicy in $TemplateIntuneTemplates ) {
265- $TemplatePolicyName = if ($TemplatePolicy.displayName ) { $TemplatePolicy.displayName } else { $TemplatePolicy.name }
266-
267- if ($TemplatePolicy.displayName -eq $TenantPolicy.Policy.displayName -or
268- $TemplatePolicy.name -eq $TenantPolicy.Policy.name -or
269- $TemplatePolicy.displayName -eq $TenantPolicy.Policy.name -or
270- $TemplatePolicy.name -eq $TenantPolicy.Policy.displayName ) {
271- $PolicyFound = $true
272- break
273- }
274- }
294+
295+ # Use hashtable lookup instead of nested loop - check for null to avoid ContainsKey errors
296+ $PolicyFound = ($TenantPolicy.Policy.displayName -and $TemplatePolicyLookup.ContainsKey ($TenantPolicy.Policy.displayName )) -or
297+ ($TenantPolicy.Policy.name -and $TemplatePolicyLookup.ContainsKey ($TenantPolicy.Policy.name ))
275298
276299 if (-not $PolicyFound ) {
277300 $PolicyKey = " IntuneTemplates.$ ( $TenantPolicy.Policy.id ) "
@@ -292,16 +315,18 @@ function Get-CIPPDrift {
292315 }
293316 }
294317
318+ # Build hashtable lookup for template CA policies
319+ $TemplateCALookup = @ {}
320+ foreach ($TemplateCAPolicy in $TemplateCATemplates ) {
321+ if ($TemplateCAPolicy.displayName ) {
322+ $TemplateCALookup [$TemplateCAPolicy.displayName ] = $true
323+ }
324+ }
325+
295326 # Check for extra Conditional Access policies not in template
296327 foreach ($TenantCAPolicy in $TenantCAPolicies ) {
297- $PolicyFound = $false
298-
299- foreach ($TemplateCAPolicy in $TemplateCATemplates ) {
300- if ($TemplateCAPolicy.displayName -eq $TenantCAPolicy.displayName ) {
301- $PolicyFound = $true
302- break
303- }
304- }
328+ # Use hashtable lookup instead of nested loop
329+ $PolicyFound = $TemplateCALookup.ContainsKey ($TenantCAPolicy.displayName )
305330
306331 if (-not $PolicyFound ) {
307332 $PolicyKey = " ConditionalAccessTemplates.$ ( $TenantCAPolicy.id ) "
@@ -328,14 +353,39 @@ function Get-CIPPDrift {
328353 $AllDeviations.AddRange ($StandardsDeviations )
329354 $AllDeviations.AddRange ($PolicyDeviations )
330355
331- # Filter deviations by status for counting
332- $NewDeviations = $AllDeviations | Where-Object { $_.Status -eq ' New' }
333- $AcceptedDeviations = $AllDeviations | Where-Object { $_.Status -eq ' Accepted' }
334- $DeniedDeviations = $AllDeviations | Where-Object { $_.Status -like ' Denied*' }
335- $CustomerSpecificDeviations = $AllDeviations | Where-Object { $_.Status -eq ' CustomerSpecific' }
356+ # Single-pass grouping instead of multiple Where-Object filters
357+ $DeviationGroups = @ {
358+ New = [System.Collections.Generic.List [object ]]::new()
359+ Accepted = [System.Collections.Generic.List [object ]]::new()
360+ Denied = [System.Collections.Generic.List [object ]]::new()
361+ CustomerSpecific = [System.Collections.Generic.List [object ]]::new()
362+ Current = [System.Collections.Generic.List [object ]]::new()
363+ }
364+
365+ foreach ($Deviation in $AllDeviations ) {
366+ switch ($Deviation.Status ) {
367+ ' New' {
368+ $DeviationGroups.New.Add ($Deviation )
369+ $DeviationGroups.Current.Add ($Deviation )
370+ }
371+ ' Accepted' {
372+ $DeviationGroups.Accepted.Add ($Deviation )
373+ }
374+ { $_ -like ' Denied*' } {
375+ $DeviationGroups.Denied.Add ($Deviation )
376+ $DeviationGroups.Current.Add ($Deviation )
377+ }
378+ ' CustomerSpecific' {
379+ $DeviationGroups.CustomerSpecific.Add ($Deviation )
380+ }
381+ }
382+ }
336383
337- # Current deviations are New + Denied (not accepted or customer specific)
338- $CurrentDeviations = $AllDeviations | Where-Object { $_.Status -in @ (' New' , ' Denied' ) }
384+ $NewDeviations = $DeviationGroups.New
385+ $AcceptedDeviations = $DeviationGroups.Accepted
386+ $DeniedDeviations = $DeviationGroups.Denied
387+ $CustomerSpecificDeviations = $DeviationGroups.CustomerSpecific
388+ $CurrentDeviations = $DeviationGroups.Current
339389
340390 $Result = [PSCustomObject ]@ {
341391 tenantFilter = $TenantFilter
0 commit comments