Public/Test-RemotePowerShell.ps1
function Test-RemotePowerShell { <# .SYNOPSIS Displays diagnostic information for a remote PowerShell connection. .DESCRIPTION The Test-RemotePowerShell function displays diagnostic information for a remote PowerShell connection. The output includes the results of DNS lookup, a listing of the remote TCP/IP interface, WinRM port availability and service enablement, PowerShell version, and a confirmation of connection establishment. .EXAMPLE PS C:\PS> Test-RemotePowerShell -Name Server1 Description ----------- This tests the PowerShell capability to remote computer 'Server1'. .EXAMPLE PS C:\PS> Get-ADComputer -Filter * | Test-RemotePowerShell Description ----------- This tests the PowerShell capability to all computers in Active Directory. .PARAMETER Name Specifies the Domain Name System (DNS) name or the IP address of the target computer. .INPUTS System.String or Microsoft.ActiveDirectory.Management.ADComputer .OUTPUTS AsgGroup.TestRemotePowerShell #> #Requires -Version 6.2 [CmdLetBinding()] param ( [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [ValidateNotNullOrEmpty()] [Alias("ComputerName", "Computer", "Server")] [string] $Name ) begin { # Error handling Set-StrictMode -Version "Latest" Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $CallerEA = $ErrorActionPreference $ErrorActionPreference = "Stop" # Error & warning supression parameters $ErrWarnAction = @{ ErrorAction = "SilentlyContinue" WarningAction = "SilentlyContinue" } # Progression status supression $ProgressPreference = "SilentlyContinue" # Local IP address(es) $LocEthAdptr = [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() | Where-Object -FilterScript { $PSItem.OperationalStatus -eq "Up" -and $PSItem.NetworkInterfaceType -eq "Ethernet" } $LocalIPAddr = $LocEthAdptr | ForEach-Object -Process { Write-Output -InputObject $PSItem.GetIPProperties().UnicastAddresses.Address.IPAddressToString } } process { try { if ($Name -eq $env:COMPUTERNAME -or $LocalIPAddr.Contains($Name)) { # Local computer skipped Write-Debug -Message "'$Name' is equivalent to local computer name variable or IP address(es)" Write-Verbose -Message "'$Name' is the local computer" Write-Warning -Message "'$Name' matches the local computer name or IP address(es)" return } # Ping test Write-Debug -Message "Sending IMCP echo request (ping) to '$Name'" Write-Verbose -Message "Testing network connection using ping" $Ping = [System.Net.NetworkInformation.Ping]::new() $PingTest = $Ping.Send($Name) $PingTestStatus = if ($Ping.Send($Name).Status -eq "Success") { Write-Output -InputObject $true } else { Write-Output -InputObject $false } # Remote IP address $RemIPAddr = if ($PingTest) { Write-Debug -Message "Getting remote IP address of '$Name' that responded to ping" Write-Verbose -Message "Getting remote computer IP address" Write-Output -InputObject $PingTest.Address.IPAddressToString } else { Write-Output -InputObject $null } # Windows Remote Management (WinRM) network port test "Testing Windows Remote Management (WinRM) TCP port on '$Name' and supressing errors and warnings" | Write-Debug Write-Verbose -Message "Testing Windows Remote Management (WinRM) TCP port" $TCPTest = Test-Connection -TargetName $Name -TCPPort 5985 # Web Services Management Service (WSMan) test "Testing Web Services Management (WSMan) on '$Name' with errors and warnings supressed" | Write-Debug Write-Verbose -Message "Testing Web Services Management (WSMan) on '$Name'" $WSManTest = if (Test-WSMan -ComputerName $Name @ErrWarnAction) { Write-Output -InputObject $true } else { Write-Output -InputObject $false } # Remote PowerShell version check $PSVerChk = if ($WSManTest) { "Invoking command on '$Name' to get PowerShell version with errors and warnings supressed" | Write-Debug Write-Verbose -Message "Getting PowerShell version on '$Name'" $PS = Invoke-Command -ComputerName $Name -ScriptBlock { $PSVersionTable.PSVersion } @ErrWarnAction if ($PS) { Write-Output -InputObject "$($PS.Major).$($PS.Minor)" } else { Write-Output -InputObject $null } } else { Write-Output -InputObject $null } # Custom object creation $Obj = [pscustomobject]@{ ComputerName = $Name PingSucceeded = $PingTestStatus RemoteIPAddress = $RemIPAddr PortAvailable = $TCPTest WinRMEnabled = $WSManTest Version = $PSVerChk } # Object type name set $Obj.PSObject.TypeNames.Insert(0, "AsgGroup.TestRemotePowerShell") # Object output Write-Output -InputObject $Obj } catch { Write-Error -ErrorRecord $PSItem -ErrorAction $CallerEA } } } |