0

I'm having issue with a script I've written and would love some help. Please note I'm very new to powershell.

I've written a script that uses a txt file that contains remote computers on a domain, I appears to be working to some degree but in the event of a machine being offline I get errors which then loop the script.

$machines
$pcname
Name = 'Machine'
Expression = { $_.PsComputerName }
}

ForEach ($System in $Machines)
{
    #Pings machine's found in text file
    if (!(test-Connection -ComputerName $System -BufferSize 16 -Count 1 -ea 0 -Quiet))
    {
        Write-Output "$System Offline"
    }

Else
   {
     #Providing the machine is reachable 
     #Checks installed programs for products that contain Kaspersky in the name
     gwmi win32_product -Filter {Name like "%Kaspersky%"} -ComputerName $Machines | Select-Object -Property $pcname,Name,Version
   }
}

At present this runs and output's like so:

Machine          Name                                        Version
UKTEST01         Kaspersky Security Center Network Agent     10.1.249 
UKTEST02         Kaspersky Endpoint Security 10 for Windows  10.2.1.23

But in the event of a machine not being reachable the following error is given:

gwmi : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At C:\Scripts\Powershell\Kaspersky Endpoint Security 10\Script\New folder\Kaspersky Checker working v2.ps1:15 char:9
+         gwmi win32_product -Filter {Name like "%Kaspersky%"} -ComputerName   $Mach ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidOperation: (:) [Get-WmiObject], COMException
+ FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

And then moves to the next machine in the list, and then repeats from the beginning again.

I'd like for this to simply show as:

UKTEST03 Offline

And stop once the last machine in the txt file is done.

Any help or advise would be greatly appreciated.

2 Answers 2

1

This is the perfect time to use a Try/Catch/Finally block. The flow is this : Try the block of code here, if you encounter an error, suppress the message and do what is in the Catch block instead.

I've modified your code a bit, so simply copy this whole code block and drop it in, replacing your Else {scriptblock} in your original code.

Else
{
 #Providing the machine is reachable 
 #Checks installed programs for products that contain Kaspersky in the name
 Try {Get-WMIObject -Class win32_product -Filter {Name like "%Kaspersky%"} `
   -ComputerName $Machines -ErrorAction STOP | 
      Select-Object -Property $pcname,Name,Version }
 Catch {#If an error, do this instead
        Write-Output "$system Offline }
  }
}

Your completed answer

I've folded in the change you requested, to keep your script from running on every machine in $machines instead of $system, as you likely intended.

ForEach ($System in $Machines){
    #Pings machine's found in text file
    if (!(test-Connection -ComputerName $System -BufferSize 16 -Count 1 -ea 0 -Quiet))
    {
        Write-Output "$System Offline"
    }
    Else
    {
     #Providing the machine is reachable 
     #Checks installed programs for products that contain Kaspersky in the name
     Try {Get-WMIObject -Class win32_product -Filter {Name like "%Kaspersky%"} `
       -ComputerName $System -ErrorAction STOP | 
          Select-Object -Property $pcname,Name,Version }
     Catch {#If an error, do this instead
            Write-Output "$system Offline "}
     #EndofElse
     }
#EndofForEach
}
Sign up to request clarification or add additional context in comments.

5 Comments

Massive help, using a Try and Catch has stopped the error, however i'm still having the problem with it starting the script from the beginning once it reaches an offline machine.
By the look of it, it's reaching a machine that is offline and then states the first machine in the text file is the one that is offline, opposed to it using the name from the text file.
You're having that problem because of the way your loop is constucted. Your loop says, For Each machine, if the machine is offline write "Machine OFFLINE". If the machine is not offline, your code says run Get-WMIObject on every single $machine, where it should be $system instead. I'll update my example with the correct solution for you.
There you go, updated my example to fix the issue of $machines being used where $system should have been, and added demarcations of the #EndOfElse and #EndofForEach locations, to make it easier to understand what the close brackets are doing.
That makes much more sense and would explain why it looped like that, It's pulling the results as expected now. You've helped a lot and I very much doubt i'll make the same mistake! Thanks
1

You could try this:

$machines=... # your machines' names
foreach ($machine in $machines)
{
    trap{"$machine`: not reachable or not running WsMan";continue}
    if(test-wsman -ComputerName $machine -ea stop){
        gcim -Class CIM_Product -Filter 'Name like "%Kaspersky%"' |
            select pscomputername,name,version
    }
}

I'm using gcim because gwmi is deprecated.

Correction: the correct name is Kaspersky; I corrected it.

3 Comments

Thank you so much, I was initially running this on a Windows 2008 server but upon copying the script to a region that used Windows 2012 I found it was failing and couldn't figure out why.
I'm running this script on a large number of machines in 10 different regions as well, so i'll try and get it refer to the text file again. Huge Help
You tagged your question as PowerShell version 4.0 only, so you shouldn't be using Windows Server 2012, because it does not use PowerShell version 4.0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.