Best method to check a computer can be successfully reached using WINRM

Darren Rose 496 Reputation points
2021-01-22T17:24:55.67+00:00

I am using PowerShell scripts to do various tasks on remote computers.

PS Remoting is enabled on all computers but sometimes I still get some issues with some where I can't connect- these are normally easily solved by checking computer is not on a public network, firewall rules etc - fixing the connection issue is not the question here.

SOI want a reliable way to check it can be accessed before running rest of my script.

So I firstly test machine is online using Test-Connection - this works okay to exclude any machines offline or not responding.

Then I need to check machine can be accessed via winrm - I tried Test-WSMan but even on some machines I couldn't connect to this came back as being okay - so that is not much use.

For example response from Test-WSMan - all looks okay, and same output I get from working machine:

wsmid : http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd
ProtocolVersion : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
ProductVendor : Microsoft Corporation
ProductVersion : OS: 0.0.0 SP: 0.0 Stack: 3.0

But if now try Invoke-Command on same machine I get error below:-

[Lxxxx] Connecting to remote server Lxxxx failed with the following error message : WinRM cannot process the request. The following error with errorcode 0x80090322 occurred while using Kerberos authentication: An unknown security error occurred. Possible causes are: -The user name or password specified are invalid. -Kerberos is used when no authentication method and no user name are specified. -Kerberos accepts domain user names, but not local user names. -The Service Principal Name (SPN) for the remote computer name and port does not exist. -The client and remote computers are in different domains and there is no trust between the two domains. After checking for the above issues, try the following: -Check the Event Viewer for events related to authentication. -Change the authentication method; add the destination computer to the WinRM TrustedHosts configuration setting or use HTTPS transport. Note that computers in the TrustedHosts list might not be authenticated. -For more information about WinRM configuration, run the following command: winrm help config. For more information, see the about_Remote_Troubleshooting Help topic. + CategoryInfo : OpenError: (Lxxxx:String) [], PSRemotingTransportException + FullyQualifiedErrorId : -2144108387,PSSessionStateBroken

So I have been using the below to check connection, and if response is 1 then it is okay to continue with script, and it it comes back with error then add computer name to $FailedRemoting variable to check later, and skip to next machine in list.

Invoke-Command -ComputerName L21217 { 1 }

Is that the best method, or is there another way I should be checking access via winrm?

Thanks

Windows for business | Windows Server | User experience | PowerShell
0 comments No comments
{count} votes

Accepted answer
  1. Andreas Baumgarten 123.6K Reputation points MVP Volunteer Moderator
    2021-01-22T18:41:10.407+00:00

    You should check $result as well (not tested).

    $result = Invoke-Command -ComputerName FAKEPC { if ($PSVersionTable.SerializationVersion) { 1 } else { 0 } }
    if ($result -eq "1") { 1 } else { 0 }
    

    if $result is equal "1" -> everything looks good
    if $result not equals "1" ("0" or any other value, for instance an error message) -> Something went wrong


    (If the reply was helpful please don't forget to upvote and/or accept as answer, thank you)

    Regards
    Andreas Baumgarten

    1 person found this answer helpful.

2 additional answers

Sort by: Most helpful
  1. Andreas Baumgarten 123.6K Reputation points MVP Volunteer Moderator
    2021-01-22T17:54:19.133+00:00

    In my opinion your last check (check if response is 1) is great and hard to beat:

    • It checks if computer is reachable via network
    • WSMan is configured properly
    • A command is executed on the remote computer

    The only improvement I can think of is running a simple command to check for example the version of PowerShell on the remote computer. Just to test if you get a response of a PowerShell command, not necessarily because of the PS version details.


    (If the reply was helpful please don't forget to upvote and/or accept as answer, thank you)

    Regards
    Andreas Baumgarten

    1 person found this answer helpful.

  2. Rich Matheisen 47,901 Reputation points
    2021-01-22T20:14:25.107+00:00

    One of the failures you noted was related to Kerberos. That's usually not a problem with WinRM but with the credentials used to establish the remote connection.

    You could use something like this to test for connectivity first and then the ability to attempt to establish a WinRM session:

    $portOK = $false
    $allOk = $false
    
    # this is faster than test-connection ot test-netconnection
    Try{
        $tcp = [System.Net.SocketsTcpClient]::New('ws05', 5985)
        $tcp.Close()
        $PortOK = $true
    }
    Catch{
        "Failed to connect on port tcp:5985"
    }
    
    if ($portOK){
        $result = try { 
            Invoke-Command -computer ws05 -scriptblock { 1 } -ErrorAction STOP
        } 
        catch {
            $_
        }
        if ($result -ne 1){
            # do something with these???
            # or just skip whatever would be done on the unreachable machine?
            # depends on how you handle errors
            $result.TargetObject
            $result.FullyQualifiedErrorId
        }
        else{
            $allOk = $true
        }
    }
    if (-not $allOk){
        # failed -- now handle the failure
    }
    

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.