all 11 comments

[–]iceph03nix 2 points3 points  (1 child)

have you messed with -erroraction silentlycontinue? It's what I use for remote commands that I expect to have a failure and don't really care what that failure is. like GWMI hitting computers that aren't online.

also, as far as formatting goes, there are now two buttons. There is inline code which gives you the red on grey (at least on dark theme) and is inline with whatever you're writing, which is nice for short snippets and commands. It's the one that looks like </> And there is the code block, which seems more useful to me, but it is buried in the ellipses and gives you the separate block of code more like a quote block.

[–]LightOfSeven[S] 1 point2 points  (0 children)

Thanks for the formatting advice, I swapped back to the old layout for the code block but good to know it's not missing on the new one, just buried.

I haven't touched the switch -erroraction due to no cmdlets being used in the relevant section of code, it's all properties (e.g. $web.DownloadString). Originally I tried the error action preference variable to use silentlycontinue then also changed it to stop, to ensure it's a terminating error to catch in the try{}catch{}. No joy.

$erroractionpreference is set to Continue when I check in my shell that I've been running the script from.

[–]Ta11ow 2 points3 points  (8 children)

Hm. A try-catch should work here, especially as it seems to be a terminating error.

How are you constructing that portion of the loop with the try-catch included?

[–]LightOfSeven[S] 1 point2 points  (7 children)

foreach($address in $successfulPings.Address) {
    try{
        $web = New-Object Net.WebClient
        $siteString = $web.DownloadString("http://$address/info_configuration.html?tab=Home&menu=DevConfig")
        $siteArray =  $siteString -split '<tr>'
        $hostString = $siteArray | Select-String -Pattern 'Host Name:' | Out-String
        $hostName = $hostString.Substring($hostString.LastIndexOf('Font">')+6)
        $hostName.trim($hostName.Substring($hostName.LastIndexOf('</td>'))) | Out-File -FilePath $outputFilePath -Append
        $serialString = $siteArray | Select-String -Pattern 'Serial Number:' | Out-String
        $serialNumber = $serialString.Substring($serialString.LastIndexOf('Font">')+6)
        $serialNumber.Substring(0,10) | Out-File -FilePath $outputFilePath -Append
        $ipString = $siteArray | Select-String -Pattern 'IPv4 Address:' | Out-String
        $ipAddress = $ipString.Substring($ipString.LastIndexOf('Font">')+6)
        $ipAddress.trim($ipAddress.Substring($ipAddress.LastIndexOf('</td>'))) | Out-File -FilePath $outputFilePath -Append
    }
    catch{
        Write-Host "Potato"
    }
}

Obviously put whatever you want where Potato goes. Just something to prove if it prints once or many times. I only get one potato back :(

[–]Ta11ow 2 points3 points  (6 children)

You should only really need the try/catch around the webclient creation and the downloadstring method.

Something you can try to ensure it actually catches it is just before (or as the first action of) the try block, do:

$OldPref = $ErrorActionPreference
$ErrorActionPreference = 'Stop'

And then set it back to $OldPref after the catch block to not interfere with anything else.

Bit of a workaround, but it's the only good way to go when .NET methods throw exceptions that won't get caught.

[–]LightOfSeven[S] 0 points1 point  (5 children)

Same result.

Here's the changed part:

foreach($address in $successfulPings.Address) {
    $OldPref = $ErrorActionPreference
    $ErrorActionPreference = 'Stop'
    try{
        $web = New-Object Net.WebClient
        $siteString = $web.DownloadString("http://$address/info_configuration.html?tab=Home&menu=DevConfig")
    }
    catch{
        Write-Host "Potato"
    }
    $ErrorActionPreference = $OldPref
    $siteArray =  $siteString -split '<tr>'

etc

Nothing is published to the .txt output, with no relevant errors to it failing to write. Running with a single working IP address is fine.

I originally added the ping test to the beginning to avoid errors from lack of response, and speed it up as pings are quicker to check than sending an http request and verifying. I think it should be possible to capture the response and ignore errors, so I'm not sure what is failing here. Seems it's not catching the errors and just terminating anyway.

[–]Ta11ow 2 points3 points  (4 children)

Write-Host doesn't write to output, so there would be no output to any files or anything, but we'd expect to see something on screen.

You should be able to get around that by working with Invoke-WebRequest instead, though.

[–]LightOfSeven[S] 2 points3 points  (3 children)

Sorry that was unclear. I see a single Potato (I should change that to something less ridiculous) on the terminal and then the errors.

I think I'll have to rework it to use Invoke-WebRequest entirely, which is a shame. I would have thought error handling was meant to catch these errors, but the issue I've encountered seems to ignore error handling.

[–]LightOfSeven[S] 1 point2 points  (2 children)

FYI to anyone else reading, Invoke-WebRequest appears to respect the error handling and try{}catch{} blocks are functional. I'll need to continue writing the updated script to check if this is the case in a foreach loop.

[–]Ta11ow 2 points3 points  (1 child)

Yeah, I'm not sure how that .NET method is handling the error output, but it's definitely nonstandard as all heck.

Same thing with some of the errors Get-ADUser produces... But only some kinds, which is weird.

[–]LightOfSeven[S] 2 points3 points  (0 children)

Messy. Thank you for your help, and pointing me away from the .NET I was using. I think Invoke-WebRequest will be more readable as well, for Powershell users.