Hello Guys im having trouble trying to figure out how to make this script to work, im very new on scripting but i do understand most of it but still figuring out some things.
try {
Test-Connection -Computername $_ -count 1 -ErrorAction Stop
} catch {
$_.Exception.ErrorCode -eq 0x800706ba
} `
{
$err = 'Unavailable (Host Offline or Firewall)'
}
try {
Test-UserCredentials -Username testuser -Password (Read-Host -AsSecureString)
} catch {
$_.CategoryInfo.Reason -eq 'UnauthorizedAccessException'
} `
{
$err = 'Access denied (Check User Permissions)'
}
Write-Warning "$computer- $err" | Out-File -FilePath c:\temp\Folder\Errors.txt -Append
What im looking for is for this script to test if the system responds or not. If True then next step would be to test credentials, and last would be to perform a get-wmiobject query. But if the system does not respond to ping then i want to catch the hostname that failed to respond ping, capture it and export it to a txt and do the same if the credential fails.
try..catch
is for handling terminating errors. Don't abuse it for status checks by forcing a check to fail hard when it doesn't need to. If you just want to test the availability of a system run Test-Connection
with the parameter -Quiet
as an if
condition:
if (Test-Connection -ComputerName $_ -Count 1 -Quiet) {
...
}
If you need to cascade multiple checks you could do so in a more readable manner by inverting the checks and returning with an appropriate message:
function Test-Multiple {
...
if (-not (Test-Connection -ComputerName $_ -Count 1 -Quiet)) {
return "Host $_ unavailable."
}
$pw = Read-Host -AsSecureString
if (-not (Test-UserCredentials -Username testuser -Password $pw)) {
return 'Login failed for user testuser.'
}
...
}
If you want the information about ping or login failures in log files you can just append it to the respective files:
function Test-Multiple {
...
if (-not (Test-Connection -ComputerName $_ -Count 1 -Quiet)) {
$_ | Add-Content 'C:\path\to\unavailable.log'
return
}
$pw = Read-Host -AsSecureString
if (-not (Test-UserCredentials -Username testuser -Password $pw)) {
$_ | Add-Content 'C:\path\to\login_failure.log'
return
}
...
}
Personally, I can't stand the behavior of Test-Connection
. Throwing an exception when it doesn't successfully ping isn't the behavior I want. Like, ever. I understand why they did it that way, but it's not how I ever want a ping to work. Test-Path
doesn't throw an exception when the path is invalid. It just returns false
. Why is Test-Connection
so unfriendly?
WMI allows you to capture the actual status code, and it also allows you to easily control the timeout so it will function much more quickly.
I tend to use this:
$Ping = Get-WmiObject -Class Win32_PingStatus -Filter "Address='$ComputerName' AND Timeout=1000";
if ($Ping.StatusCode -eq 0) {
# Success
}
else {
# Failure
}
If I actually want to decode the ping status code:
$StatusCodes = @{
[uint32]0 = 'Success';
[uint32]11001 = 'Buffer Too Small';
[uint32]11002 = 'Destination Net Unreachable';
[uint32]11003 = 'Destination Host Unreachable';
[uint32]11004 = 'Destination Protocol Unreachable';
[uint32]11005 = 'Destination Port Unreachable';
[uint32]11006 = 'No Resources';
[uint32]11007 = 'Bad Option';
[uint32]11008 = 'Hardware Error';
[uint32]11009 = 'Packet Too Big';
[uint32]11010 = 'Request Timed Out';
[uint32]11011 = 'Bad Request';
[uint32]11012 = 'Bad Route';
[uint32]11013 = 'TimeToLive Expired Transit';
[uint32]11014 = 'TimeToLive Expired Reassembly';
[uint32]11015 = 'Parameter Problem';
[uint32]11016 = 'Source Quench';
[uint32]11017 = 'Option Too Big';
[uint32]11018 = 'Bad Destination';
[uint32]11032 = 'Negotiating IPSEC';
[uint32]11050 = 'General Failure'
};
$Ping = Get-WmiObject -Class Win32_PingStatus -Filter "Address='$ComputerName' AND Timeout=1000"
$StatusCodes[$Ping.StatusCode];
You could do it like this:
if(Test-Connection -Computername $_ -Count 2 -ErrorAction 0 -Quiet) {
if(-not (Test-UserCredentials -Username testuser -Password (Read-Host -AsSecureString))) {
$err = "Access denied (Check User Permissions)"
}
} else {
$err = "Unavailable (Host Offline or Firewall)"
}
if($err) {
Write-Warning "$computer - $err" | Out-File -FilePath c:\temp\Folder\Errors.txt -Append
}
I believe Test-Connection
and Test-Credentials
are meant to return $true or $false rather than an exception (if properly used), so you don't really need try
/catch
here.
User contributions licensed under CC BY-SA 3.0