Private/Get-ProcessedCommands.ps1
function Get-ProcessedCommands { <# .SYNOPSIS Processes module commands in parallel to extract detailed information. #> [CmdletBinding()] [OutputType([PSCustomObject[]])] param( [Parameter(Mandatory)] [ValidateNotNull()] $Commands, [Parameter(Mandatory)] [string]$ModuleName, [Parameter(Mandatory)] $Module, [Parameter()] [int]$MaxConcurrentJobs = 8, [Parameter()] [switch]$SkipProgressBar ) # Define script block for parallel processing $processCommandScript = { param($CommandName, $ModuleName) try { # Import the module in this job context Import-Module $ModuleName -ErrorAction SilentlyContinue # Get command object $command = Get-Command -Name $CommandName -ErrorAction SilentlyContinue if (-not $command) { throw "Command not found: $CommandName" } # Get help information $help = Get-Help $CommandName -Full -ErrorAction SilentlyContinue # Build command info object $commandInfo = [PSCustomObject]@{ Name = $command.Name CommandType = $command.CommandType.ToString() Module = $command.ModuleName Version = "Unknown" Synopsis = if ($help.Synopsis) { $help.Synopsis.Trim() } else { "No synopsis available" } Description = if ($help.Description) { ($help.Description | ForEach-Object { $_.Text }) -join "`n" } else { "No description available" } Syntax = if ($help.Syntax) { ($help.Syntax.SyntaxItem | ForEach-Object { $_.ToString() }) } else { @() } Parameters = @() Examples = @() Notes = if ($help.AlertSet) { ($help.AlertSet | ForEach-Object { $_.Alert.Text }) -join "`n" } else { "" } RelatedLinks = if ($help.RelatedLinks) { ($help.RelatedLinks.NavigationLink | ForEach-Object { $_.Uri }) } else { @() } OutputType = if ($command.OutputType) { $command.OutputType.Name } else { @() } ProcessingError = $null } # Process parameters if ($help.Parameters -and $help.Parameters.Parameter) { foreach ($param in $help.Parameters.Parameter) { $paramInfo = [PSCustomObject]@{ Name = $param.Name Type = $param.Type.Name Required = $param.Required -eq $true Position = $param.Position DefaultValue = $param.DefaultValue AcceptsPipelineInput = $param.PipelineInput -ne "false" Description = if ($param.Description) { ($param.Description | ForEach-Object { $_.Text }) -join " " } else { "" } } $commandInfo.Parameters += $paramInfo } } # Process examples if ($help.Examples -and $help.Examples.Example) { foreach ($example in $help.Examples.Example) { $exampleInfo = [PSCustomObject]@{ Title = if ($example.Title) { $example.Title.Trim() } else { "Example" } Code = if ($example.Code) { $example.Code.Trim() } else { "" } Remarks = if ($example.Remarks) { ($example.Remarks | ForEach-Object { $_.Text }) -join "`n" } else { "" } } $commandInfo.Examples += $exampleInfo } } return $commandInfo } catch { # Return error info for failed commands return [PSCustomObject]@{ Name = $CommandName CommandType = "Unknown" Module = $ModuleName Version = "Unknown" Synopsis = "Error retrieving help information" Description = "Error retrieving help information" Syntax = @() Parameters = @() Examples = @() Notes = "" RelatedLinks = @() OutputType = @() ProcessingError = $_.Exception.Message } } } # Process commands in parallel batches $commandDetails = [List[PSCustomObject]]::new() $totalCommands = $Commands.Count $processedCount = 0 # Split commands into batches $batchSize = [Math]::Min($MaxConcurrentJobs, $totalCommands) $batches = for ($i = 0; $i -lt $totalCommands; $i += $batchSize) { $endIndex = [Math]::Min($i + $batchSize - 1, $totalCommands - 1) $Commands[$i..$endIndex] } foreach ($batch in $batches) { if (-not $SkipProgressBar) { Write-Progress -Activity "Processing Commands" ` -Status "Processing batch of $($batch.Count) commands" ` -PercentComplete (($processedCount / $totalCommands) * 100) } # Start jobs for this batch $jobs = foreach ($command in $batch) { Start-Job -ScriptBlock $processCommandScript -ArgumentList $command.Name, $ModuleName } # Wait for jobs with timeout $timeout = 120 # 2 minutes per batch $null = Wait-Job -Job $jobs -Timeout $timeout # Collect results foreach ($job in $jobs) { try { if ($job.State -eq "Completed") { $result = Receive-Job -Job $job -ErrorAction SilentlyContinue if ($result) { # Update version info if ($result.PSObject.Properties.Name -contains 'Version') { $result.Version = $Module.Version.ToString() } $commandDetails.Add($result) } } else { Write-Warning "Job failed or timed out for command processing" $commandDetails.Add([PSCustomObject]@{ Name = "Unknown" CommandType = "Unknown" Module = $ModuleName Version = $Module.Version.ToString() Synopsis = "Job processing failed or timed out" Description = "Job processing failed or timed out" Syntax = @() Parameters = @() Examples = @() Notes = "" RelatedLinks = @() OutputType = @() ProcessingError = "Job timeout or failure" }) } } catch { Write-Warning "Error receiving job results: $_" } finally { Remove-Job -Job $job -Force -ErrorAction SilentlyContinue } } $processedCount += $batch.Count } if (-not $SkipProgressBar) { Write-Progress -Activity "Processing Commands" -Completed } # Sort and return results return $commandDetails.ToArray() | Sort-Object Name } |