-2

I am currently trying to write a script that takes a list of Computers joined to our domain, iterate through them one at a time to check if they exist in an Access DB that I created, run WMI queries on them collecting their system info, and add that data to the DB if they aren't already in it. I am successfully able to do so on most of the computers (around half), but some of them say RPC server not found.

I know that some of these errors are due to computers being offline (the firewall is disabled and WMI querying is enabled). The problem is that some of the computers are online, and when I run the Get-WmiObject command on them in the script I get that RPC server error, but when I run the command separately outside of the script I am able to successfully query the information. I have posted the function that is causing the weird behavior and was hoping someone with more programming knowledge would find what noob mistake I am making.

The second problem is that after the first iteration I get the error below saying blank CompName field? The first two iterations work as expected then it just throws a bunch of these errors with the "Computer already exists after".

Snippet of Error

function Update-Systems {
    $PSCredential = Get-Credential
    $Comp = (Get-ADComputer -Filter * | select -ExpandProperty Name)

    foreach ($Computer in $Comp) {
        $RecordSet.MoveFirst()
        $RecordSet.Find("CompName = '$Computer'")
        $RecordCheck = $RecordSet.Fields.Item("CompName").Value

        if (!$RecordCheck) {
            "Collecting Data for $Record"
            $SystemProp = Get-WmiObject -Class Win32_ComputerSystem -Credential $PSCredential -ComputerName: $Computer -ErrorAction SilentlyContinue 
            $RecordSet.Addnew()
            $RecordSet.Fields.Item("DateRan") = Get-Date
            $RecordSet.Fields.Item("Domain") = $SystemProp.Domain
            $RecordSet.Fields.Item("CompName") = $SystemProp.Name
            $RecordSet.Fields.Item("Model") = $SystemProp.Model
            $RecordSet.Fields.Item("Manufacturer") = $SystemProp.Manufacturer
            $RecordSet.Update()
        } else {
            "Computer already exists"
        }
    }
}
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
Corey
  • 3
  • 4
  • 5
    don't post images of code. – TrevorBrooks Aug 22 '17 at 20:39
  • [edit] your question to contain the code as text. –  Aug 22 '17 at 20:46
  • 1
    @TrevorBrooks sorry about that, this is my first time posting on StackOverflow. Code isn't much use if you can't copy it..... – Corey Aug 23 '17 at 16:41
  • @lashing What kind of object is $RecordSet? – Paolis Aug 23 '17 at 21:49
  • @Paolis $RecordSet = new-object -ComObject ADODB.Recordset` – Corey Aug 23 '17 at 23:51
  • The errors you posted seem to indicate that the Find method on the $RecordSet is failing because $CompName isn't defined yet for that object. How are you instantiating and populating the $RecordSet? I'm not familiar with how ADBO.RecordSets behave and whether or not if a property is not defined if that is a non-terminating error. – Paolis Aug 24 '17 at 14:00
  • @Paolis thank you for your help but it looks like there was just some null values running around unchecked. After cleaning up the code with some error checking suggested by @Ansgar Wieches I was able to get rid of any errors. I am still having the issue though where `Get-WmiObject` is returning values on a computer if ran as a standalone command in a separate Powershell window, but doesn't work on the same computer in the script....I wonder what could be causing that weird behavior – Corey Aug 25 '17 at 16:23

1 Answers1

0

Most likely Get-WmiObject fails to query information from a remote computer. Since you instructed the cmdlet to just carry on in case of an error (-ErrorAction SilentlyContinue) the variable $SystemProp ends up empty when an error occurs, because of which $SystemProp.Name evaluates to $null as well.

You could work around the issue by assigning $Computer rather than $SystemProp.Name to the recordset, at least as a fallback like this:

$RecordSet.Fields.Item("CompName") = if (-not $SystemProp) {
    $Computer
} else {
    $SystemProp.Name
}

However, a better approach would be to do proper error handling:

$ErrorActionPreference = 'Stop'
try {
    $SystemProp = Get-WmiObject -Class Win32_ComputerSystem -Credential $PSCredential -ComputerName $Computer
    $RecordSet.AddNew()
    $RecordSet.Fields.Item("DateRan")      = Get-Date
    $RecordSet.Fields.Item("Domain")       = $SystemProp.Domain
    $RecordSet.Fields.Item("CompName")     = $SystemProp.Name
    $RecordSet.Fields.Item("Model")        = $SystemProp.Model
    $RecordSet.Fields.Item("Manufacturer") = $SystemProp.Manufacturer
} catch {
    Write-Error $_ -ErrorAction Continue
}

You could also retry a couple times before giving up.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • O.K., after some testing I ended up just doing some checking before executing the `Get-WmiObject` code. The first one checks if `$RecordSet` has a value. If it does it will move the record marker to the beginning of the database then try to find the computer, and if the record check returns null it will try to query the data and add it to the DB. If it fails to query it will say that it was unable to query the info. If it does get the info it will add it to the DB and start the next computer. Thank you all for your help! This got rid of all errors :) – Corey Aug 25 '17 at 16:15