Forum Discussion
Write-Host AND output results to text file.
- May 03, 2022
It does a ping/icmp test to the computers listed in the computers.txt file, if the firewall is active.. It won't return the request marking the computer inaccessible. You could try to use Test-Path "\\$($computer)\c$" instead of test-connection -computername.. (Run this as an account who has local admin priviledges on the remote machine, Domain Admin of Global Admin/Device Administator? Also, shouldn't invoke-command -computername (get-content -Path .\computers.txt) be invoke-command -computername $computer ?
Harm_Veenstra wrote:... Also, shouldn't invoke-command -computername (get-content -Path .\computers.txt) be invoke-command -computername $computer ?
As a quick explainer: no, this is fine.
-Computer takes a string array, not a string, as an input, meaning this is perfectly fine if the input file contains one computer name per line. Of course, implicit conversion means a string is fine, too (i.e. an explicit type cast isn't required.)
Cheers,
Lain
- LainRobertsonMay 04, 2022Silver Contributor
You're quite right, actually. I'd only read your comment and zeroed in on that statement, however, I'd read it out of context and therefore missed the point entirely.
Having read the question now, you're bang-on with your statement.
Probably the only other thing I'd add though is that I wouldn't go with the foreach approach at all since it won't scale well where there's a significant number of clients to update. Rather, I'd retain the Invoke-Command at the outer-most level while shifting the reporting logic to within the -ScriptBlock.
The issue with the foreach being the outer-most control is that it's a synchronous process, meaning one computer is processed after another. Conversely, Invoke-Command can process the ScriptBlock in parallel up to the limit specified in -ThrottleLimit (or 32 if -ThrottleLimit isn't specified.)
I wouldn't bother with the Test-Connection (or Test-NetConnection) at all, if I'm being honest, since the native exception is useful to know - given the cause can vary. But if I was going to handle it in a custom manner, I'd actually use -ErrorVariable to generate a consumable object since that's something you can pipe to a file (the current behaviour in this thread) and/or use in downstream processing (i.e. has more utilitarian value.)
Translating my waffling into code, my personal preference would result in something like this.
$RemoteErrors = $null; Invoke-Command -ComputerName (Get-Content -Path .\computers.txt) -ArgumentList (Get-Content -Path .\users.txt) -ErrorVariable +RemoteErrors -ScriptBlock { $args | Remove-LocalGroupMember -Group "Administrators" -ErrorAction:SilentlyContinue; } $Summary = $RemoteErrors | Foreach-Object { [PSCustomObject]@{ Server = $_.CategoryInfo.TargetName; Status = "Failed"; } }; $Summary; $Summary | Out-File -FilePath "<somepath>";
This will scale out much better than foreach and provides the failed hosts as objects rather than just static text. You can also then include the failure reason (in the hashtable section on lines 9 and 10), too, if so desired.
Anyhow, horses for courses. It's not a complex requirement meaning this may just be overkill on my part. If it's a small list of computers, this probably isn't adding anything useful.
Cheers,
Lain
Edited to include the output to file (and then a spelling mistake afterwards - not my day.)