Private/Utilities/Test-ModuleVersionConflicts.ps1
function Test-ModuleVersionConflicts { <# .SYNOPSIS Tests for module version conflicts before importing required modules. .DESCRIPTION Checks if any required modules are already loaded with incompatible versions and provides guidance on resolution. This prevents assembly loading conflicts and ensures clean module loading. Can automatically resolve conflicts when requested. .PARAMETER RequiredModuleVersions Hashtable of module names and their required minimum versions. .PARAMETER AutoResolve Automatically attempt to resolve conflicts by removing incompatible modules. .PARAMETER Force Force removal of conflicting modules without confirmation (use with AutoResolve). .EXAMPLE Test-ModuleVersionConflicts -RequiredModuleVersions $script:RequiredModuleVersions .EXAMPLE Test-ModuleVersionConflicts -RequiredModuleVersions $script:RequiredModuleVersions -AutoResolve .OUTPUTS PSCustomObject with conflict information and recommendations #> [CmdletBinding()] param( [Parameter(Mandatory)] [hashtable]$RequiredModuleVersions, [Parameter()] [switch]$AutoResolve, [Parameter()] [switch]$Force ) $result = [PSCustomObject]@{ HasConflicts = $false Conflicts = [System.Collections.ArrayList]::new() Recommendations = [System.Collections.ArrayList]::new() SafeToProceed = $true AutoResolutionAttempted = $false AutoResolutionSuccess = $false ActionsPerformed = [System.Collections.ArrayList]::new() } Write-Verbose "Checking for module version conflicts..." foreach ($moduleName in $RequiredModuleVersions.Keys) { $requiredVersion = [version]$RequiredModuleVersions[$moduleName] # Check if module is currently loaded $loadedModules = Get-Module -Name $moduleName -ErrorAction SilentlyContinue if ($loadedModules) { foreach ($loadedModule in $loadedModules) { $loadedVersion = $loadedModule.Version if ($loadedVersion -lt $requiredVersion) { Write-Verbose "Version conflict detected: $moduleName v$loadedVersion (loaded) < v$requiredVersion (required)" $conflict = [PSCustomObject]@{ ModuleName = $moduleName LoadedVersion = $loadedVersion RequiredVersion = $requiredVersion ConflictType = 'IncompatibleVersion' Severity = 'High' } $null = $result.Conflicts.Add($conflict) $result.HasConflicts = $true $result.SafeToProceed = $false } elseif ($loadedVersion -gt $requiredVersion) { Write-Verbose "Newer version detected: $moduleName v$loadedVersion (loaded) > v$requiredVersion (required)" $conflict = [PSCustomObject]@{ ModuleName = $moduleName LoadedVersion = $loadedVersion RequiredVersion = $requiredVersion ConflictType = 'NewerVersion' Severity = 'Low' } $null = $result.Conflicts.Add($conflict) # Newer versions are usually compatible, so we can proceed } else { Write-Verbose "✓ $moduleName v$loadedVersion matches requirements" } } } } # Generate recommendations based on conflicts if ($result.HasConflicts) { $highSeverityConflicts = $result.Conflicts | Where-Object { $_.Severity -eq 'High' } if ($highSeverityConflicts) { if ($AutoResolve) { Write-Verbose "Auto-resolving module version conflicts..." $result.AutoResolutionAttempted = $true $resolutionSuccess = $true foreach ($conflict in $highSeverityConflicts) { try { Write-Verbose "Removing conflicting module: $($conflict.ModuleName) v$($conflict.LoadedVersion)" Remove-Module $conflict.ModuleName -Force -ErrorAction Stop $null = $result.ActionsPerformed.Add("Removed $($conflict.ModuleName) v$($conflict.LoadedVersion)") Write-Verbose "Successfully removed $($conflict.ModuleName) v$($conflict.LoadedVersion)" } catch { Write-Verbose "Failed to remove $($conflict.ModuleName): $($_.Exception.Message)" $null = $result.ActionsPerformed.Add("Failed to remove $($conflict.ModuleName): $($_.Exception.Message)") $resolutionSuccess = $false } } if ($resolutionSuccess) { $result.AutoResolutionSuccess = $true $result.SafeToProceed = $true $result.HasConflicts = $false Write-Verbose "All conflicts resolved automatically" } else { $null = $result.Recommendations.Add("Some conflicts could not be resolved automatically") $null = $result.Recommendations.Add("Restart PowerShell session to ensure clean module loading") } } else { $null = $result.Recommendations.Add("Remove incompatible module versions using: Remove-Module <ModuleName> -Force") $null = $result.Recommendations.Add("Restart PowerShell session to ensure clean module loading") $null = $result.Recommendations.Add("Re-import PIMActivation module after restart") $null = $result.Recommendations.Add("Or run with -AutoResolve parameter for automatic conflict resolution") # Generate specific commands foreach ($conflict in $highSeverityConflicts) { $null = $result.Recommendations.Add("Remove-Module $($conflict.ModuleName) -Force") } } } $newVersionConflicts = $result.Conflicts | Where-Object { $_.ConflictType -eq 'NewerVersion' } if ($newVersionConflicts) { $null = $result.Recommendations.Add("Newer module versions detected - this is usually safe but may cause compatibility issues") $null = $result.Recommendations.Add("Monitor for any unexpected behavior during PIM operations") } } return $result } |