James
 Basic Member Posts:374

 |
| 29 Jun 2010 07:52 AM |
|
Hello,
I am just wondering is there a way to sort out the memory that Powershell uses?
When running massive scripts which take up all the memory in the server I am running it on (which is 4GB!) it slows everything down as you would expect.
Is there anything I can put in my script to keep it down so the speed of the box is not dead?
Many Thanks
James |
|
|
|
|
James
 Basic Member Posts:374

 |
| 01 Jul 2010 03:41 AM |
|
Does anyone know how a single script can hog 4GB of RAM? and if so how do I stop it from hogging it? or release it as it loops? Many Thanks James |
|
|
|
|
George Howarth
 Basic Member Posts:360

 |
| 01 Jul 2010 03:55 AM |
|
Post your script. Maybe we can optimize it. |
|
|
|
|
Shay Levy PowerShell MVP, Admin
 Veteran Member Posts:1362

 |
|
James
 Basic Member Posts:374

 |
| 01 Jul 2010 05:08 AM |
|
Hello, I can share the code yes however I will take certain parts out which relate to our domain structure.
# Set Parameters
Function New-Year {
param
(
[switch]$All,
[switch]$Stage1,
[switch]$Stage2,
[switch]$Stage3,
[switch]$Stage4,
[switch]$Help
)
# Set Variables
$Global:S = $Null
$Global:StartRoutine = $null
$Global:FinishRoutine = $null
$Global:Stage1Run = $null
$Global:Stage2Run = $null
$Global:Stage3Run = $null
$Global:Stage4Run = $null
$Global:Stage1Start = $null
$Global:Stage2Start = $null
$Global:Stage3Start = $null
$Global:Stage4Start = $null
$Global:Stage1Finish = $null
$Global:Stage2Finish = $null
$Global:Stage3Finish = $null
$Global:Stage4Finish = $null
$Global:TimeRoutine = $null
$Global:TimeStage1 = $null
$Global:TimeStage2 = $null
$Global:TimeStage3 = $null
$Global:TimeStage4 = $null
$Global:Switches = $null
$Global:SchoolList = Import-Csv "C:\Powershell\CSV\SchoolsList.csv"
Function Usage {
Write-Host ""
Write-Host "FUNCTION NAME: New-Year" -ForegroundColor White
Write-Host ""
Write-Host "USAGE"
Write-Host " New-Year -All "
Write-Host " New-Year -Stage1"
Write-Host " New-Year -Stage1 -Stage2"
Write-Host " New-Year -Stage1 -Stage2 -Stage3"
Write-Host ""
Write-Host "DESCRIPTION:"
Write-Host " Designed for the use of the schools team for a new intake of students, parents etc."
Write-Host " It can be used for one particular operation or all operations required"
Write-Host " for the new intake. It will also give you the statistics of time taken at the end."
Write-Host ""
Write-Host "AVAILABLE SWITCHES:"
Write-Host " -All : Runs All of the stages in order"
Write-Host " -Stage1 : Runs Stage 1 - Removing Of Disabled Users"
Write-Host " -Stage2 : Runs Stage 2 - Removing Of Spaces In The SAMAccountName,UPN, Mail Attributes"
Write-Host " -Stage3 : Runs Stage 3 - Sets Student Target And Proxy Addresses "
Write-Host " -Stage4 : Runs Stage 4 - Sets City And Company Information For Users"
Write-Host ""
Write-Host "REQUIREMENTS:"
Write-Host " You must provide at lease one switch"
Write-Host ""
break
}
Function All {
Stage1
Stage2
Stage3
Stage4
}
Function RoutineStart {
Write-Host " "
Write-Host " ROUTINE START: " -ForegroundColor White
Write-Host " "
$Global:StartRoutine = Get-Date
" Day: " + $Global:StartRoutine.DayOfWeek
" Date: " + $Global:StartRoutine.ToShortDateString()
" Time: " + $Global:StartRoutine.ToShortTimeString()
Write-Host " "
}
Function Stage1 {
#Remove Disabled Users
$Global:Stage1Run = 1
Write-Host " Stage 1: Removing Disabled Users.... " -ForegroundColor Yellow
$Global:Stage1Start = Get-Date
Write-Host " "
$SchoolList |
ForEach-Object{
$School = $_.School
$ou = 'OU=users,OU=' + $School + ',OU=foo1,DC=foo,DC=co,DC=uk'
Get-QADUser -Title "student", "teacher","staff","parent" -SearchRoot $ou -SizeLimit 0 -IncludeAllProperties |
Where-Object {$_.useraccountcontrol -eq 514 -or $_.useraccountcontrol -eq 66050 }|
ForEach-Object{
$SamAccountName = $_.SamAccountName
Write-Host "Deleting User: " $SamAccountName
Delete-ADUser $SamAccountName
}
}
Write-Host " "
Write-Host " Stage 1 Complete! Disabled Users Successfully Removed. " -ForegroundColor Yellow
$Global:Stage1Finish = Get-Date
Write-Host " "
Write-Host " "
}
Function Stage2 {
$Global:Stage2Run = 1
# Remove Spaces
Write-Host " Stage 2: Removing Spaces From Accounts.... " -ForegroundColor Yellow
$Global:Stage2Start = Get-Date
Write-Host " "
$SchoolList |
ForEach-Object{
$School = $_.School
$ou = 'OU=users,OU=' + $School + ',OU=foo1,DC=foo,DC=co,DC=uk'
Get-QADUser -Title "student", "teacher","staff","parent" -SearchRoot $OU -SizeLimit 0 -includeAllProperties |Where-Object {$_.UserPrincipalName -match "\s" -or $_.samAccountName -match "\s" -or $_.mail -match "\s"}|
ForEach-Object{
$Sam = $_.SamAccountName
$Sam1 = $Sam -replace " ",""
$NewSam = $Sam1 -replace "'",""
$UPN = $_.UserPrincipalName
$UPN1 = $UPN -replace " ",""
$NewUPN = $UPN1 -replace "'",""
$Mail = $_.Mail
$Mail1 = $Mail -replace " ",""
$NewMail = $Mail1 -replace "'",""
Set-QADUser -Identity $Sam -ObjectAttributes @{Mail = $NewMail}
Set-QADUser -Identity $Sam -UserPrincipalName $NewUPN
Set-QADUser -Identity $Sam -SamAccountName $NewSam
}
}
Write-Host " "
Write-Host " Stage 2 Complete! Spaces Successfully Removed. " -ForegroundColor Yellow
$Global:Stage2Finish = Get-Date
Write-Host " "
Write-Host " "
}
Function Stage3 {
$Global:Stage3Run = 1
Write-Host " Stage 3: Setting Student Proxy and Target Addresses.... " -ForegroundColor Yellow
$Global:Stage3Start = Get-Date
Write-Host " "
# Assign Target Address and Proxy Address to Students
$SchoolList |
ForEach-Object{
$School = $_.School
$ou = 'OU=users,OU=' + $School + ',OU=foo1,DC=foo,DC=co,DC=uk'
Get-QADUser -Title "student" -SearchRoot $OU -SizeLimit 0 | ForEach-Object{
$TargetAddress = 'smtp:' + $_.samAccountName + '@foo1.co.uk'
$ProxyAddress = 'SMTP:' + $_.samAccountName + '@' + $School + '.foo.co.uk'
Set-QADUser -Identity $_.Name -PasswordNeverExpires $false
Set-QADUser -Identity $_.Name -ObjectAttributes @{TargetAddress=$TargetAddress}
Set-QADUser -Identity $_.Name -ObjectAttributes @{ProxyAddresses=$ProxyAddress}
}
}
Write-Host " "
Write-Host " Stage 3 Complete! Target and Proxy Addresses Successfully Written. " -ForegroundColor Yellow
$Global:Stage3Finish = Get-Date
Write-Host " "
Write-Host " "
}
Function Stage4 {
$Global:Stage4Run = 1
Write-Host " Stage 4: Setting City And Company Information.... " -ForegroundColor Yellow
$Global:Stage4Start = Get-Date
Write-Host " "
# Write City And Company Information
$SchoolList|
ForEach-Object{
$School = $_.School
$ou = 'OU=users,OU=' + $School + ',OU=foo1,DC=foo,DC=co,DC=uk'
Get-QADUser -SearchRoot $OU -sizeLimit 0 |
ForEach-Object{
$Sam = $_.SamAccountName
Set-QADUser -Identity $Sam -Company $School -City "city1"
}
}
Write-Host " "
Write-Host " Stage 4 Complete! City And Company Information Successfully Written. " -ForegroundColor Yellow
$Global:Stage4Finish = Get-Date
Write-Host " "
Write-Host " "
}
Function RoutineFinish {
Write-Host " All Stages Complete! " -ForegroundColor White
Write-Host " "
Write-Host " "
Write-Host " ROUTINE END: " -ForegroundColor White
Write-Host " "
$Global:FinishRoutine = Get-Date
" Day: " + $Global:FinishRoutine.DayOfWeek
" Date: " + $Global:FinishRoutine.ToShortDateString()
" Time: " + $Global:FinishRoutine.ToShortTimeString()
Write-Host " "
Write-Host " "
Write-Host " Routine Statistics: "
Write-Host " ------------------- "
Write-Host " "
Write-Host " "
# Work Out Time Taken
$TimeRoutine = New-TimeSpan -Start $StartRoutine -End $FinishRoutine
if ($Stage1 -or $All) { $TimeStage1 = New-TimeSpan -Start $Stage1Start -End $Stage1Finish }
if ($Stage2 -or $All) { $TimeStage2 = New-TimeSpan -Start $Stage2Start -End $Stage2Finish }
if ($Stage3 -or $All) { $TimeStage3 = New-TimeSpan -Start $Stage3Start -End $Stage3Finish }
if ($Stage4 -or $All) { $TimeStage4 = New-TimeSpan -Start $Stage4Start -End $Stage4Finish }
# Give Statistics
Write-Host " Routine Start: $($StartRoutine.DayOfWeek) $($StartRoutine)"
Write-Host " "
If($Stage1Run -ne "1") {
Write-Host " "
Write-Host " Statistics For Stage 1 Not Available (Stage 1 Was Not Run)"
Write-Host " "
} else {
Write-Host " "
Write-Host " Stage 1 Start: $($Stage1Start.DayOfWeek) $($Stage1Start)"
Write-Host " Stage 1 Finish: $($Stage1Finish.DayOfWeek) $($Stage1Finish)"
Write-Host " Stage 1 Complete Time: $([string]$TimeStage1.Days) Days $([string]$TimeStage1.Hours) Hours $([string]$TimeStage1.Minutes) Minutes $([string]$TimeStage1.Seconds) Seconds"
Write-Host " "
}
If($Stage2Run -ne "1") {
Write-Host " "
Write-Host " Statistics For Stage 2 Not Available (Stage 2 Was Not Run)"
Write-Host " "
} else {
Write-Host " "
Write-Host " Stage 2 Start: $($Stage2Start.DayOfWeek) $($Stage2Start)"
Write-Host " Stage 2 Finish: $($Stage2Finish.DayOfWeek) $($Stage2Finish)"
Write-Host " Stage 2 Complete Time: $([string]$TimeStage2.Days) Days $([string]$TimeStage2.Hours) Hours $([string]$TimeStage2.Minutes) Minutes $([string]$TimeStage2.Seconds) Seconds"
Write-Host " "
}
If($Stage3Run -ne "1") {
Write-Host " "
Write-Host " Statistics For Stage 3 Not Available (Stage 3 Was Not Run)"
Write-Host " "
} else {
Write-Host " "
Write-Host " Stage 3 Start: $($Stage3Start.DayOfWeek) $($Stage3Start)"
Write-Host " Stage 3 Finish: $($Stage3Finish.DayOfWeek) $($Stage3Finish)"
Write-Host " Stage 3 Complete Time: $([string]$TimeStage3.Days) Days $([string]$TimeStage3.Hours) Hours $([string]$TimeStage3.Minutes) Minutes $([string]$TimeStage3.Seconds) Seconds"
Write-Host " "
}
If($Stage4Run -ne "1") {
Write-Host " "
Write-Host " Statistics For Stage 4 Not Available (Stage 4 Was Not Run)"
Write-Host " "
} else {
Write-Host " "
Write-Host " Stage 4 Start: $($Stage4Start.DayOfWeek) $($Stage4Start)"
Write-Host " Stage 4 Finish: $($Stage4Finish.DayOfWeek) $($Stage4Finish)"
Write-Host " Stage 4 Complete Time: $([string]$TimeStage4.Days) Days $([string]$TimeStage4.Hours) Hours $([string]$TimeStage4.Minutes) Minutes $([string]$TimeStage4.Seconds) Seconds"
Write-Host " "
}
Write-Host " "
Write-Host " Routine Finish: $($FinishRoutine.DayOfWeek) $($FinishRoutine)"
Write-Host " "
Write-Host " "
Write-Host " Routine Complete Time: $([string]$TimeRoutine.Days) Days $([string]$TimeRoutine.Hours) Hours $([string]$TimeRoutine.Minutes) Minutes $([string]$TimeRoutine.Seconds) Seconds"
Write-Host " "
Write-Host " "
Write-Host " End Of Routine Statistics"
Write-Host " "
Write-Host " "
}
if (!($All -or $Stage1 -or $Stage2 -or $Stage3 -or $Stage4 -or $Help))
{
Write-Host " "
Write-Host "Please Select A Switch"
Write-Host " " ; break} else {
if($All) {$Global:S += "All "}
if($Stage1) {$Global:S += "Stage1 "}
if($Stage2) {$Global:S += "Stage2 "}
if($Stage3) {$Global:S += "Stage3 "}
if($Stage4) {$Global:S += "Stage4 "}
if($Help) { Usage break }
}
RoutineStart
if($S -match "All") {All}
if($S -match "Stage1") {Stage1}
if($S -match "Stage2") {Stage2}
if($S -match "Stage3") {Stage3}
if($S -match "Stage4") {Stage4}
RoutineFinish
}
Its using 4GB of ram when it just runs stage3 and nothing else on the server is doing anything hence it kills the server and slows it all down. Shay, I am not too sure what your getting at with your foreach's could you elaborate a little more? And are there any guidelines for anything in future? So how to better manage memory (Shay I presume you were meaning this however I am unsure of your meaning) Many Thanks James |
|
|
|
|
halr9000 PowerShell MVP, Site Admin
 Advanced Member Posts:565

 |
|
James
 Basic Member Posts:374

 |
| 01 Jul 2010 05:42 AM |
|
The csv file contains a list of 127 school names and thats all nothing else just one column. Its size is 2K Comment Based help in v2? How do you mean? Many Thanks James |
|
|
|
|
George Howarth
 Basic Member Posts:360

 |
| 01 Jul 2010 05:46 AM |
|
This can be simplified/optimized. I don't have time today, but I'll see what I can do tomorrow. |
|
|
|
|
Bartek Bielawski
 New Member Posts:43

 |
| 01 Jul 2010 05:50 AM |
|
Quick one: if you want disabled accounts, tell Quest Cmdlet to return only those (-Disabled) That should save you a lot of time and effort in Stage1.
|
|
|
|
|
James
 Basic Member Posts:374

 |
| 01 Jul 2010 06:07 AM |
|
Hello, I have just found the help file for that. Many Thanks for that it makes it a little neater! James |
|
|
|
|
James
 Basic Member Posts:374

 |
| 01 Jul 2010 06:25 AM |
|
Hello, I thought the same however I thought it would put too much memroy usage on it doing that though but thinking about it now would that not be teh equal amount of time for my code and yours to execute? Many Thanks James |
|
|
|
|
James
 Basic Member Posts:374

 |
| 01 Jul 2010 06:41 AM |
|
I stand corrected! I have just run it and changed the following: Get-QADUser -Title "student", "teacher","staff","parent" -SearchRoot $ou -SizeLimit 0 -Disabled | # -IncludeAllProperties Only if using Account Control # Where-Object {$_.useraccountcontrol -eq 514 -or $_.useraccountcontrol -eq 66050 }| ForEach-Object{ and it took minutes and deleted around 30 accounts!!!! Many Thanks James |
|
|
|
|
James
 Basic Member Posts:374

 |
| 01 Jul 2010 06:46 AM |
|
Oh just an after thought would that catch the disabled users which have the "Password Never Expires" checked? So in otherworks the user account control of: 66050 I have just tried it and its not removing them users.... Does anyone know why this is? or would I have to run something else to catch them too? Many Thanks James |
|
|
|
|
glnsize
 Basic Member Posts:193
 |
| 01 Jul 2010 06:50 AM |
|
I ran through and did a quick optimization of you're script... A couple of points you use -IncludeAllProperties ALOT. That will increase you're memory utilization, b/c powershell must process all those properties. Pair that down to what you need. Also you're using where-object to do all the filtering, that's fine, but it will increase the footprint. Consider moving that logic into a LDAP filter, it will not only be faster, but use WAY less memory as well. DO NOT RUN THIS IN A LIVE ENV... I just did a re-write I haven't even tried to run this script. Read through it and note the changes, this is only an example.
<#
.SYNOPSIS
Designed for the use of the schools team for a new intake of students, parents etc.
It can be used for one particular operation or all operations required
for the new intake. It will also give you the statistics of time taken at the end.
.DESCRIPTION
Designed for the use of the schools team for a new intake of students, parents etc.
It can be used for one particular operation or all operations required
for the new intake. It will also give you the statistics of time taken at the end.
.PARAMETER ALL
Will run all options. (DEFAULT)
.PARAMETER File
Path to a CSV file containg the new students
.PARAMETER DisabledUsers
Removing Of Disabled Users
.PARAMETER Spaces
Removing Of Spaces In The SAMAccountName,UPN, Mail Attributes
.PARAMETER StudentInfo
Sets Student Target And Proxy Addresses
.PARAMETER LocationInfo
Sets City And Company Information For Users
.EXAMPLE
./New-Year.ps1 -Path 'C:\Powershell\CSV\SchoolsList.csv' -All
.EXAMPLE
./New-Year.ps1 -Path 'C:\Powershell\CSV\SchoolsList.csv' -DisabledUsers
.EXAMPLE
./New-Year.ps1 -Path 'C:\Powershell\CSV\SchoolsList.csv' -DisabledUsers -Spaces -StudentInfo
#>
[CmdletBinding(DefaultParameterSetName='ALL')]
param
(
[Parameter(Mandatory=$true,ParameterSetName='All',HelpMessage ="Path to the CSV containing the list of Schools")]
[Parameter(Mandatory=$true,ParameterSetName='Selective',HelpMessage ="Path to the CSV containing the list of Schools")]
[ValidateScript({Test-Path -Path $_})]
[String]
$File
,
[Parameter(Mandatory=$false,ParameterSetName='All')]
[switch]
$All
,
[Parameter(ParameterSetName='Selective')]
[switch]
$DisabledUsers
,
[Parameter(ParameterSetName='Selective')]
[switch]
$Spaces
,
[Parameter(ParameterSetName='Selective')]
[switch]
$StudentInfo
,
[Parameter(ParameterSetName='Selective')]
[switch]
$LocationInfo
)
Begin
{
#Remove Disabled Users
Function Remove-DisabledUsers
{
Param(
[Parameter(Mandatory=$true)]
[string[]]$SchoolList
)
$start = Get-date
Write-verbose "$(get-date -format g) Starting Removing Disabled Users.... "
Foreach ($School in $SchoolList)
{
$ou = 'OU=users,OU=' + $School + ',OU=foo1,DC=foo,DC=co,DC=uk'
Get-QADUser -Title "student", "teacher","staff","parent" `
-SearchRoot $ou `
-SizeLimit 0 `
-IncludeAllProperties |
Where-Object {$_.useraccountcontrol -eq 514 -or $_.useraccountcontrol -eq 66050 }|
Delete-ADUser
}
Write-verbose "$(get-date -format g) Finished Removing Disabled Users.... "
Write-verbose "User cleanup completed in $((New-TimeSpan -Start $start).TotalMinutes) Minutes"
}
# Remove Spaces
Function Remove-SpacesFromAccounts
{
Param(
[Parameter(Mandatory=$true)]
[string[]]$SchoolList
)
$Start = Get-Date
Write-Verbose "$(get-date -format g) Removing Spaces From Accounts.... "
Foreach ($School in $SchoolList)
{
$ou = 'OU=users,OU=' + $School + ',OU=foo1,DC=foo,DC=co,DC=uk'
$Users = Get-QADUser -Title "student", "teacher","staff","parent" `
-SearchRoot $OU `
-SizeLimit 0 `
-includeAllProperties |
Where-Object {$_.UserPrincipalName -match "\s" -or $_.samAccountName -match "\s" -or $_.mail -match "\s"}
Foreach ($User in $Users)
{
$Sam = $User.SamAccountName
$Sam1 = $Sam -replace " ",""
$NewSam = $Sam1 -replace "'",""
$UPN = $User.UserPrincipalName
$UPN1 = $UPN -replace " ",""
$NewUPN = $UPN1 -replace "'",""
$Mail = $User.Mail
$Mail1 = $Mail -replace " ",""
$NewMail = $Mail1 -replace "'",""
Set-QADUser -Identity $Sam -ObjectAttributes @{Mail = $NewMail}
Set-QADUser -Identity $Sam -UserPrincipalName $NewUPN
Set-QADUser -Identity $Sam -SamAccountName $NewSam
}
}
Write-verbose "$(get-date -format g) Finished Removing spaces from accounts"
Write-verbose "Space removal completed in $((New-TimeSpan -Start $start).TotalMinutes) Minutes"
}
Function Set-StudentInfo
{
Param(
[Parameter(Mandatory=$true)]
[string[]]$SchoolList
)
$start = Get-date
Write-Verbose "$(get-date -format g) Setting Student Proxy and Target Addresses.... "
# Assign Target Address and Proxy Address to Students
Foreach ($School in $SchoolList)
{
$ou = 'OU=users,OU=' + $School + ',OU=foo1,DC=foo,DC=co,DC=uk'
$users = Get-QADUser -Title "student" -SearchRoot $OU -SizeLimit 0
Foreach ($user in $users)
{
$TargetAddress = 'smtp:{0}@foo1.co.uk' -f $user.samAccountName
$ProxyAddress = 'SMTP:{0}@{1}.foo.co.uk' -f $user.samAccountName ,$School
Set-QADUser -Identity $user.Name -PasswordNeverExpires $false
Set-QADUser -Identity $user.Name -ObjectAttributes @{TargetAddress=$TargetAddress}
Set-QADUser -Identity $user.Name -ObjectAttributes @{ProxyAddresses=$ProxyAddress}
}
}
Write-Verbose "$(get-date -format g) Setting Student Proxy and Target Addresses.... "
Write-Verbose "completed Setting student info in $((New-TimeSpan -Start $start).TotalMinutes) Minutes"
}
Function Set-LocationInfo
{
Param(
[Parameter(Mandatory=$true)]
[string[]]$SchoolList
)
$start = Get-date
Write-Verbose "$(get-date -format g) Setting City And Company Information...."
# Write City And Company Information
Foreach ($School in $SchoolList)
{
$ou = 'OU=users,OU=' + $School + ',OU=foo1,DC=foo,DC=co,DC=uk'
Get-QADUser -SearchRoot $OU -sizeLimit 0 |
Set-QADUser -Company $School -City "city1"
}
Write-Verbose "$(get-date -format g) City And Company Information Successfully Written. " -ForegroundColor Yellow
Write-Verbose "completed Setting city, and company info in $((New-TimeSpan -Start $start).TotalMinutes) Minutes"
}
}
End
{
$SchoolList = Import-Csv -Path $File
IF ($PSCMDLET.ParameterSetName -eq "All" -OR $DisabledUsers)
{
Remove-DisabledUsers -SchoolList $SchoolList
}
IF ($PSCMDLET.ParameterSetName -eq "All" -OR $Spaces)
{
Remove-SpacesFromAccounts -SchoolList $SchoolList
}
IF ($PSCMDLET.ParameterSetName -eq "All" -OR $StudentInfo)
{
Set-StudentInfo -SchoolList $SchoolList
}
IF ($PSCMDLET.ParameterSetName -eq "All" -OR $LocationInfo)
{
Set-LocationInfo -SchoolList $SchoolList
}
}
Hope that helps, ~Glenn UPDATE: Forgot the cmdletbinding statement... |
|
|
|
|
Bartek Bielawski
 New Member Posts:43

 |
| 01 Jul 2010 06:54 AM |
|
Well, it has nothing to do with disabled account, right? ;) But do not worry - Quest knew you will need it, so you have -PasswordNeverExpires switch there too. ;) But those two loops should be quicker than the one you had anyway... Since you ask AD only for accounts you want to process, and don't waste time and resources to filter them on your side. |
|
|
|
|
Shay Levy PowerShell MVP, Admin
 Veteran Member Posts:1362

 |
| 01 Jul 2010 06:55 AM |
|
Get-QADUser -SizeLimit 0 -Disabled -PasswordNeverExpires:$true foreach($i in 1..1000000000) { do something} is not the same as 1..1000000000 | foreach { do something} The first will blow your memory off because it tries to gather all 1000000000 objects first. The latter will do the same in a streaming way, one at a time, no performance penalty or memory issues.
|
|
Shay Levy Windows PowerShell MVP
http://PowerShay.com
PowerShell Community Toolbar
Twitter: @ShayLevy |
|
|
Shay Levy PowerShell MVP, Admin
 Veteran Member Posts:1362

 |
| 01 Jul 2010 07:01 AM |
|
You can save some precious round trips to AD: Set-QADUser -Identity $Sam -EMail $NewMail -UserPrincipalName $NewUPN -SamAccountName $NewSam Instead of: Set-QADUser -Identity $Sam -ObjectAttributes @{Mail = $NewMail} Set-QADUser -Identity $Sam -UserPrincipalName $NewUPN Set-QADUser -Identity $Sam -SamAccountName $NewSam And Set-QADUser -Identity $user.Name -PasswordNeverExpires $false -ObjectAttributes @{TargetAddress=$TargetAddress; ProxyAddresses=$ProxyAddress} Instead of: Set-QADUser -Identity $user.Name -PasswordNeverExpires $false Set-QADUser -Identity $user.Name -ObjectAttributes @{TargetAddress=$TargetAddress} Set-QADUser -Identity $user.Name -ObjectAttributes @{ProxyAddresses=$ProxyAddress}
|
|
Shay Levy Windows PowerShell MVP
http://PowerShay.com
PowerShell Community Toolbar
Twitter: @ShayLevy |
|
|
James
 Basic Member Posts:374

 |
| 01 Jul 2010 07:39 AM |
|
Ahhh Shay, So what I have in my code then is doing it in a streaming way then :) Also bielawb how would I get the disabled with -PasswordNeverExpires as I have tried adding another loop in and it just errors continually... I have done the following: Get-QADUser -Title "student", "teacher","staff","parent" -SearchRoot $ou -SizeLimit 0 -Disabled | ForEach-Object{ $SamAccountName = $_.SamAccountName Write-Host "Deleting User: " $SamAccountName Delete-ADUser $SamAccountName } Get-QADUser -Title "student", "teacher","staff","parent" -SearchRoot $ou -SizeLimit 0 -PasswordNeverExpires $true -Disabled | ForEach-Object{ $SamAccountName = $_.SamAccountName Write-Host "Deleting User: " $SamAccountName Delete-ADUser $SamAccountName } So in effect two loops and its just erroring saying: Get-QADUser : Cannot bind parameter 'Identity'. Cannot convert value "True" to type "Quest.ActiveRoles.ArsPowerShellSna pIn.Data.IdentityParameter". Error: "Invalid cast from 'System.Boolean' to 'Quest.ActiveRoles.ArsPowerShellSnapIn.Data. IdentityParameter'." glnsize - I will have a look at it and throw it as my test boxes :) and I am not to sure on the ldap queries as I have never done them before could you show me an example as something to work off? Many Thanks James Many Thanks James |
|
|
|
|
James
 Basic Member Posts:374

 |
| 01 Jul 2010 07:52 AM |
|
Hello, glnsize I have just ran your code and its coming up with: C:\powershell\Scripts\new-Year.ps1 : A parameter cannot be found that matches parameter name 'Path'. At line:1 char:21 I am not entierly sure what its referring to... Could you shed any light on the issue? Many Thanks James |
|
|
|
|
James
 Basic Member Posts:374

 |
| 01 Jul 2010 07:58 AM |
|
Shay, Thanks for that I have changed my code! Many Thanks James |
|
|
|
|
Shay Levy PowerShell MVP, Admin
 Veteran Member Posts:1362

 |
|
glnsize
 Basic Member Posts:193
 |
| 01 Jul 2010 08:24 AM |
|
That's what I get for not testing it first... sorry about that I forgot the CmdletBinding statement... I updated the code.
Anyways Shay is you're man when it comes to the AD Stuff. I was more trying to highlight the work flow and some of the v2 features (comment based help, parameter binding, validation, etc...)
As an aside after going through this script... unless your domain is really massive (i don't think it is or your original script shouldn't have worked) your target should be -le 10 min. If this script takes longer than 10 min you still have some more optimizations to do.
Hope that helps, ~Glenn
p.s. sorry to script and run, but my wife would like to leave on vacation....
|
|
|
|
|
James
 Basic Member Posts:374

 |
| 01 Jul 2010 08:46 AM |
|
Thanks for that Shay! I just thought I could set them all to neverexpire before the script runs and then I dont have to go through and check again! :) But I will see what happens and failing that I will chuck it right in there! :) Our domain consists of 127 schools with information from all the parents, students, teachers and staff within each of the schools! 1 account per person! So were running a fair few accounts! So its pretty big! Thats fine I will have another pop with the code and post back my findings! :) Many Thanks James |
|
|
|
|