Quantcast
Channel: Software Communities : Popular Discussions - ActiveRoles
Viewing all articles
Browse latest Browse all 1277

Get-QADObject Memory Issues

$
0
0

Good Morning,

 

I'm tried looking around the web for this issue, but have not been able to find a definite solution.

 

QUICK OVERVIEW: My company had to change email servers. In the process we migrated just under 4,000 users to the new email system. As a transition phase during the migration a contact was created for each user with the new email address. The user account was then pointed to forward mail to this contact. I wrote a Powershell 3.0 script using the Quest AD Module to delete the contacts and update the corresponding user account with the new email information. The script works excellent on a small scale, but starts throwing "Out of Memory" errors when it gets to about 600+ users. I'm not sure what I'm missing or how to catch / fix this memory leak. Any recommendations would be greatly appreciated.

 

ATTEMPTED SOLUTIONS: The script initually did everything under 1 function: export the contacts with all attributes (my failsafe in case something went horribly wrong), found the user account that corresponds to the contact, exported user info (again failsafe), deleted contact, updated user, export the user with the new settings. After reading on the few forums I found that were relevant, I tried implementing Clear-Variable, [GC]::Collect(), Remove-Variable throughout the script, but did not see any impact on the memory usage. Under this initial script, I was using about 1.6GB of RAM about 1/3 into the script. The code for the script I'm posint below is version 6. In this one I'm Including all properties on my queries for the export purposes. In previous versions I was only selecting the properies I needed, but then had to do another Get-QADObject/User with full properties for the export. In the end, the script crashed with the "Out of Memory" error regardless of whether I was getting all properies or only the selected ones. I also played around with different PageSize settings and setting it to 25 seemed to speed the process up the most, but had no noticeable impact on the memory consumption. In one version of the script I even tried a While (contacts exist) { process accounts with SizeLimit '250'}. During the testing phase I wasn't actually makeing the changes, just moving the contacts to another OU. In theory I though that setting the size limit would fix my issue, but it had no impact to the overall result.

 

I finally broke the script into functions and pipelined the whole process (see code below: code has been slightly modified to hide true variable values and condense comments and custom messages).

 

ERROR MESSAGES: These are the error messages I'm receiving. As you can see, the system has plenty of RAM available, but the script is using ~ 1.4GB. I'm not 100% sure what the 2nd part of the error means. I'm assuming that it resulted in the memory running out and the variable not containing any more data for that iteration of the script.

 

Full Error - with RM.PNG

 

 

 

SCRIPT CODE:

 

#requires -version 3

## Load Quest Snappin

Add-PSSnapin Quest.ActiveRoles.ADManagement -ErrorAction silentlycontinue

 

## ***** Declare Variables *****

 

## Containers

$global:contact_OU="ou=MIGRATION,ou=CONTACTS,ou=OFFICE,ou=DEPT,dc=SUBDOMAIN,dc=DOMAIN,dc=COM"

$global:unmatched_OU="ou=Unmatched,ou=MIGRATION,ou=CONTACTS,ou=OFFICE,ou=DEPT,dc=SUBDOMAIN,dc=DOMAIN,dc=COM"

 

## Reporting Variables

$global:report_path="C:\AD\Email Cleanup"

$global:timeStamp=Get-Date-UFormat"%H%M_%d-%m-%d-%Y"

 

 

## Get-QAD Object Splat Variables

$user_splat= @{

          OrganizationalUnit ="ou=USERS,ou=DEPT,ou=COMPANY,dc=SUBDOMAIN,dc=DOMAIN,dc=COM"

          LdapFilter ="(!(DisplayName=*.ADM))"## Do not include admin accounts

          IncludeAllProperties =$true

          SizeLimit ="1"

          ShowProgress =$true

} # end $user_splat

 

$contact_splat= @{

Type="Contact"

          OrganizationalUnit =$contact_OU

          LdapFilter ="(mail=*@newEmail.com)"

          IncludeAllProperties =$true

          SearchScope ="OneLevel"

          SizeLimit ="0"

          PageSize ="25"

          ShowProgress =$true

} # end $contact_splat

 

 

## Write-Out colors.  Some color variables have been removed to shorten the code being posted.

$gc_colors= @{

          ForegroundColor ="Yellow"

          BackgroundColor ="DarkGreen"

} # end splat $gc_colors

 

cls

## ***** Get Reports *****

functionGet_Reports ($obj, $fileName) {

## Export the objects

$report=$timeStamp+"_"+$fileName

 

$obj|Export-Csv"$report_path\$report.csv"-Append-NoTypeInformation

 

return$obj

} # end function Get_Reports

 

 

## ***** Update Users *****

functionProcess_Users ($contact) {

 

          if (!($user=Get-QADUser @user_splat -LogonName$contact.mailNickname)) {

       Write-Host"*******************************************************" @unmatched_colors

       Write-Host @unmatched_colors $contact.Name " Could not be matched to a user account."

       Write-Host"*******************************************************" @unmatched_colors

                                          try {

       #Write-Host "******************* Moving ************************" $contact.Name

       Move-QADObject-Identity$contact.Name -NewParentContainer$unmatched_OU-ErrorAction'Stop'-ErrorVariable$moveError

     } catch [System.OutOfMemoryException] {

       Write-Warning"Out of RAM"

       $errorTime=Get-Date-UFormat"%d-%m-%d-%Y_%H%M"

       Write-Host"Memory Error:"$errorTime|Out-File"$report_path\Function_Report_$timeStamp.txt"-Append

       Throw"Memory Error"

     } catch {

       Write-Warning"Error moving contact"

       Get_Reports$contact"Error_Unmatched_Users"

     } finally {

       Get_Reports$contact"Unmatched_Contacts"

     } # end finally

                              } # end if (!(Get-QADUser)

                    else {

       ## Set variables

                                   $new_email=$contact.PrimarySMTPAddress

 

       ## Generate Report prior to cleanup

       Get_Reports$user"Pre-Cleanup_Users"

 

     try {

       ## Remove contact so that the new email address can be set as the primary address for the user.

       Remove-QADObject-Identity$contact.name -Force

 

       ## Process user accounts

       $user|Set-QADUser-ObjectAttributes @{altRecipient=''; msExchHomeServerName=''; homeMDB=''; targetAddress="$new_email"}`

       |Add-QADProxyAddress-Type"SMTP"-Address$new_email-Primary `   

       |Remove-QADProxyAddress-Pattern"*@oldemail1.com"`

       |Remove-QADProxyAddress-Pattern"*@oldemail2.com"

     } catch [System.OutOfMemoryException] {    

       Write-Warning"Out of RAM"

       $errorTime=Get-Date-UFormat"%d-%m-%d-%Y_%H%M"

       Write-Host"Memory Error:"$errorTime|Out-File"$report_path\Function_Report_$timeStamp.txt"-Append

       Throw"Memory Error"

     } catch {

       Write-Warning"Error moving user"

       Get_Reports$user"Error_Users"

    } finally {

       ## Generate report after user changes have been applied

       Get-QADUser$user.Name |% {Get_Reports$_"Post-Cleanup_Users"}

    } # end finally

                    } # end else

} # end function Process_Users

 

 

## Function to create pop-up message(s) with information about the script and initiate the rest of the functions if the user chooses to do so.

functionNotifications {

$script_description="This script will go through Active Directory and match ... {script description}.

 

Do you wish to proceed?"

 

          $a=New-Object-ComObject wscript.shell

$proceed=$a.popup($script_description,0,"Script Description",4)

 

          if ($proceed-eq 6) {

  ## Answered "Yes", proceed with script

  Write-Host"YES"

  Write-Host"Processing Contacts and Users"

 

  ## Process users

                    Get-QADObject @contact_splat |%{Get_Reports$_"Contacts"} |% {Process_Users$_}

 

  Invoke-Item$report_path

          } # end if

else {

  ## Answered "NO" exit script.

  Write-Host"*** Exiting Script ***"

          } # end else

 

} # end function Notifications

 

## Run the notification and give the user an option to terminate program before executing.

Notifications


Viewing all articles
Browse latest Browse all 1277

Trending Articles