function Get-ServerConfig { param( [string]$Path = ".\servers.json" ) if (-not (Test-Path $Path)) { throw "Config-Datei nicht gefunden: $Path" } return Get-Content $Path -Raw | ConvertFrom-Json } function Get-ServerGroup { param( [Parameter(Mandatory)] [string]$Name ) $config = Get-ServerConfig if (-not $config.groups.$Name) { throw "Gruppe '$Name' existiert nicht" } return $config.groups.$Name } function Invoke-ServerCommand { param( [Parameter(Mandatory)] [string]$Group, [Parameter(Mandatory)] [scriptblock]$ScriptBlock ) $servers = Get-ServerGroup -Name $Group foreach ($server in $servers) { $name = $server.name Write-Host "[$name] Starte..." -ForegroundColor Cyan try { Invoke-Command -ComputerName $name -ScriptBlock $ScriptBlock -ErrorAction Stop } catch { Write-Warning "[$name] Fehler: $_" } } } function Invoke-ServerCommandParallel { param( [string]$Group, [scriptblock]$ScriptBlock ) $servers = Get-ServerGroup -Name $Group $servers | ForEach-Object -Parallel { $name = $_.name try { Invoke-Command -ComputerName $name -ScriptBlock $using:ScriptBlock } catch { Write-Host "[$name] Fehler: $_" } } } Register-ArgumentCompleter -CommandName Get-ServerGroup, Invoke-ServerCommand -ParameterName Group -ScriptBlock { param($commandName, $parameterName, $wordToComplete) $config = Get-ServerConfig $config.groups.PSObject.Properties.Name | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) } }