I wrote a script to gather Event Log data and posted it here – Quick PowerShell Stuff 17. That script would fail if WinRM or remote PowerShell sessions were not allowed to connect to a Domain Controller for example. What I needed was a more automatic way to fix this as I am now automating my health check data collection process.
Connection Failure Correction
For starters, why are we doing this? Simply put, because sometimes PowerShell cannot connect and errors like this are generated:
“[Server01] Connecting to remote server failed with the following error message : The client cannot connect to the destination specified in the request. Verify that the service on the destination is running and is accepting requests. Consult the logs and documentation for the WS-Management service running on the destination, most commonly IIS or WinRM. If the destination is the WinRM service, run the following command on the destination to analyze and configure the WinRM service: “winrm quickconfig”. For more information, see the about_Remote_Troubleshooting Help topic.
+ CategoryInfo : OpenError: (:) [], PSRemotingTransportException
+ FullyQualifiedErrorId : PSSessionStateBroken”
With an error like this, my data collection for that server is incomplete. How can this be fixed? First, we need to test the connection to the remote server. We can use this test to determine the next step in a script. If the test passes, PowerShell should be able to make a connection and keep moving along the script. If, however, the test fails, we need to create a remediation function, test again and make decisions based on those results.
What test cmdlets exist for PowerShell and WinRM? Luckily, there is a built in PowerShell cmdlets called Test-WSMan and Microsoft has a good web documentation page set up here – Test-WSMan. Using one of the Test-WSMan tests, we can attempt to make a connection to a remote server
Test-WSMan -ComputerName $Server
If the server does not accept remote PowerShell connections, an error like this should occur:
If the connection is good, we should get a result like this:
In order to handle both scenarios, we will use the Test-WSMan cmdlet and pair it with Try/Catch we can catch a failure. A caught failure will result in a variable called $Failed to be set to $True. If this isn’t changed, then $Failed will equal $False.
Try { $Test = Test-WSMan -ComputerName $Server -ErrorAction STOP } Catch { $Failed = $True }
Next we need to enable remote PowerShell. A good write-up on the various ways to do this in presented with this blog article. The method used in the scripting below is the third one mentioned. Basically we are using a utility program called ‘PSExec which is from PSTools (SysInternals) – download it here.
If ($Failed -eq $True) { .\PSExec.exe \\$Server -S WinRM.Cmd QuickConfig -Q }
Now if the $Failed variable is $False, then no action is taken. Now that the change has been made, we should check once more, just in case.
# Reset $Failed variable so we can test once more $Failed = $False # Fourth - Test connection to server with PowerShell - Again! Try { $Test = Test-WSMan -ComputerName $Server -ErrorAction STOP } Catch { $Failed = $True }
Now if the $Failed variable is $True once more, we don’t run the code and use a write-host to notify the admin that the change failed and no code can run due to connection issues. If $Failed is $False however, the code below will connect to the server and check some event log information (just a code sample for illustrative purposes.
If ($Failed -eq $True) { Write-Host "Connections will not work, please fix this manually" -ForegroundColor Yellow } Else { Write-Host "Connection should work now, going to attempt to connect and process the rest of the script." -ForegroundColor Green $Script = { $Server = $Args[0] Get-WinEvent -ListLog "Application" -ComputerName $Server } Invoke-Command -ComputerName $Server -ScriptBlock $Script -Args $Server }
Now that we have that code we can create a script that can correct connection issues and execute remote PowerShell.
Removing the Changes
What about cleanup? the ‘WinRM.Cmd QuickConfig -Q’ command makes a few changes. What if we want those removed? For this section, I won’t go into a lengthy discussion on how to make the changes, nor take the credit for it. A well written article on this already been done – How to undo WinRM changes. The summarized code would look something like this:
Stop-Service WinRM Set-Service -Name WinRM -StartupType Disabled WinRM Delete WinRM/Config/Listener?Address=*+Transport=HTTP Get-NetFirewallRule | ? {$_.Displayname -eq "Windows Remote Management (HTTP-In)"} | Set-NetFirewallRule -Enabled "False" Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name LocalAccountTokenFilterPolicy -Value 0
Fairly simple. Make sure to read the article link prior to the coding as it explains what each line of code is for. Maybe you don’t want to make all the changes listed above. Don’t just copy it blindly!
That’s it for this Quick PowerShell blog article. Hope it helps you out. Please comment below if you have any feedback or requests!