Came up with the below script to address the issue of delegated admins that don't stage their computer objects in AD. This script will delete any computer objects in the default Computer container. I scheduled a task to run every half hour that runs under an standard user account (that is a member of no admin groups but has delete access to the container). This way if the delegated admins brain dump and forget to the stage the system they don't have to call me to move it. They just have to wait a half hour before they can add it again.
#########################################################################
# Script Name: AD_Delete_Non_Staged_Computers.ps1
# Version: 1.0
# Author: Dean
# Last Edited: 06/28/2011
# Description: Deletes Non Staged Computers from Default Computers
# Container. Sends Email Report
#########################################################################
#Variable for System Count
$x = 0
#Email Message Body
$emsg = "<p>The following computer(s) were deleted from the Computers container:</p>"
#Email server
$smtpServer = "smtp.mycollege.edu"
#Get Current Short Date
$rptDate = Get-Date
#Query AD for All Computers in OU Computers Container
$objADSI = [ADSI]"LDAP://CN=Computers,DC=MYCOLLEGE,DC=EDU"
$Search = New-Object DirectoryServices.DirectorySearcher($objADSI)
$Search.filter = "(objectClass=computer)"
$Results = $Search.Findall()
#Remove Each Computer Object Listed in Results
foreach($result in $Results)
{
$x = $x + 1
$emsg = $emsg + $result.Properties["cn"][0].ToString().Trim() + "<br />"
$systemCN = "CN=" + $result.Properties["cn"][0].ToString().Trim()
$objADSI.Delete("computer", $systemCN)
}
if($x -gt 0)
{
#Settings for Email Message
$messageParameters = @{
Subject = "Deleted Computer Report " + $rptDate
Body = $emsg
From = "admins@mycollege.edu"
To = "admins@mycollege.edu"
SmtpServer = $smtpServer
}
#Send Email Message
Send-MailMessage @messageParameters –BodyAsHtml
}
Thursday, June 30, 2011
Sunday, May 22, 2011
PowerShell: AD Logged On Report
Saw a great post on finding logged on users via PowerShell by Ben Wilkinson
http://gallery.technet.microsoft.com/scriptcenter/d46b1f3b-36a4-4a56-951b-e37815a2df0c
Using Ben's script a starting point, I created a script that emails a logged on report for AD systems. This scripts queries AD for all computer systems that aren't disabled. For each of those AD systems it will ping the system before attempting the WMI command. Added a status field to the report for better troubleshooting of failed connections.
#####################################################################
# Script Name: AD_Logged_On_Report.ps1
# Version: 2.0
# Author: Dean
# Last Edited: 05/22/2011
# Description: Email Report of Logged On Accounts for AD Systems
#####################################################################
#Error Handling
$erroractionpreference = "SilentlyContinue"
#Variable for Email FROM Address
$mFrom = "reporter@my.company.net"
#Variable for EMail TO Address
$mTo = "report-Admins@my.company.net"
#Variable for SMTP Server
$smtp = "smtp.my.company.net"
#Get Current Short Date
$rptDate = Get-Date -Format d
#Array for Reporting Objects
$Summary = @()
#LDAP Search for All Computers in Specific OU
#Filtering on Computers That Aren't Disabled
$ADsPath = [ADSI]"LDAP://DC=MY,DC=COMPANY,DC=NET"
$Search = New-Object DirectoryServices.DirectorySearcher($ADsPath)
$Search.filter = "(&(objectClass=computer)(!userAccountControl=4130)(!userAccountControl=4098))"
$Search.SearchScope = "SubTree"
$ADSystems = $Search.FindAll()
foreach ($ADSystem in $ADSystems)
{
#Pull The Computer Name
$Computer = $ADSystem.Properties["cn"][0].ToString()
#Variables for System Status and Logged On Users
$strStatus = ""
$strLoggedOn = ""
#Ping Computer Before Attempting Remote WMI
if (test-connection -computername $Computer -quiet)
{
$strStatus = "Ping Successful"
#Retrieve Processes on Computer System via WMI Call
$processinfo = @(Get-WmiObject -class win32_process -ComputerName $Computer)
#If Process Listing Not NUll Then Find Processes Owned by Unique Non Default Accounts
if ($processinfo)
{
$users = $processinfo | Foreach-Object {$_.GetOwner().User} |
Where-Object {$_ -ne "NETWORK SERVICE" -and $_ -ne "LOCAL SERVICE" -and $_ -ne "SYSTEM"} |
Sort-Object -Unique
#ADD Unique Accounts to the Logged On Variable
if ($users)
{
foreach ($user in $users)
{
$strLoggedOn = $strLoggedOn + $user.ToLower() + " | "
}
}
#else
#{
#$strLoggedOn = "None"
#}
}
else
{
#Report WMI Call Failure
$strStatus = "WMI Failed"
}
}
else
{
#Report Ping Failure
$strStatus = "Ping Failed"
}
#Clean Up Logged On Variable
if($strLoggedOn.Length -gt 4)
{
$strLoggedOn = $strLoggedOn.Trim().TrimEnd("|")
}
#Create New PowerShell Object and Assign Data to It
$uEntry = new-Object PSObject
$uEntry | add-Member -memberType noteProperty -name "Computer Name" -Value $Computer.ToString().ToUpper()
$uEntry | add-Member -memberType noteProperty -name "Status" -Value $strStatus.ToString()
$uEntry | add-Member -memberType noteProperty -name "Logged On Users" -Value $strLoggedOn.ToString()
#Add Entry to Summary Array
$Summary += $uEntry
}
#Style for HTML Table in ConvertTo-HTML
$a = "<style>"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;}"
$a = $a + "TH{border-width: 1px;padding: 5px;border-style: solid;border-color: black;text-align: left;}"
$a = $a + "TD{border-width: 1px;padding: 5px;border-style: solid;border-color: black;text-align: left;}"
$a = $a + "</style>"
#Message Body
$emsg = $Summary | Sort-Object {$_."Computer Name"} | ConvertTo-Html -head $a | Out-String
#Settings for Email Message
$messageParameters = @{
Subject = "Logged On Report for " + $rptDate
Body = $emsg
From = $mFrom
To = $mTo
SmtpServer = $smtp
}
#Send Report Email Message
Send-MailMessage @messageParameters –BodyAsHtml
Write-Host "All Done"
http://gallery.technet.microsoft.com/scriptcenter/d46b1f3b-36a4-4a56-951b-e37815a2df0c
Using Ben's script a starting point, I created a script that emails a logged on report for AD systems. This scripts queries AD for all computer systems that aren't disabled. For each of those AD systems it will ping the system before attempting the WMI command. Added a status field to the report for better troubleshooting of failed connections.
#####################################################################
# Script Name: AD_Logged_On_Report.ps1
# Version: 2.0
# Author: Dean
# Last Edited: 05/22/2011
# Description: Email Report of Logged On Accounts for AD Systems
#####################################################################
#Error Handling
$erroractionpreference = "SilentlyContinue"
#Variable for Email FROM Address
$mFrom = "reporter@my.company.net"
#Variable for EMail TO Address
$mTo = "report-Admins@my.company.net"
#Variable for SMTP Server
$smtp = "smtp.my.company.net"
#Get Current Short Date
$rptDate = Get-Date -Format d
#Array for Reporting Objects
$Summary = @()
#LDAP Search for All Computers in Specific OU
#Filtering on Computers That Aren't Disabled
$ADsPath = [ADSI]"LDAP://DC=MY,DC=COMPANY,DC=NET"
$Search = New-Object DirectoryServices.DirectorySearcher($ADsPath)
$Search.filter = "(&(objectClass=computer)(!userAccountControl=4130)(!userAccountControl=4098))"
$Search.SearchScope = "SubTree"
$ADSystems = $Search.FindAll()
foreach ($ADSystem in $ADSystems)
{
#Pull The Computer Name
$Computer = $ADSystem.Properties["cn"][0].ToString()
#Variables for System Status and Logged On Users
$strStatus = ""
$strLoggedOn = ""
#Ping Computer Before Attempting Remote WMI
if (test-connection -computername $Computer -quiet)
{
$strStatus = "Ping Successful"
#Retrieve Processes on Computer System via WMI Call
$processinfo = @(Get-WmiObject -class win32_process -ComputerName $Computer)
#If Process Listing Not NUll Then Find Processes Owned by Unique Non Default Accounts
if ($processinfo)
{
$users = $processinfo | Foreach-Object {$_.GetOwner().User} |
Where-Object {$_ -ne "NETWORK SERVICE" -and $_ -ne "LOCAL SERVICE" -and $_ -ne "SYSTEM"} |
Sort-Object -Unique
#ADD Unique Accounts to the Logged On Variable
if ($users)
{
foreach ($user in $users)
{
$strLoggedOn = $strLoggedOn + $user.ToLower() + " | "
}
}
#else
#{
#$strLoggedOn = "None"
#}
}
else
{
#Report WMI Call Failure
$strStatus = "WMI Failed"
}
}
else
{
#Report Ping Failure
$strStatus = "Ping Failed"
}
#Clean Up Logged On Variable
if($strLoggedOn.Length -gt 4)
{
$strLoggedOn = $strLoggedOn.Trim().TrimEnd("|")
}
#Create New PowerShell Object and Assign Data to It
$uEntry = new-Object PSObject
$uEntry | add-Member -memberType noteProperty -name "Computer Name" -Value $Computer.ToString().ToUpper()
$uEntry | add-Member -memberType noteProperty -name "Status" -Value $strStatus.ToString()
$uEntry | add-Member -memberType noteProperty -name "Logged On Users" -Value $strLoggedOn.ToString()
#Add Entry to Summary Array
$Summary += $uEntry
}
#Style for HTML Table in ConvertTo-HTML
$a = "<style>"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;}"
$a = $a + "TH{border-width: 1px;padding: 5px;border-style: solid;border-color: black;text-align: left;}"
$a = $a + "TD{border-width: 1px;padding: 5px;border-style: solid;border-color: black;text-align: left;}"
$a = $a + "</style>"
#Message Body
$emsg = $Summary | Sort-Object {$_."Computer Name"} | ConvertTo-Html -head $a | Out-String
#Settings for Email Message
$messageParameters = @{
Subject = "Logged On Report for " + $rptDate
Body = $emsg
From = $mFrom
To = $mTo
SmtpServer = $smtp
}
#Send Report Email Message
Send-MailMessage @messageParameters –BodyAsHtml
Write-Host "All Done"
Friday, April 29, 2011
PowerShell: Set Mailbox Quota via AD Account Settings
Using only AD to set mailbox quota sizes.
#######################################################################
# Description: Set Mailbox Quota Sizes for Members of an AD Group
# 2GB Mailbox 2097152 and 1992294
# 1GB Mailbox 1048576 and 996352
#######################################################################
#Retrieve AD Group
$objGroup = [ADSI]"LDAP://CN=BioTech,OU=campusDepts,DC=MYDOMAIN,DC=edu"
#Create Array of Group Members
$objGroupMembers = $objGroup.member
foreach ($user in $objGroupMembers)
{
#Retrieve AD User Info
$userPath = "LDAP://" + $user
$objUser = [ADSI]$userPath
#Check to See of User Account Has a Mailbox
if ($objUser.homeMDB)
{
#Apply to Only Mailboxes with Default DB Setting or Lower Mailbox Quota Limit
if (($objUser.mDBUseDefaults -eq $true) -or ($objUser.mDBOverQuotaLimit -lt 2097152))
{
#Set Prohibit Send
$objUser.mDBOverQuotaLimit = 2097152
$objUser.setInfo()
#Set Issue Warning
$objUser.mDBStorageQuota = 1992294
$objUser.setInfo()
#Set Use Database Defaults Setting
$objUser.mDBUseDefaults = $false
$objUser.setInfo()
#Write Out Accounts Changed (Quick Logging)
Write-Host $objUser.sAMAccountName
}
}
}
Write-Host "All Done"
#######################################################################
# Description: Set Mailbox Quota Sizes for Members of an AD Group
# 2GB Mailbox 2097152 and 1992294
# 1GB Mailbox 1048576 and 996352
#######################################################################
#Retrieve AD Group
$objGroup = [ADSI]"LDAP://CN=BioTech,OU=campusDepts,DC=MYDOMAIN,DC=edu"
#Create Array of Group Members
$objGroupMembers = $objGroup.member
foreach ($user in $objGroupMembers)
{
#Retrieve AD User Info
$userPath = "LDAP://" + $user
$objUser = [ADSI]$userPath
#Check to See of User Account Has a Mailbox
if ($objUser.homeMDB)
{
#Apply to Only Mailboxes with Default DB Setting or Lower Mailbox Quota Limit
if (($objUser.mDBUseDefaults -eq $true) -or ($objUser.mDBOverQuotaLimit -lt 2097152))
{
#Set Prohibit Send
$objUser.mDBOverQuotaLimit = 2097152
$objUser.setInfo()
#Set Issue Warning
$objUser.mDBStorageQuota = 1992294
$objUser.setInfo()
#Set Use Database Defaults Setting
$objUser.mDBUseDefaults = $false
$objUser.setInfo()
#Write Out Accounts Changed (Quick Logging)
Write-Host $objUser.sAMAccountName
}
}
}
Write-Host "All Done"
PowerShell: Set AD User No Expiration
In specified OUs, this script sets all user accounts to not expire account or password.
#Array for OUs
$arrOUs = "LDAP://OU=campusUsers,DC=MYDOMAIN,DC=EDU",
"LDAP://OU=campusStudents,DC=MYDOMAIN,DC=EDU"
$i = 0
#Run Against All Users in Specified OU
foreach ($ou in $arrOUs)
{
$ADsPath = [ADSI]$ou
$Search = New-Object DirectoryServices.DirectorySearcher($ADsPath)
$Search.filter = "(objectClass=user)"
$Search.PageSize = 900
$Search.SearchScope = "SubTree"
$results = $Search.Findall()
foreach($result in $results)
{
#Retrieve User Account
$objUser = $result.GetDirectoryEntry()
#Set Account to Not Expire
$objUser.accountExpires = 0
$objUser.setInfo()
#Pull Password Settings and Convert to Int
$crtUAC = [int]($objUser.userAccountControl.ToString())
#If Account is Enabled and\or Requiring Password Change at Next Login
#Set Password Doesn't Expire
if (($crtUAC -eq 512) -or ($crtUAC -eq 544))
{
$objUser.userAccountControl = 66048
$objUser.setInfo()
}
#Same Thing for Disabled Account; However Leave Disabled
elseif ($crtUAC -eq 514)
{
$objUser.userAccountControl = 66050
$objUser.setInfo()
}
$i = $i + 1
write-host $i
}
}
Write-Host 'All Done'
#Array for OUs
$arrOUs = "LDAP://OU=campusUsers,DC=MYDOMAIN,DC=EDU",
"LDAP://OU=campusStudents,DC=MYDOMAIN,DC=EDU"
$i = 0
#Run Against All Users in Specified OU
foreach ($ou in $arrOUs)
{
$ADsPath = [ADSI]$ou
$Search = New-Object DirectoryServices.DirectorySearcher($ADsPath)
$Search.filter = "(objectClass=user)"
$Search.PageSize = 900
$Search.SearchScope = "SubTree"
$results = $Search.Findall()
foreach($result in $results)
{
#Retrieve User Account
$objUser = $result.GetDirectoryEntry()
#Set Account to Not Expire
$objUser.accountExpires = 0
$objUser.setInfo()
#Pull Password Settings and Convert to Int
$crtUAC = [int]($objUser.userAccountControl.ToString())
#If Account is Enabled and\or Requiring Password Change at Next Login
#Set Password Doesn't Expire
if (($crtUAC -eq 512) -or ($crtUAC -eq 544))
{
$objUser.userAccountControl = 66048
$objUser.setInfo()
}
#Same Thing for Disabled Account; However Leave Disabled
elseif ($crtUAC -eq 514)
{
$objUser.userAccountControl = 66050
$objUser.setInfo()
}
$i = $i + 1
write-host $i
}
}
Write-Host 'All Done'
PowerShell: AD Account Creation and Password Last Change Dates for Individual User
AD Account Creation and Password Last Change Dates for Individual User
# Variable for User ID
$userID = "myUserID"
#Create AD Searcher
$ADsPath = [ADSI]"LDAP://DC=MYDOMAIN,DC=EDU"
$Search = New-Object DirectoryServices.DirectorySearcher($ADsPath)
$Search.filter = "(&(objectClass=user)(sAMAccountName=" + $userID.ToString() + "))"
$Search.SearchScope = "SubTree"
$result = $Search.FindOne()
#Get AD User Account
$objUser = $result.GetDirectoryEntry()
#Check to See If Password Last Set has been Actually Set and Not Default Windows Time
if(($result.Properties["pwdlastset"][0].ToString() -ne "9223372036854775807") -and ($result.Properties["pwdlastset"][0].ToString() -ne "0"))
{
$pwdSetDate = [System.DateTime]::FromFileTime($result.Properties["pwdlastset"][0])
}
else
{
$pwdSetDate = "Not Set"
}
#Write Out User Info
Write-Host "Account Created: " $objUser.whenCreated.ToString()
Write-Host "Last Password Change: " $pwdSetDate
# Variable for User ID
$userID = "myUserID"
#Create AD Searcher
$ADsPath = [ADSI]"LDAP://DC=MYDOMAIN,DC=EDU"
$Search = New-Object DirectoryServices.DirectorySearcher($ADsPath)
$Search.filter = "(&(objectClass=user)(sAMAccountName=" + $userID.ToString() + "))"
$Search.SearchScope = "SubTree"
$result = $Search.FindOne()
#Get AD User Account
$objUser = $result.GetDirectoryEntry()
#Check to See If Password Last Set has been Actually Set and Not Default Windows Time
if(($result.Properties["pwdlastset"][0].ToString() -ne "9223372036854775807") -and ($result.Properties["pwdlastset"][0].ToString() -ne "0"))
{
$pwdSetDate = [System.DateTime]::FromFileTime($result.Properties["pwdlastset"][0])
}
else
{
$pwdSetDate = "Not Set"
}
#Write Out User Info
Write-Host "Account Created: " $objUser.whenCreated.ToString()
Write-Host "Last Password Change: " $pwdSetDate
Set Exchange Mailbox ActiveSync Policy for AD Group Members
One unit I support wanted a few AD groups to receive a specific ActiveSync security policy. Below is the script that quickly got it done.
#AD Setting for Multi Domain Forest
Set-ADServerSettings -ViewEntireForest $true
$Depts = "Group1","Group2","Group3"
ForEach ($Dept in $Depts)
{
(get-group $Dept).members | Set-CASMailbox –ActiveSyncMailboxPolicy "EDU Security for Mobile Devices"
}
#AD Setting for Multi Domain Forest
Set-ADServerSettings -ViewEntireForest $true
$Depts = "Group1","Group2","Group3"
ForEach ($Dept in $Depts)
{
(get-group $Dept).members | Set-CASMailbox –ActiveSyncMailboxPolicy "EDU Security for Mobile Devices"
}
PowerShell: Adjusting Configured Minimum Mailbox Quota
My new unit's Exchange environment had configured minimum mailbox quotas. Well they decided to up the range and we had to make sure all mailboxes were at least set the new minimum (which is this case was 500 MB).
#AD Setting for Multi Domain Forest
Set-ADServerSettings -ViewEntireForest $true
$mailboxes = get-mailbox -resultsize unlimited | select-object Name,Identity,ProhibitSendQuota,RecipientType,UseDatabaseQuotaDefaults
foreach ($mailbox in $mailboxes)
{
#Only Query User Mailboxes
if ($mailbox.RecipientType.ToString() -eq 'UserMailbox')
{
if ($mailbox.UseDatabaseQuotaDefaults -eq $false)
{
$quota = $mailbox.ProhibitSendQuota.Value.ToMB()
if($quota -lt 500)
{
#Write-Host $mailbox.Name.ToString()
set-mailbox -identity $mailbox.Identity -ProhibitSendQuota 500MB -IssueWarningQuota 475MB
}
}
}
}
Write-Host "All Done"
#AD Setting for Multi Domain Forest
Set-ADServerSettings -ViewEntireForest $true
$mailboxes = get-mailbox -resultsize unlimited | select-object Name,Identity,ProhibitSendQuota,RecipientType,UseDatabaseQuotaDefaults
foreach ($mailbox in $mailboxes)
{
#Only Query User Mailboxes
if ($mailbox.RecipientType.ToString() -eq 'UserMailbox')
{
if ($mailbox.UseDatabaseQuotaDefaults -eq $false)
{
$quota = $mailbox.ProhibitSendQuota.Value.ToMB()
if($quota -lt 500)
{
#Write-Host $mailbox.Name.ToString()
set-mailbox -identity $mailbox.Identity -ProhibitSendQuota 500MB -IssueWarningQuota 475MB
}
}
}
}
Write-Host "All Done"
Subscribe to:
Posts (Atom)