Welcome to Powergui.org - an open source community for Windows Powershell

PowerGUI.org PowerGUI.org and blogs

Forums » Active Directory and PowerShell

Thread: please help with script tuning

This question is answered.


Permlink Replies: 5 - Pages: 1 - Last Post: Dec 6, 2009 9:12 AM by: Deas
Deas

Posts: 20
Registered: 3/6/09
please help with script tuning
Posted: Dec 3, 2009 4:19 PM
 
  Click to reply to this thread Reply

hello,

i developed a script that enumerates all folders of our roaming profiles server, checks them for age, size, and do some action if needed. unfortunately this script brings the powershell.exe process to the limit. it takes more than 1gig of memory and is not even finished!

would be cool if sbdy could help and explain to me why this is and how i can fix and avoid this in the future.

here is he script:

If (-not (Get-PSSnapin Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue)) {
 Add-PSSnapin Quest.ActiveRoles.ADManagement
}

$LogFile = "C:\PSScripts\Logs\UserProfileMaintenance-DeleteProfilesOlder.txt"

#Check if file already exists and delete before appending new data
$FileExists = Test-Path $LogFile

if ($FileExists -eq $true) {
Remove-Item $LogFile
}

$LogFileDaily = "C:\PSScripts\Logs\UserProfileMaintenance-" + (Get-Date).DayOfWeek + ".txt"

#Check if file already exists and delete before appending new data
$FileExists = Test-Path $LogFileDaily

if ($FileExists -eq $true) {
Remove-Item $LogFileDaily
}

$Date = Get-Date
Get-ChildItem \\profiles\Userprofiles$ | ForEach-Object {
 $Size = Get-ChildItem("\\profiles\Userprofiles$\" + $_) -Recurse -Force | Measure-Object Length -Sum
 $Size = $Size.Sum
 $Size = $Size / 1024 / 1024
 Write-Host $_ $Size.ToString("#.##")
 
 $LogWrite = new-object IO.StreamWriter($LogFileDaily,$true)
 $LogWrite.WriteLine("\\profiles\Userprofiles$\" + $_ + ";" + $Size)
 $LogWrite.Close()
 
 $UserID = "DOMAIN\" + $_
 
 If ((Get-QADUser $UserID) -ne $Null) {
  If ((Get-QADUser $UserID -DontUseDefaultIncludedProperties -IncludedProperties AccountIsDisabled).AccountIsDisabled) {
   Write-Host "\\profiles\Userprofiles$\" + $_ + " Deleted - Account Disabled!"
   $LogWrite = new-object IO.StreamWriter($LogFile,$true)
   $LogWrite.WriteLine("\\profiles\Userprofiles$\" + $_ + " Deleted - Account Disabled!")
   $LogWrite.Close()
   Remove-Item "\\profiles\Userprofiles$\" + $_ -Force -Recurse -WhatIf
  }
 }
 
 $LastWritten = (Get-ItemProperty("\\profiles\Userprofiles$\" + $_)).LastWriteTime
 Write-Host $LastWritten
 
 If ($LastWritten -lt $Date.AddDays(-60)){
  Write-Host "\\profiles\Userprofiles$\" + $_ + " Deleted - Profile older than 60 Days!"
  $LogWrite = new-object IO.StreamWriter($LogFile,$true)
  $LogWrite.WriteLine("\\profiles\Userprofiles$\" + $_ + " Deleted - Profile older than 60 Days!")
  $LogWrite.Close()
  Remove-Item("\\profiles\Userprofiles$\" + $_) -Force -Recurse -WhatIf
 }
 
 If (($_ -like "*!*") -or ($_ -like "*_*")) {
  Write-Host "\\profiles\Userprofiles$\" + $_ + " Deleted - Renamed Profile!"
  $LogWrite = new-object IO.StreamWriter($LogFile,$true)
  $LogWrite.WriteLine("\\profiles\Userprofiles$\" + $_ + " Deleted - Renamed Profile!")
  $LogWrite.Close()
  Remove-Item("\\profiles\Userprofiles$\" + $_) -Force -Recurse -WhatIf
 }
 
 If ($Size -gt 150) {
  $emailFrom = "profileadmin@domain.internal"
  $emailTo = "admin@domain.internal"
  $subject = "Userprofil Warning " + $_
  $body = "body"
  $smtpServer = "smtp-relay.domain.internal"
  $smtp = new-object Net.Mail.SmtpClient($smtpServer)
  $smtp.Send($emailFrom, $emailTo, $subject, $body)
 }
}

thank you very much for your help!


brgds Deas




gareth.mcguinness_000

Posts: 54
Registered: 8/25/09
Re: please help with script tuning
Posted: Dec 4, 2009 5:29 AM   in response to: Deas
Answered
  Click to reply to this thread Reply

Hi,

Are you using version 1.3 of the cmdlets per chance?

I have had a similar problem with a script that works in about 200Mb on version 1.22 but kills my system with version 1.3. after using about 1.7Gb!

It seems like the get-qaduser does not clean up the object memory (finalization step?) when you are running it through a loop.

Try it with a version previous to 1.3 and see if it improves the memory management.

Gareth






Deas

Posts: 20
Registered: 3/6/09
Re: please help with script tuning
Posted: Dec 4, 2009 7:45 AM   in response to: Deas
 
  Click to reply to this thread Reply

hello,

yes, i have upgraded to 1.3 this week - was not such a good idea i think. meanwhile i replaced the get-qaduser with get-user and now the powershell takes about 33megabyte after an hour of running time. MUCH better i think!

so i know for sure that this is a VERY large memory leak!

is there anybody from quest who could confirm this and when it will be fixed?!?

EDIT: anybody knows where to download the last release before 1.3.0? i already deleted it from our server...

brgds Deas

Message was edited by: Deas


Shay Levy


Posts: 1,919
Registered: 1/31/08
Re: please help with script tuning
Posted: Dec 6, 2009 12:27 AM   in response to: Deas
Helpful
  Click to reply to this thread Reply

See if this makes any difference:

$Date = Get-Date
$LogFile = "C:\PSScripts\Logs\UserProfileMaintenance-DeleteProfilesOlder.txt"
$LogFileDaily = "C:\PSScripts\Logs\UserProfileMaintenance-" + $Date.DayOfWeek + ".txt"
$emailFrom = "profileadmin@domain.internal"
$emailTo = "admin@domain.internal"
$smtpServer = "smtp-relay.domain.internal"

# Check if file already exists and delete before appending new data
if( Test-Path $LogFile) {Remove-Item $LogFile -force}

#Check if file already exists and delete before appending new data
if( Test-Path $LogFileDaily) {Remove-Item $LogFileDaily -force}

Get-ChildItem \\profiles\Userprofiles$ | where {$_.psiscontainer} | ForEach-Object {
 $UserID = "DOMAIN\" + $_.name
 $Size = ((Get-ChildItem $_ -Recurse -Force | Measure-Object Length -Sum).Sum /1GB).ToString("#.##")
 Write-Host $Size
 Add-Content -path $LogFileDaily -value ("$($_.fullname); $Size")
 If ($Size -gt 150) {
  $subject = "Userprofil Warning $_"
  $body = "body"
  $smtp = new-object Net.Mail.SmtpClient($smtpServer)
  $smtp.Send($emailFrom, $emailTo, $subject, $body)
 }
 
 $user = Get-QADUser -samaccountname $UserID
 if ($user -AND $user.AccountIsDisabled)
 {
  Write-Host "\\profiles\Userprofiles$\$_ Deleted - Account Disabled!"
  Add-Content -path $LogFile -value "\\profiles\Userprofiles$\$_ Deleted - Account Disabled!"
  Remove-Item $_.fullname -Force -Recurse -WhatIf
 }

 if ($_.LastWriteTime -lt $Date.AddDays(-60))
 {
     Write-Host "\\profiles\Userprofiles$\$_ Deleted - Profile older than 60 Days!"
     Add-Content -path $LogFile -value "\\profiles\Userprofiles$\$_ Deleted - Profile older than 60 Days!"
  Remove-Item $_.fullname -Force -Recurse -WhatIf
 }
 
 if ($_.name -match '!|_')
 {
  Write-Host "\\profiles\Userprofiles$\$_ Deleted - Renamed Profile!"
  Add-Content -path $LogFile -value "\\profiles\Userprofiles$\$_ Deleted - Renamed Profile!"
  Remove-Item $_.fullname -Force -Recurse -WhatIf
 } 
 
}


Shay Levy [MVP]
http://blogs.microsoft.co.il/blogs/ScriptFanatic
PowerShell Toolbar
Deas

Posts: 20
Registered: 3/6/09
Re: please help with script tuning
Posted: Dec 6, 2009 5:40 AM   in response to: Shay Levy
 
  Click to reply to this thread Reply

hello,

thank´s for the tuning tips, i´ll implement them in my script!

but the main problem is the get-qaduser cmdlet which obviously has a VERY large memory leak. it is so large that i think nobody from quest ever testet it on more than 10 users...   i replaced the get-qaduser part now with:

$UAC = (([ADSI]("LDAP://" + (Get-User ("DOMAIN\" + $_.Name.Replace(".V2",""))).DistinguishedName)).UserAccountControl).ToString()
  $Disabled = $False
  Switch ($UAC) {
   {($UAC -bor 2) -eq $UAC} {$Disabled = $True}
  }
  If ($Disabled -eq $True) {

brgds Deas


Deas

Posts: 20
Registered: 3/6/09
Re: please help with script tuning
Posted: Dec 6, 2009 9:12 AM   in response to: Shay Levy
 
  Click to reply to this thread Reply

hello,

if anybody is interested - here is the final script i use now:

$Date = Get-Date

$LogFile = "C:\PSScripts\Logs\UserProfileMaintenance-DeleteProfilesOlder.txt"
$LogFileDaily = "C:\PSScripts\Logs\UserProfileMaintenance-" + $Date.DayOfWeek + ".txt"

$emailFrom = "profileadmin@domain.local"
$smtpServer = "smtp-relay.domain.local"

# Check if file already exists and delete before appending new data
if( Test-Path $LogFile) {Remove-Item $LogFile -force}
if( Test-Path $LogFileDaily) {Remove-Item $LogFileDaily -force}

Get-ChildItem \\profiles\Userprofiles$ | where {$_.psiscontainer} | ForEach-Object {
 $Deleted = $False

 If ((Get-User ("DOMAIN\" + $_.Name.Replace(".V2","")) -ErrorAction SilentlyContinue) -ne $Null) {
  $UAC = (([ADSI]("LDAP://" + (Get-User ("DOMAIN\" + $_.Name.Replace(".V2",""))).DistinguishedName)).UserAccountControl).ToString()
  $Disabled = $False
  Switch ($UAC) {
   {($UAC -bor 2) -eq $UAC} {$Disabled = $True}
  }
  
  If ($Disabled -eq $True) {
   Write-Host "\\profiles\Userprofiles$\$_ Deleted - Account Disabled!"
   Add-Content -path $LogFile -value "\\profiles\Userprofiles$\$_ Deleted - Account Disabled!"
   Remove-Item $_.FullName -Force -Recurse -WhatIf
   $Deleted = $True
  }
 }
 Else {
  Write-Host "\\profiles\Userprofiles$\$_ Deleted - Account not found!"
  Add-Content -path $LogFile -value "\\profiles\Userprofiles$\$_ Deleted - Account not found!"
  Remove-Item $_.FullName -Force -Recurse -WhatIf
  $Deleted = $True
 }
 
 if (($_.LastWriteTime -lt $Date.AddDays(-60)) -and ($Deleted -eq $False)) {
  Write-Host "\\profiles\Userprofiles$\$_ Deleted - Profile older than 60 Days!"
  Add-Content -path $LogFile -value "\\profiles\Userprofiles$\$_ Deleted - Profile older than 60 Days!"
  Remove-Item $_.FullName -Force -Recurse -WhatIf
  $Deleted = $True
 }
 
 if (($_.name -match '!|_') -and ($Deleted -eq $False)) {
  Write-Host "\\profiles\Userprofiles$\$_ Deleted - Renamed Profile!"
  Add-Content -path $LogFile -value "\\profiles\Userprofiles$\$_ Deleted - Renamed Profile!"
  Remove-Item $_.FullName -Force -Recurse -WhatIf
  $Deleted = $True
 }
 
 If ($Deleted -eq $False) {
  $Size = (Get-ChildItem $_.FullName -Recurse -Force | Measure-Object Length -Sum).Sum /1MB
  Add-Content -path $LogFileDaily -value ("$($_.FullName);" + $Size.ToString("#.##"))
 
  If ($Size -gt 150) {
   $subject = "Userprofil Warning " + $_.Name.Replace(".V2","")
   $emailTo = $_.Name.Replace(".V2","") + "@domain.local"
   $body = "bla bla bla " + $Size.ToString("#.##") + " bla bla bla"
   $smtp = new-object Net.Mail.SmtpClient($smtpServer)
   $smtp.Send($emailFrom, $emailTo, $subject, $body)
  }
 }
}

i didn´t used your script exactly because:

.) it is a litte bit more complex - i don´t want to check the size of a profile that i delete and sending an e-mail to a disabled user doesn´t make sense
.) only do it once - checking a deleted folder does not make sense...
.) when you format the size string directly you can´t compare it
.) i forgot that win7 adds a .v2 at the end of the profile name - this i added here
.) without the get-qaduser it is a little bit more code at the moment, but runs MUCH better until quest fixes this huge memory leak.

brgds Deas




Legend
MVP: 2501 + pts
Guru: 2001 - 2500 pts
Expert: 751 - 2000 pts
Enthusiast: 31 - 750 pts
Novice: 0 - 30 pts
Moderators
Helpful answer (5 pts)
Answered (10 pts)

Point your RSS reader here for a feed of the latest messages in all forums