Private/System/Invoke-ResourceDisposal.ps1
|
#Requires -Version 5.1 <# .SYNOPSIS Resource Disposal and Cleanup Module for Find-UnknownSID Enterprise Solution .DESCRIPTION Provides focused resource disposal and cleanup functionality including: - Comprehensive resource cleanup operations - IDisposable pattern implementation - Memory manager disposal - Enterprise-grade correlation tracking This module follows the single-responsibility principle by focusing exclusively on resource disposal and cleanup operations. .NOTES Author: Jeffrey Stuhr Blog: https://www.techbyjeff.net LinkedIn: https://www.linkedin.com/in/jeffrey-stuhr-034214aa/ TROUBLESHOOTING: - For disposal issues: .\Troubleshooting\Performance\Resource-Disposal.md - For cleanup problems: .\Troubleshooting\Performance\Resource-Cleanup.md - For performance: .\Troubleshooting\Performance\Performance-Tuning.md .COMPONENT Find-UnknownSID Resource Disposal System .FUNCTIONALITY - Comprehensive resource cleanup - IDisposable pattern implementation - Memory manager disposal - Final garbage collection #> function Invoke-ResourceCleanup { <# .SYNOPSIS Performs comprehensive resource cleanup and disposal .DESCRIPTION Executes enterprise-grade resource cleanup including object disposal, memory cleanup, and resource finalization following community best practices for PowerShell resource management. .PARAMETER MemoryManager MemoryManager instance to dispose .PARAMETER AdditionalResources Additional IDisposable resources to dispose .PARAMETER CorrelationId Correlation identifier for tracking cleanup operations .EXAMPLE PS> Invoke-ResourceCleanup -MemoryManager $memoryManager Disposes memory manager and performs cleanup .EXAMPLE PS> Invoke-ResourceCleanup -MemoryManager $memoryManager -AdditionalResources @($resource1, $resource2) Disposes multiple resources safely .NOTES ENTERPRISE COMPLIANCE: - Follows PowerShell community disposal patterns - Implements defense-in-depth cleanup strategy - Provides comprehensive error handling - Supports correlation tracking for audit trails WHATIF BEHAVIOR: - Resource disposal operations ALWAYS execute regardless of -WhatIf - Only detailed logging operations respect -WhatIf - This ensures critical cleanup is not skipped during simulations #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter()] [AllowNull()] [MemoryManager]$MemoryManager, [Parameter()] [AllowNull()] [System.IDisposable[]]$AdditionalResources, [Parameter()] [string]$CorrelationId = [System.Guid]::NewGuid().ToString() ) begin { # Ensure correlation ID is not empty if (-not $CorrelationId.Trim()) { $CorrelationId = [System.Guid]::NewGuid().ToString() } # Memory management configuration constants $script:MemoryManagementConfig = @{ LogComponent = 'MemoryManagement' } } process { try { # Resource disposal operations always execute - critical for system stability # Only detailed logging respects ShouldProcess if ($PSCmdlet.ShouldProcess("Resources", "Dispose and cleanup")) { Write-StructuredLog "Starting resource cleanup and disposal..." -Level Information -Component $script:MemoryManagementConfig.LogComponent -CorrelationId $CorrelationId } else { Write-Verbose "WhatIf: Would dispose and cleanup resources" Write-StructuredLog "WhatIf simulation: resource disposal would be performed" -Level Debug -Component $script:MemoryManagementConfig.LogComponent -CorrelationId $CorrelationId } # ALWAYS dispose resources - essential for system stability regardless of WhatIf # Dispose additional resources first if ($AdditionalResources) { foreach ($resource in $AdditionalResources) { if ($resource -and $resource -is [System.IDisposable]) { try { $resource.Dispose() if ($PSCmdlet.ShouldProcess("Resources", "Log additional resource disposal")) { Write-StructuredLog "Additional resource disposed successfully" -Level Debug -Component $script:MemoryManagementConfig.LogComponent -CorrelationId $CorrelationId } } catch { Write-StructuredLog "Failed to dispose additional resource: $($_.Exception.Message)" -Level Warning -Component $script:MemoryManagementConfig.LogComponent -CorrelationId $CorrelationId } } } } # Dispose memory manager if ($MemoryManager -and (-not $MemoryManager.Disposed)) { try { $MemoryManager.Dispose() if ($PSCmdlet.ShouldProcess("Resources", "Log memory manager disposal")) { Write-StructuredLog "Memory manager disposed successfully" -Level Information -Component $script:MemoryManagementConfig.LogComponent -CorrelationId $CorrelationId } } catch { Write-StructuredLog "Failed to dispose memory manager: $($_.Exception.Message)" -Level Warning -Component $script:MemoryManagementConfig.LogComponent -CorrelationId $CorrelationId } } # Perform final memory cleanup - always execute try { [System.GC]::Collect() [System.GC]::WaitForPendingFinalizers() [System.GC]::Collect() if ($PSCmdlet.ShouldProcess("Resources", "Log final garbage collection")) { Write-StructuredLog "Final garbage collection completed" -Level Debug -Component $script:MemoryManagementConfig.LogComponent -CorrelationId $CorrelationId } } catch { Write-StructuredLog "Final garbage collection failed: $($_.Exception.Message)" -Level Warning -Component $script:MemoryManagementConfig.LogComponent -CorrelationId $CorrelationId } } catch { Write-StructuredLog "Resource cleanup operation failed: $($_.Exception.Message)" -Level Error -Component $script:MemoryManagementConfig.LogComponent -CorrelationId $CorrelationId Write-Error "Resource cleanup failed: $($_.Exception.Message)" -ErrorAction Stop } } end { Write-StructuredLog "Resource cleanup completed" -Level Information -Component $script:MemoryManagementConfig.LogComponent -CorrelationId $CorrelationId } } # Functions are automatically available when dot-sourced # Note: Export-ModuleMember is only valid in .psm1 module files function Invoke-ResourceDisposal { <# .SYNOPSIS Performs targeted resource disposal operations .DESCRIPTION Executes focused resource disposal for IDisposable objects with comprehensive error handling and logging. .PARAMETER Resources Array of IDisposable resources to dispose .PARAMETER Force Force disposal even if errors occur .PARAMETER CorrelationId Correlation identifier for tracking disposal operations .EXAMPLE PS> Invoke-ResourceDisposal -Resources $disposableObjects Disposes array of resources safely .EXAMPLE PS> Invoke-ResourceDisposal -Resources $fileStream -Force Forces disposal even if errors occur .NOTES This function provides targeted disposal of specific resources and complements the broader Invoke-ResourceCleanup function. #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory = $true)] [AllowEmptyCollection()] [AllowNull()] [object[]]$Resources, [Parameter()] [switch]$Force, [Parameter()] [string]$CorrelationId = [System.Guid]::NewGuid().ToString() ) begin { if (-not $CorrelationId.Trim()) { $CorrelationId = [System.Guid]::NewGuid().ToString() } $disposalResults = @{ TotalResources = $Resources.Count DisposedCount = 0 FailedCount = 0 SkippedCount = 0 Errors = @() } } process { try { if ($PSCmdlet.ShouldProcess("$($Resources.Count) resources", "Dispose")) { Write-StructuredLog "Starting disposal of $($Resources.Count) resources" -Level Information -Component 'ResourceDisposal' -CorrelationId $CorrelationId } foreach ($resource in $Resources) { if ($null -eq $resource) { $disposalResults.SkippedCount++ continue } if ($resource -is [System.IDisposable]) { try { $resource.Dispose() $disposalResults.DisposedCount++ if ($PSCmdlet.ShouldProcess("Resource", "Log disposal")) { Write-StructuredLog "Resource disposed successfully: $($resource.GetType().Name)" -Level Debug -Component 'ResourceDisposal' -CorrelationId $CorrelationId } } catch { $disposalResults.FailedCount++ $disposalResults.Errors += $_.Exception.Message $errorMessage = "Failed to dispose resource $($resource.GetType().Name): $($_.Exception.Message)" Write-StructuredLog $errorMessage -Level Warning -Component 'ResourceDisposal' -CorrelationId $CorrelationId if (-not $Force) { throw } } } else { $disposalResults.SkippedCount++ if ($PSCmdlet.ShouldProcess("Resource", "Log skip")) { Write-StructuredLog "Skipped non-disposable resource: $($resource.GetType().Name)" -Level Debug -Component 'ResourceDisposal' -CorrelationId $CorrelationId } } } return [PSCustomObject]$disposalResults } catch { Write-StructuredLog "Resource disposal operation failed: $($_.Exception.Message)" -Level Error -Component 'ResourceDisposal' -CorrelationId $CorrelationId throw } } end { if ($PSCmdlet.ShouldProcess("Operation", "Log completion")) { Write-StructuredLog "Resource disposal completed. Disposed: $($disposalResults.DisposedCount), Failed: $($disposalResults.FailedCount), Skipped: $($disposalResults.SkippedCount)" -Level Information -Component 'ResourceDisposal' -CorrelationId $CorrelationId } } } |