{"id":3196,"date":"2025-07-02T21:31:22","date_gmt":"2025-07-02T13:31:22","guid":{"rendered":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/?p=3196"},"modified":"2025-07-26T19:49:20","modified_gmt":"2025-07-26T11:49:20","slug":"how-to-ensure-the-test-wsman-cmdlet-doesnt-give-you-false-positives","status":"publish","type":"post","link":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/2025\/07\/02\/how-to-ensure-the-test-wsman-cmdlet-doesnt-give-you-false-positives-3196","title":{"rendered":"How to ensure the Test-WSMan cmdlet doesn&#8217;t give you false positives?"},"content":{"rendered":"\n<p>I was recently creating some <a href=\"https:\/\/www.jhouseconsulting.com\/2025\/06\/21\/the-citrix-virtual-apps-and-desktops-desktops-as-a-service-health-check-script-on-steroids-3181\" target=\"_blank\" rel=\"noreferrer noopener\">health check tests<\/a> that would use both the <a href=\"https:\/\/learn.microsoft.com\/en-us\/powershell\/module\/cimcmdlets\/get-ciminstance\" target=\"_blank\" rel=\"noopener\" title=\"\">Get-CimInstance<\/a> and <a href=\"https:\/\/learn.microsoft.com\/en-us\/powershell\/module\/microsoft.powershell.core\/invoke-command\" target=\"_blank\" rel=\"noopener\" title=\"\">Invoke-Command<\/a> cmdlets. These use the <a href=\"https:\/\/learn.microsoft.com\/en-us\/windows\/win32\/winrm\/portal\" target=\"_blank\" rel=\"noopener\" title=\"\">Windows Remote Management (WinRM)<\/a> protocol. To make the process more efficient I added a function that first tests that WinRM is enabled and healthy on the remote host using the <a href=\"https:\/\/learn.microsoft.com\/en-us\/powershell\/module\/microsoft.wsman.management\/test-wsman\" target=\"_blank\" rel=\"noopener\" title=\"\">Test-WSMan<\/a> cmdlet.<\/p>\n\n\n\n<p>That was working well until I hit a couple of unhealthy machines and received a response from Test-WSMan that provided misleading information. Just by using the basic command line with no other parameters gave me a positive response.<\/p>\n\n\n\n<p><a href=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Test-WSMan-Sick-Machine.png\"><img fetchpriority=\"high\" decoding=\"async\" class=\"aligncenter size-full wp-image-3258\" src=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Test-WSMan-Sick-Machine.png\" alt=\"Test-WSMan Sick Machine\" width=\"659\" height=\"125\" srcset=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Test-WSMan-Sick-Machine.png 659w, https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Test-WSMan-Sick-Machine-300x57.png 300w\" sizes=\"(max-width: 659px) 100vw, 659px\" \/><\/a><\/p>\n\n\n\n<!--more-->\n\n\n\n<p>So if you assume at this point the Test-WSMan cmdlet has returned a positive response, and then proceed to use the Get-CimInstance cmdlet against that machine, you receive an error that leaves you scratching your head.<\/p>\n\n\n\n<p><a href=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Get-CimInstance-Sick-Machine.png\"><img decoding=\"async\" class=\"aligncenter size-large wp-image-3255\" src=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Get-CimInstance-Sick-Machine-680x156.png\" alt=\"Get-CimInstance Sick Machine\" width=\"680\" height=\"156\" srcset=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Get-CimInstance-Sick-Machine-680x156.png 680w, https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Get-CimInstance-Sick-Machine-768x176.png 768w, https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Get-CimInstance-Sick-Machine-300x69.png 300w, https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Get-CimInstance-Sick-Machine.png 1438w\" sizes=\"(max-width: 680px) 100vw, 680px\" \/><\/a><\/p>\n\n\n\n<p>How did Test-WSMan give a positive response and yet Get-CimInstance failed with a Kerberos error?<\/p>\n<p>Well it turns out that Test-WSMan by default sends the request to the remote computer anonymously, without using authentication. If the request is made anonymously, it returns <strong>no <\/strong>information that is specific to the operating-system version. <em>Instead, this cmdlet displays null values for the operating system version and service pack level (OS: 0.0.0 SP: 0.0)<\/em>.<\/p>\n<p>Get-CimInstance is using Kerberos authentication, but Test-WSMan didn&#8217;t test for that, as it just made an anonymous connection. Bad coding!<\/p>\n<p>The trick is to use the the Authentication parameter with the Default value, which will use the authentication method implemented by the WS-Management protocol. When a client computer and a server are both part of the same Active Directory domain (or trusted domains), WinRM defaults to using Kerberos for authentication. So this will fail on Kerberos issues before we even get to the Get-CimInstance cmdlet.<\/p>\n\n\n\n<p><a href=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Test-WSMan-Auth-Default-Sick-Machine.png\"><img decoding=\"async\" class=\"aligncenter size-large wp-image-3257\" src=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Test-WSMan-Auth-Default-Sick-Machine-680x133.png\" alt=\"Test-WSMan Auth Default Sick Machine\" width=\"680\" height=\"133\" srcset=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Test-WSMan-Auth-Default-Sick-Machine-680x133.png 680w, https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Test-WSMan-Auth-Default-Sick-Machine-768x150.png 768w, https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Test-WSMan-Auth-Default-Sick-Machine-1536x300.png 1536w, https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Test-WSMan-Auth-Default-Sick-Machine-300x59.png 300w, https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Test-WSMan-Auth-Default-Sick-Machine.png 1679w\" sizes=\"(max-width: 680px) 100vw, 680px\" \/><\/a><\/p>\n\n\n\n<p>Furthermore, when the Test-WSMan cmdlet is then run against a healthy computer using the Authentication parameter, the operating system version and service pack level are returned.<\/p>\n\n\n\n<p><a href=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Test-WSMan-Auth-Default-Healthy-Machine.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3256\" src=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Test-WSMan-Auth-Default-Healthy-Machine.png\" alt=\"Test-WSMan Auth Default Healthy Machine\" width=\"661\" height=\"132\" srcset=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Test-WSMan-Auth-Default-Healthy-Machine.png 661w, https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2025\/07\/Test-WSMan-Auth-Default-Healthy-Machine-300x60.png 300w\" sizes=\"(max-width: 661px) 100vw, 661px\" \/><\/a><\/p>\n\n\n\n<p>So this is how the Test-WSMan cmdlet should be used by default. Why on earth would Microsoft leave off the authentication by default. I know the documentation states this, but most don&#8217;t read it! It would be better to have it on by default and allow you to set the Authentication parameter value to Anonymous, if you really wanted that behaviour. I can not think of one reason you would ever want to test it anonymously. That doesn&#8217;t make sense to me. I can guarantee that many have used this incorrectly over the years.<\/p>\n<p>I actually wrote a function for that <a href=\"https:\/\/www.jhouseconsulting.com\/2025\/06\/21\/the-citrix-virtual-apps-and-desktops-desktops-as-a-service-health-check-script-on-steroids-3181\" target=\"_blank\" rel=\"noopener\">health check script<\/a> to ensure we get valid output. It simply returns True or False. Try it out!<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: powershell; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\nFunction IsWinRMAccessible {\n  # The Get-CimInstance and Invoke-Command cmdlets uses WinRM, so we test to see if WinRM is enabled and responding correctly.\n  # The Test-WSMan cmdlet submits an identification request that determines whether the WinRM service is running on a local or remote computer.\n  # If the tested computer is running the service, the cmdlet displays the WS-Management identity schema, the protocol version, the product\n  # vendor, and the product version of the tested service. By default the request is sent to the remote computer anonymously, without using\n  # authentication. So we include the Authentication parameter and with the Default value, which will use the authentication method\n  # implemented by the WS-Management protocol. When a client computer and a server are both part of the same Active Directory domain (or\n  # trusted domains), WinRM defaults to using Kerberos for authentication. This will fail on Kerberos issues, for example. This can happen\n  # when there is a missing SPN (Service Principal Name), the computer account has lost its domain trust, etc. Therefore, this test is only\n  # successful if the Test-WSMan cmdlet hasn't returned a null (0.0.0) value for the operating system version.\n  param (&#x5B;string]$hostname)\n  $success = $False\n  try {\n    $output = Test-WSMan -Computername $hostname -Authentication Default -ErrorAction Stop\n    # Verify that Test-WSMan hasn't returned a null (0.0.0) value for the operating system version.\n    If (($output.ProductVersion -split (&quot; &quot;))&#x5B;1] -ne &quot;0.0.0&quot;) {\n      $success = $True\n    }\n  }\n  Catch {\n    #$_.Exception.Message\n  }\n  return $success\n}\n<\/pre><\/div>\n\n\n<p>Hope that helps to demystify the Test-WSMan cmdlet.<\/p>\n<p>Enjoy!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I was recently creating some health check tests that would use both the Get-CimInstance and Invoke-Command cmdlets. These use the Windows Remote Management (WinRM) protocol. To make the process more efficient I added a function that first tests that WinRM is enabled and healthy on the remote host using the Test-WSMan cmdlet. That was working &#8230; <a title=\"How to ensure the Test-WSMan cmdlet doesn&#8217;t give you false positives?\" class=\"read-more\" href=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/2025\/07\/02\/how-to-ensure-the-test-wsman-cmdlet-doesnt-give-you-false-positives-3196\" aria-label=\"Read more about How to ensure the Test-WSMan cmdlet doesn&#8217;t give you false positives?\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[659,5],"tags":[467,840,880,881,281,839,838,835,879,878],"class_list":["post-3196","post","type-post","status-publish","format-standard","hentry","category-powershell","category-scripting","tag-authentication","tag-domain-trust","tag-get-ciminstance","tag-invoke-command","tag-kerberos","tag-service-principal-name","tag-spn","tag-test-wsman","tag-windows-remote-management","tag-winrm"],"aioseo_notices":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts\/3196","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/comments?post=3196"}],"version-history":[{"count":4,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts\/3196\/revisions"}],"predecessor-version":[{"id":3394,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts\/3196\/revisions\/3394"}],"wp:attachment":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/media?parent=3196"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/categories?post=3196"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/tags?post=3196"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}