Try/Catch inside ForEach If/Else Loop

Pat McGuinness 21 Reputation points
2021-09-10T23:13:18.69+00:00

Hello,

I am fairly new to PowerShell and am drawing a blank on what a Try/Catch is not running when part of an If/Else inside of a ForEach loop. I am working to automate license collections (partial key only) of existing and new client devices when onboarding new environments as part of my job at an MSP. The script runs the ForEach fine and collects the info I'm looking for, but it's ignoring the IF/ELSE and TRY/CATCH, so we keep getting duplicate entries in the resulting CSV and we're not getting an exceptions log to see what systems are not responding to requests for information.

The end goal is to remove the $cred variable and setup a scheduled task to run twice a day to eventually collect all device licensing info to hand off to the business for software inventory among other things. Any assistance would be greatly appreciated. I'm assuming this is either a syntax issue or my own ignorance of how these commands run.

Clear-Host

$DomName = Get-ADDomain |Select -Expand NetBIOSName

New-Item -ItemType Directory -Force -Path C:\TEMP\${DomName}_Onboarding\${DomName}_ServerLicensing\

Get-ADComputer -Filter {(OperatingSystem -Like '*Server*') -AND (Enabled -Eq 'TRUE')}|Select -Expand Name|Out-File C:\TEMP\${DomName}_Onboarding\${DomName}_ServerLicensing\Servers.txt

$cred=Get-Credential

$servers = Get-Content C:\TEMP\${DomName}_Onboarding\${DomName}_ServerLicensing\Servers.txt    
$collected = Get-Content C:\TEMP\${DomName}_Onboarding\${DomName}_ServerLicensing\PS_MSOLicenses.csv

 foreach ($server in $servers)
 {
 if ($server -in $collected.PSComputerName)
 {
 Write-Host "$server information already collected."
 }
 else
 {
 Write-Host "$server information NOT yet collected."

try {

(Get-WmiObject -Class SoftwareLicensingProduct -Filter 'ProductKeyId != NULL'-Computername $server) | Select-Object -Property PSComputerName,Name,Description,LicenseFamily,ProductKeyChannel,PartialProductKey |Export-csv C:\TEMP\${DomName}_Onboarding\${DomName}_ServerLicensing\PS_MSOLicenses.csv -NoTypeInformation -Append

}

catch {
       "$server could not be contacted. System may be Windows Server 2008, be offline, or PS Remoting is not enabled." | Out-File -Append C:\TEMP\${DomName}_Onboarding\${DomName}_ServerLicensing\${DomName}_Server_Licensing_Exceptions.csv
    }

 }
 }

Thanks again for any and all assistance.

Windows for business Windows Server User experience PowerShell
0 comments No comments
{count} votes

Accepted answer
  1. MotoX80 36,291 Reputation points
    2021-09-11T00:40:07.937+00:00

    Does this help? Note the use of import-csv.

    https://devblogs.microsoft.com/scripting/powertip-get-row-from-csv-file-based-on-value/

     $servers = Get-Content C:\TEMP\Servers.txt
     "Here are the servers."
     $servers  
     ""    
     $raw = Get-Content C:\TEMP\Test.csv
     "Here is the raw csv."
     $raw  
    
     ""
     $collected = Import-Csv C:\TEMP\Test.csv
     "Here is the imported csv."
     $collected  
     ""
    
      foreach ($server in $servers)  {
          "Looking for $server"
          if ($collected.Where({$PSItem.PSComputername -eq $server})  )   {
              "$server information already collected."
          }  else  {
              "$server information NOT yet collected."
          }
          ""
      }
    

    Some test data produces this and finds test10.

    Here are the servers.
    localhost
    xxxxxxxxx
    Test10
    
    Here is the raw csv.
    "PSComputername","SomeField","AnotherField"
    "AAAAA","11111","aaaaaaa"
    "Test10","22222","bbbbb"
    "ZZZZZ","33333","ccccc"
    
    Here is the imported csv.
    
    PSComputername SomeField AnotherField
    -------------- --------- ------------
    AAAAA          11111     aaaaaaa     
    Test10         22222     bbbbb       
    ZZZZZ          33333     ccccc       
    
    Looking for localhost
    localhost information NOT yet collected.
    
    Looking for xxxxxxxxx
    xxxxxxxxx information NOT yet collected.
    
    Looking for Test10
    Test10 information already collected.
    

    Update: to use the -IN operator, the IF statement should be:

     if ($server -in ($collected).pscomputername) {
    

2 additional answers

Sort by: Most helpful
  1. Rich Matheisen 47,901 Reputation points
    2021-09-11T02:30:17.443+00:00

    For the Catch block to be run the Get-WmiObject must generate a terminating error. A simple non-terminating error won't do that.

    Adding -ErrorAction STOP to the Get-WmiObject cmdlet will force all errors to be "terminating".

    0 comments No comments

  2. Pat McGuinness 21 Reputation points
    2021-09-11T03:27:46.577+00:00

    See below for the working script based on the updates provided by @MotoX80 and @Rich Matheisen

    Clear-Host  
      
    $DomName = Get-ADDomain |Select -Expand NetBIOSName  
      
    New-Item -ItemType Directory -Force -Path C:\TEMP\ServerLicensing\  
      
    Get-ADComputer -Filter {(OperatingSystem -Like '*Server*') -AND (Enabled -Eq 'TRUE')}|Select -Expand Name|Out-File C:\TEMP\ServerLicensing\Servers.txt  
      
    ## $cred=Get-Credential  
      
    ## Credit MotoX80 & RichMatheisen-8856  
      
      $servers = Get-Content C:\TEMP\ServerLicensing\Servers.txt  
      "Here are the servers."  
      $servers    
      ""      
      $raw = Get-Content C:\TEMP\ServerLicensing\PS_MSOLicenses.csv  
      "Here is the raw csv."  
      $raw    
           
      ""  
      $collected = Import-Csv C:\TEMP\ServerLicensing\PS_MSOLicenses.csv  
      "Here is the imported csv."  
      $collected    
      ""  
              
       foreach ($server in $servers)  {  
           "Looking for $server"  
           if ($collected.Where({$PSItem.PSComputername -eq $server})  )   {  
               "$server information already collected."  
           }  else  {  
               "$server information NOT yet collected."  
      
    try{  
      
    (Get-WmiObject -Class SoftwareLicensingProduct -Filter 'ProductKeyId != NULL'-Computername $server -ErrorAction STOP) | Select-Object -Property PSComputerName,Name,Description,LicenseFamily,ProductKeyChannel,PartialProductKey |Export-csv C:\TEMP\ServerLicensing\PS_MSOLicenses.csv -NoTypeInformation -Append  
      
    }  
      
    catch {  
           "$server could not be contacted. System may be Windows Server 2008, be offline, or PS Remoting is not enabled." | Out-File -Append C:\TEMP\ServerLicensing\Licensing_Exceptions.csv  
        }  
      
           }  
           ""  
       }  
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.