Public/Set-sqmTcpPort.ps1
|
<# .SYNOPSIS Konfiguriert den TCP-Port einer SQL Server-Instanz ueber die Registry. .DESCRIPTION Setzt den statischen TCP-Port fuer eine SQL Server-Instanz. Der Port wird aus BasePort und PortIncrement berechnet: - Default-Instanz (MSSQLSERVER): Port = BasePort - Named Instance: Port = BasePort + (InstanzNummer * PortIncrement) Die Instanznummer wird aus dem Instanznamen extrahiert wenn moeglich (z.B. INST01 -> 1, INST02 -> 2). Ist keine Zahl im Namen enthalten, wird eine fortlaufende Nummer anhand der Registry-Reihenfolge vergeben. Aenderungen werden erst nach Neustart des SQL Server-Dienstes aktiv. Die Funktion startet den Dienst NICHT automatisch neu. .PARAMETER SqlInstance Name der SQL-Instanz (z.B. "MSSQLSERVER" fuer Default, "INST01" fuer Named Instance). Darf auch als SERVERNAME\INSTANZNAME angegeben werden - der Servername wird ignoriert. .PARAMETER BasePort Basisport. Standard: 1433. .PARAMETER PortIncrement Schrittweite pro Instanz. Standard: 10. .PARAMETER InstanceNumber Optionale explizite Instanznummer (ueberschreibt Auto-Erkennung aus Instanzname). .OUTPUTS [PSCustomObject] mit: SqlInstance : Instanzname Port : Berechneter Port PreviousPort : Port vor der Aenderung Status : AlreadySet | Changed | Error Message : Detailmeldung .EXAMPLE Set-sqmTcpPort -SqlInstance 'MSSQLSERVER' -BasePort 1433 .EXAMPLE Set-sqmTcpPort -SqlInstance 'INST01' -BasePort 1433 -PortIncrement 10 .NOTES Voraussetzungen : Lokale Administratorrechte, SQL Server installiert. Registry-Pfad : HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\ <InstanceRegPath>\MSSQLServer\SuperSocketNetLib\Tcp\IPAll Nach Aenderung muss der SQL Server-Dienst neu gestartet werden. #> function Set-sqmTcpPort { [CmdletBinding()] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory = $true, Position = 0)] [string]$SqlInstance, [Parameter(Mandatory = $false)] [ValidateRange(1024, 65535)] [int]$BasePort = 1433, [Parameter(Mandatory = $false)] [ValidateRange(1, 100)] [int]$PortIncrement = 10, [Parameter(Mandatory = $false)] [ValidateRange(0, 99)] [int]$InstanceNumber = -1 ) $functionName = $MyInvocation.MyCommand.Name # Serverprafix entfernen (SERVERNAME\INST01 -> INST01) if ($SqlInstance -match '\\(.+)$') { $SqlInstance = $Matches[1] } $instanceUpper = $SqlInstance.ToUpper() $result = [PSCustomObject]@{ SqlInstance = $instanceUpper Port = $null PreviousPort = $null Status = 'Error' Message = $null } function _Log { param([string]$Msg, [string]$Level = 'INFO') Write-Verbose "[$functionName] $Msg" try { Invoke-sqmLogging -Message $Msg -FunctionName $functionName -Level $Level } catch { } } try { # --- Instanznummer bestimmen --- if ($InstanceNumber -ge 0) { $instNum = $InstanceNumber } elseif ($instanceUpper -eq 'MSSQLSERVER') { $instNum = 0 } else { # Zahl aus Instanzname extrahieren (INST01 -> 1, SQL02 -> 2) if ($instanceUpper -match '(\d+)$') { $instNum = [int]$Matches[1] } else { # Fallback: Position in der Registry-Liste $instNames = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL' ` -ErrorAction SilentlyContinue).PSObject.Properties | Where-Object { $_.Name -notmatch '^PS' } | Select-Object -ExpandProperty Name $idx = [Array]::IndexOf($instNames, $instanceUpper) $instNum = if ($idx -ge 0) { $idx } else { 1 } } } $targetPort = $BasePort + ($instNum * $PortIncrement) $result.Port = $targetPort _Log "Instanz: $instanceUpper | InstanzNr: $instNum | Zielport: $targetPort" # --- Registry-Pfad ermitteln --- $instanceRegKey = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL' ` -ErrorAction Stop).$instanceUpper if (-not $instanceRegKey) { $result.Message = "Instanz '$instanceUpper' nicht in Registry gefunden." _Log $result.Message 'ERROR' Write-Error $result.Message return $result } $tcpRegPath = "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$instanceRegKey\MSSQLServer\SuperSocketNetLib\Tcp\IPAll" if (-not (Test-Path $tcpRegPath)) { $result.Message = "TCP-Registry-Pfad nicht gefunden: $tcpRegPath" _Log $result.Message 'ERROR' Write-Error $result.Message return $result } # --- Aktuellen Port lesen --- $currentProps = Get-ItemProperty -Path $tcpRegPath -ErrorAction Stop $currentPort = $currentProps.TcpPort $result.PreviousPort = $currentPort _Log "Aktueller Port: '$currentPort' | Zielport: $targetPort" # --- Idempotenz-Pruefung --- if ($currentPort -eq $targetPort.ToString()) { $result.Status = 'AlreadySet' $result.Message = "Port $targetPort ist bereits konfiguriert - keine Aenderung noetig." _Log $result.Message 'INFO' Write-Verbose $result.Message return $result } # --- Port setzen --- Set-ItemProperty -Path $tcpRegPath -Name 'TcpPort' -Value $targetPort.ToString() -ErrorAction Stop Set-ItemProperty -Path $tcpRegPath -Name 'TcpDynamicPorts' -Value '' -ErrorAction Stop $result.Status = 'Changed' $result.Message = "TCP-Port fuer '$instanceUpper' von '$currentPort' auf $targetPort geaendert. " + "Dienst-Neustart erforderlich." _Log $result.Message 'INFO' Write-Host " OK: $($result.Message)" -ForegroundColor Green } catch { $result.Message = "Fehler beim Setzen des TCP-Ports: $($_.Exception.Message)" _Log $result.Message 'ERROR' Write-Error $result.Message } return $result } |