How to Receive Errors in Test-Connection with -AsJob switch

扶醉桌前 提交于 2019-12-23 05:33:11

问题


I was setting up a monitoring script that would ping IPs and send an email when a packet fails. I decided to use Test-Connection. Below is a sample code:

Code1

$IPList = @("192.168.0.1","172.217.161.15")
Test-Connection -ComputerName $IPList -BufferSize 4 -Count 1 -AsJob -ErrorAction Stop
Get-Job | Wait-Job | Receive-Job

So the result I get is:

Source        Destination     IPV4Address      IPV6Address                              Bytes    Time(ms) 
------        -----------     -----------      -----------                              -----    -------- 
BLR-AA200906  172.217.161.15                                                            4        55       
BLR-AA200906  192.168.0.1                                                               4                 

The 192 series IP is supposed to throw an error. You can see that the Time(ms) column is empty.

Code2

$IPList = @("192.168.0.1","172.217.161.15")
foreach ($IP in $IPList)
{
    Start-job -ScriptBlock {Test-Connection -ComputerName $Args[0] -BufferSize 4 -Count 1 -ErrorAction Stop} -ArgumentList $IP
}
Get-Job | Wait-Job | Receive-Job

If I do this, it will throw an error that I can easily catch

Testing connection to computer '192.168.0.1' failed: Error due to lack of resources
    + CategoryInfo          : ResourceUnavailable: (192.168.0.1:String) [Test-Connection], PingException
    + FullyQualifiedErrorId : TestConnectionException,Microsoft.PowerShell.Commands.TestConnectionCommand
    + PSComputerName        : localhost

The Question

This brings me to my question. How can I receive/catch error messages thrown in Code1? The difference is I am using -AsJob which is much more efficient than spinning up a job in a foreach loop.

PS Version is 5.1


回答1:


It's important to differentiate that your code examples are doing different things, Code1 is spinning up a single job and running x number of test connections. Code2 is spinning up x number of jobs each testing 1 connection.

I'm not aware of a way to get the errors out of test-connection with -asjob, however a different approach would be to use the statuscode attribute. 11010 is the statuscode for Error due to lack of resources which occurrs when test-connection doesn't receive a response from the host, aka Request Timed Out.

The downside to using the statuscode, is that you need to translate the status codes.

$IPList = @("192.168.254.1","172.217.161.15")

$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'
}

Test-Connection -ComputerName $IPList -BufferSize 4 -Count 1 -AsJob
Get-Job | Wait-Job | Receive-Job | ft Address,IPV4Address,IPV6Address,Buffersize,ResponseTime,@{n="Status";e={$StatusCodes[$_.statuscode]}}

This gives the following output

Address        IPV4Address    IPV6Address Buffersize ResponseTime Status           
-------        -----------    ----------- ---------- ------------ ------           
172.217.161.15 172.217.161.15                      4          381 Success          
192.168.254.1                                      4              Request Timed Out

I appreciate this doesn't give you the error messages, but you can check the status of each request and use that to do the business logic you would have done by catching the errors.

References

IcmpSendEcho2 fails with fails with WSA_QOS_ADMISSION_FAILURE and ERROR_NOACCESS

https://docs.microsoft.com/en-gb/windows/desktop/api/ipexport/ns-ipexport-icmp_echo_reply

Powershell - Test-Connection failed due to lack of resources




回答2:


I don't have a particular solution, but this is the cause of your issue:

The -AsJob parameter creates a WMI job, whereas Start-Job creates a CIM job.

WMI jobs will each have their own instance, where as CIM jobs run in your current Powershell instance. Thus, WMI jobs do not take additional time to create and destroy instances using your current session, which can be very costly.

WMI jobs are a bit more detached from Powershell in general. They don't seem to have a "host" shell to transcribe to. This is where the duality of Powershell can get a bit confusing.

Unfortunately, in this case, that means you completely rely on the Test-Connection cmdlet implementing Powershell's event handlers, and it appears that is not the case, since job states always record as 'Completed'. You are no longer able to fall back to the "compatibility" that CIM jobs bring by simply dumping their own shell to the output stream.

Start-Job -ScriptBlock {Write-Host "This is not real output."} | Wait-Job | Receive-Job
PS> This is not real output.

Thus, in your case, if you must use -AsJob, the best you can do is monitor $error. (As far as I can tell.)



来源:https://stackoverflow.com/questions/51542721/how-to-receive-errors-in-test-connection-with-asjob-switch

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!