Gregory Motyka
Gregory Motyka

Reputation: 21

PowerShell Set-ADComputer description based on the input

I have a code which runs trough Active Directory computers objects to collect information. Part of that information is then updated on Active directory description field. My problem is that when I get the Exception.Message the AD object of a computer is still updated with the last found computer information. I would like to find out how can I:

Attached is the script I'm using but can't figure out where to put the output for the two Set-ADComputer statements

    # Getting computers from Active Directory
    $Computers = Get-ADComputer -Filter {Enabled -eq $true} | select -expand name
    Foreach($computer in $computers)
    # Checking if the computer is Online      
    {
    if(!(Test-Connection -ComputerName $computer -BufferSize 16 -Count 1 -ea 0 -quiet))
    {write-host "Cannot reach $Computer is offline" -ForegroundColor red}
       else {
    $Output = @()
    Try{
    $xx = Get-WmiObject win32_computersystem -ComputerName $Computer -ErrorAction Stop
    $in = Get-WmiObject Win32_OperatingSystem -ComputerName $Computer -ErrorAction Stop
    $mc = Get-WmiObject -class Win32_NetworkAdapterConfiguration -Filter "IPEnabled='True'" -ComputerName $Computer -ErrorAction Stop
    $sr = Get-WmiObject win32_bios -ComputerName $Computer -ErrorAction Stop
    $Xr = Get-WmiObject –class Win32_processor -ComputerName $Computer -ErrorAction Stop 
    $ld = Get-ADComputer $Computer -properties Name,Lastlogondate,ipv4Address,enabled,description,DistinguishedName -ErrorAction Stop
    $r = "{0} GB" -f ((Get-WmiObject Win32_PhysicalMemory -ComputerName $Computer -ErrorAction Stop | Measure-Object Capacity  -Sum).Sum / 1GB)
    $x = Get-WmiObject win32_computersystem -ComputerName $Computer -ErrorAction Stop | select @{Name = "Type";Expression = {if (($_.pcsystemtype -eq '2')  )
    {'Laptop'} Else {'Desktop Or Other'}}},Manufacturer,@{Name = "Model";Expression = {if (($_.model -eq "$null")  ) {'Virtual'} Else {$_.model}}},username
    $t= New-Object PSObject -Property @{
    SerialNumber = $sr.serialnumber -replace "-.*"
    Computername = $ld.name
    IPaddress = $ld.ipv4Address
    MACaddress = $mc.MACAddress
    Enabled = $ld.Enabled
    Description = $ld.description
    OU = $ld.DistinguishedName.split(',')[1].split('=')[1] 
    DC = $xx.domain
    Type = $x.type
    Manufacturer = $x.Manufacturer
    Model = $x.Model
    RAM = $R
    ProcessorName = ($xr.name | Out-String).Trim()
    NumberOfCores = ($xr.NumberOfCores | Out-String).Trim()
    NumberOfLogicalProcessors = ($xr.NumberOfLogicalProcessors | Out-String).Trim()
    Addresswidth = ($xr.Addresswidth | Out-String).Trim()
    Operatingsystem = $in.caption
    InstallDate = ([WMI] '').ConvertToDateTime($in.installDate)
    LastLogonDate = $ld.lastlogondate
    LoggedinUser = $x.username
    }
    $Output += $t
    }
    Catch [Exception]
    {
    $ErrorMessage = $_.Exception.Message
    Add-Content -value "$Computer, $ErrorMessage, skipping to next" $txt
    Set-ADComputer $Computer -Description $ErrorMessage
    }
    }
    # Output file location to be chnaged as needed
    $file="C:\scripts\reports\AD-Inentory_$((Get-Date).ToString('MM-dd-yyyy')).csv"
    $txt="c:\scripts\reports\AD-Inentory-error_$((Get-Date).ToString('MM-dd-yyyy')).txt"
    $desc="$($mc.MACAddress) ( $($sr.serialnumber -replace "-.*") ) $($x.Model) | $((Get-Date).ToString('MM-dd-yyyy'))"
    # Properties to be included in the output file
    $Output | select Computername,Enabled,Description,IPaddress,MACaddress,OU,DC,Type,SerialNumber,Manufacturer,Model,RAM,ProcessorName,NumberOfCores,NumberOfLogicalProcessors,Addresswidth,Operatingsystem,InstallDate,LoggedinUser,LastLogonDate | export-csv -Append $file -NoTypeInformation 
    Set-ADComputer $Computer -Description $desc -verbose
    }

Upvotes: 2

Views: 3338

Answers (2)

Gregory Motyka
Gregory Motyka

Reputation: 21

After looking at the suggestion to include continue statement I was able to achieve the solution to my problem with the following final script:

# Output file location to be changed as needed
$file="C:\scripts\reports\AD-Inentory_$((Get-Date).ToString('MM-dd-yyyy')).csv"
$txt="c:\scripts\reports\AD-Inentory-error_$((Get-Date).ToString('MM-dd-yyyy')).txt"

# Getting computers from Active Directory
$Computers = Get-ADComputer -Filter {Enabled -eq $true} | select -expand name

  Foreach($computer in $computers){

if(!(Test-Connection -ComputerName $computer -BufferSize 16 -Count 1 -ea 0 -quiet))
 {
 write-host "Cannot reach $Computer is offline" -ForegroundColor red
 }
 else
 {

$Output = @()

    Try
    {
        $xx = Get-WmiObject win32_computersystem -ComputerName $Computer -ErrorAction Stop
        $in = Get-WmiObject Win32_OperatingSystem -ComputerName $Computer -ErrorAction Stop
        $mc = Get-WmiObject -class Win32_NetworkAdapterConfiguration -Filter "IPEnabled='True'" -ComputerName $Computer -ErrorAction Stop
        $sr = Get-WmiObject win32_bios -ComputerName $Computer -ErrorAction Stop
        $Xr = Get-WmiObject –class Win32_processor -ComputerName $Computer -ErrorAction Stop 
        $ld = Get-ADComputer $Computer -properties Name,Lastlogondate,ipv4Address,enabled,description,DistinguishedName -ErrorAction Stop
        $r = "{0} GB" -f ((Get-WmiObject Win32_PhysicalMemory -ComputerName $Computer -ErrorAction Stop | Measure-Object Capacity  -Sum).Sum / 1GB)
        $x = Get-WmiObject win32_computersystem -ComputerName $Computer -ErrorAction Stop | select @{Name = "Type";Expression = {if (($_.pcsystemtype -eq '2')  )
            {'Laptop'} Else {'Desktop Or Other'}}
        },Manufacturer,@{Name = "Model";Expression = {if (($_.model -eq "$null")  ) {'Virtual'} Else {$_.model}}},username

        ## Output on creation
        $t= New-Object PSObject -Property @{
            SerialNumber              = $sr.serialnumber -replace "-.*"
            Computername              = $ld.name
            IPaddress                 = $ld.ipv4Address
            MACaddress                = $mc.MACAddress
            Enabled                   = $ld.Enabled
            Description               = $ld.description
            OU                        = $ld.DistinguishedName.split(',')[1].split('=')[1] 
            DC                        = $xx.domain
            Type                      = $x.type
            Manufacturer              = $x.Manufacturer
            Model                     = $x.Model
            RAM                       = $R
            ProcessorName             = ($xr.name | Out-String).Trim()
            NumberOfCores             = ($xr.NumberOfCores | Out-String).Trim()
            NumberOfLogicalProcessors = ($xr.NumberOfLogicalProcessors | Out-String).Trim()
            Addresswidth              = ($xr.Addresswidth | Out-String).Trim()
            Operatingsystem           = $in.caption
            InstallDate               = ([WMI] '').ConvertToDateTime($in.installDate)
            LastLogonDate             = $ld.lastlogondate
            LoggedinUser              = $x.username
        }

        # Only do this kind of update if it hasn't failed yet
        $Output += $t
        $desc="$($mc.MACAddress) ( $($sr.serialnumber -replace "-.*") ) $($x.Model) | $((Get-Date).ToString('MM-dd-yyyy'))"
        Set-ADComputer $Computer -Description $desc -verbose
        $Output | select Computername,Enabled,Description,IPaddress,MACaddress,OU,DC,Type,SerialNumber,Manufacturer,Model,RAM,ProcessorName,NumberOfCores,NumberOfLogicalProcessors,Addresswidth,Operatingsystem,InstallDate,LoggedinUser,LastLogonDate | export-csv -Append $file -NoTypeInformation 

    }
    Catch [Exception]
    {
    # Only do this kind of update if it has failed
        $ErrorMessage = $_.Exception.Message
        Add-Content -value "$Computer, $ErrorMessage, skipping to next" $txt
        Set-ADComputer $Computer -Description $ErrorMessage
            continue
    }
  }
}

Upvotes: 0

jkdba
jkdba

Reputation: 2509

It looks like the reason why it had the problem behaviour is it was catching the error, and setting the description as you wanted with the error.

However it would then continue on to evaluate the code outside of the catch and the else block, since it failed on the current computer the variables used to build the description variable still contained data from the previous computer that was successful and then update the failed computer again.

You could fix this by using the continue statement at the bottom of the catch block to skip the rest of the code for that iteration and move to the next item in the loop.

That solution would look like this:

Catch [Exception]
{
    $ErrorMessage = $_.Exception.Message
    Add-Content -value "$Computer, $ErrorMessage, skipping to next" $txt
    Set-ADComputer $Computer -Description $ErrorMessage
    ## add continue statement here
    continue
}

continue statement documentation here and examples here.

The other option is you restructure your code to make sure this cannot happen, like below.

I think this will fix your issue and do what you are trying to achieve. I put comments in the code around the changes I made (denoted by the ##) feel free to ask questions.

I would recommend you use more descriptive variable names.

## No Need to define these in the foreach loop
# Output file location to be chnaged as needed
$file = "C:\scripts\reports\AD-Inentory_$((Get-Date).ToString('MM-dd-yyyy')).csv"
$txt = "c:\scripts\reports\AD-Inentory-error_$((Get-Date).ToString('MM-dd-yyyy')).txt"

# Getting computers from Active Directory

## Update to use pipeline
Get-ADComputer -Filter {Enabled -eq $true} | Foreach-Object {

    $computer = $_.Name

    if(!(Test-Connection -ComputerName $computer -BufferSize 16 -Count 1 -ea 0 -quiet))
    {
        write-host "Cannot reach $Computer is offline" -ForegroundColor red
    }
    else
    {
        Try
        {
            ## No Longer Need this because we are uisng the pipe line
            #$Output = @()

            $xx = Get-WmiObject win32_computersystem -ComputerName $Computer -ErrorAction Stop
            $in = Get-WmiObject Win32_OperatingSystem -ComputerName $Computer -ErrorAction Stop
            $mc = Get-WmiObject -class Win32_NetworkAdapterConfiguration -Filter "IPEnabled='True'" -ComputerName $Computer -ErrorAction Stop
            $sr = Get-WmiObject win32_bios -ComputerName $Computer -ErrorAction Stop
            $Xr = Get-WmiObject –class Win32_processor -ComputerName $Computer -ErrorAction Stop
            $ld = Get-ADComputer $Computer -properties Name, Lastlogondate, ipv4Address, enabled, description, DistinguishedName -ErrorAction Stop
            $r = "{0} GB" -f ((Get-WmiObject Win32_PhysicalMemory -ComputerName $Computer -ErrorAction Stop | Measure-Object Capacity  -Sum).Sum / 1GB)
            $x = Get-WmiObject win32_computersystem -ComputerName $Computer -ErrorAction Stop | select @{Name = "Type"; Expression = {if (($_.pcsystemtype -eq '2')  )
                    {'Laptop'} Else {'Desktop Or Other'}}
            }, Manufacturer, @{Name = "Model"; Expression = {if (($_.model -eq "$null")  ) {'Virtual'} Else {$_.model}}}, username

            ## Output on creation
            New-Object PSObject -Property @{
                SerialNumber              = $sr.serialnumber -replace "-.*"
                Computername              = $ld.name
                IPaddress                 = $ld.ipv4Address
                MACaddress                = $mc.MACAddress
                Enabled                   = $ld.Enabled
                Description               = $ld.description
                OU                        = $ld.DistinguishedName.split(',')[1].split('=')[1]
                DC                        = $xx.domain
                Type                      = $x.type
                Manufacturer              = $x.Manufacturer
                Model                     = $x.Model
                RAM                       = $R
                ProcessorName             = ($xr.name | Out-String).Trim()
                NumberOfCores             = ($xr.NumberOfCores | Out-String).Trim()
                NumberOfLogicalProcessors = ($xr.NumberOfLogicalProcessors | Out-String).Trim()
                Addresswidth              = ($xr.Addresswidth | Out-String).Trim()
                Operatingsystem           = $in.caption
                InstallDate               = ([WMI] '').ConvertToDateTime($in.installDate)
                LastLogonDate             = $ld.lastlogondate
                LoggedinUser              = $x.username
            }

            ## Only do this kind of update if it hasnt failed yet
            $desc = "$($mc.MACAddress) ( $($sr.serialnumber -replace "-.*") ) $($x.Model) | $((Get-Date).ToString('MM-dd-yyyy'))"
            # Properties to be included in the output file
            Set-ADComputer $Computer -Description $desc -verbose

            ## No longer need this
            # $t
        }
        Catch [Exception]
        {
            $ErrorMessage = $_.Exception.Message
            Add-Content -value "$Computer, $ErrorMessage, skipping to next" $txt
            Set-ADComputer $Computer -Description $ErrorMessage
            continue
        }
    }
} | select Computername, Enabled, Description, IPaddress, MACaddress, OU, DC, Type, SerialNumber, Manufacturer, Model, RAM, ProcessorName, NumberOfCores, NumberOfLogicalProcessors, Addresswidth, Operatingsystem, InstallDate, LoggedinUser, LastLogonDate | export-csv -Append $file -NoTypeInformation

Upvotes: 1

Related Questions