Posts Tagged Powershell

Taking Ownership of a Registry Key using Powershell

A while back we setup and installed QRadar as syslog server for our IT Infrastructure.  The system works pretty well, Linux and Unix hosts send syslogs to it.  Routers and Switches and other such devices are checked via snmp.  The real challenge was to get Microsoft 2008 R2 servers working with it.

The way it works with Microsoft, is that QRadar logs into a server with Admin rights, and creates a DCOM object that then fetches logs via WMI and sends them back to the QRadar Server.  This requires a very specific set of rights including the taking ownership of two registry keys that by default have the TrustedInstaller account as the owner.  Seeing as I need to do this as I setup new servers, as part of a auto install process I wanted to script the whole thing.

The big challenge was scripting a ownership change of the registry.  I ended up having to revert to some VB to make it happen.  However it all runs as a powershell script.  So here are the highlights and that part of the script.

Problem

  • Need to grant special permissions on a Registry Key via Script
  • Need to take ownership of a Registry Key via Script

Key Points

  • You must run this script as the user that is taking ownership
  • You can’t give ownership it must be taken thus the 1st bullet
  • Make sure to take a backup of your registry before you change it or permissions

Special thank you to Tome Tanasovski on the technet forms who wrote this originally, I just added comments and figured out how to make it work with a hive key I was interested in that had a special character in it.


function enable-privilege {
 param(
 ## The privilege to adjust. This set is taken from
 ## http://msdn.microsoft.com/en-us/library/bb530716(VS.85).aspx
 [ValidateSet(
 "SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege",
 "SeChangeNotifyPrivilege", "SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege",
 "SeCreatePermanentPrivilege", "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege",
 "SeDebugPrivilege", "SeEnableDelegationPrivilege", "SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege",
 "SeIncreaseQuotaPrivilege", "SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege",
 "SeLockMemoryPrivilege", "SeMachineAccountPrivilege", "SeManageVolumePrivilege",
 "SeProfileSingleProcessPrivilege", "SeRelabelPrivilege", "SeRemoteShutdownPrivilege",
 "SeRestorePrivilege", "SeSecurityPrivilege", "SeShutdownPrivilege", "SeSyncAgentPrivilege",
 "SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege", "SeSystemtimePrivilege",
 "SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege", "SeTrustedCredManAccessPrivilege",
 "SeUndockPrivilege", "SeUnsolicitedInputPrivilege")]
 $Privilege,
 ## The process on which to adjust the privilege. Defaults to the current process.
 $ProcessId = $pid,
 ## Switch to disable the privilege, rather than enable it.
 [Switch] $Disable
 )

## Taken from P/Invoke.NET with minor adjustments.
 $definition = @'
 using System;
 using System.Runtime.InteropServices;

public class AdjPriv
{
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct TokPriv1Luid
{
public int Count;
public long Luid;
public int Attr;
}

internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
public static bool EnablePrivilege(long processHandle, string privilege, bool disable)
{
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = new IntPtr(processHandle);
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
if(disable)
{
tp.Attr = SE_PRIVILEGE_DISABLED;
}
else
{
tp.Attr = SE_PRIVILEGE_ENABLED;
}
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
return retVal;
}
}
'@

$processHandle = (Get-Process -id $ProcessId).Handle
$type = Add-Type $definition -PassThru
$type[0]::EnablePrivilege($processHandle, $Privilege, $Disable)
}

enable-privilege SeTakeOwnershipPrivilege
#This is the Key to take ownership of, I left this in here as an example.  Note I had to change "ChangePermission" to "Take Ownership"
$key = [Microsoft.Win32.Registry]::ClassesRoot.OpenSubKey('CLSID\{76A64158-CB41-11D1-8B02-00600806D9B6}',[Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::TakeOwnership)

#You must get a blank acl for the key b/c you do not currently have access
$acl = $key.GetAccessControl([System.Security.AccessControl.AccessControlSections]::None)

#domain\user is the user that is going to take ownership
$me = [System.Security.Principal.NTAccount]"domain\user"
$acl.SetOwner($me)
$key.SetAccessControl($acl)

#After you have set owner you need to get the acl with the perms so you can modify it.
$acl = $key.GetAccessControl()

#Domain\user here is the one you are going to give permissions to
$rule = New-Object System.Security.AccessControl.RegistryAccessRule ("domain\user","FullControl","Allow")
$acl.SetAccessRule($rule)
$key.SetAccessControl($acl)

$key.Close()

Advertisements

,

3 Comments

Powershell Script to Delete Exchange Mailboxes in Mass

By Request: How to delete a large number of mailboxes at once.

First, and I can not stress this enough, this script has the potential to delete production data, namely user and Exchange mailboxes. Please carefully consider the impact of this script before you use it. Make sure you have good backups of your User Accounts and Exchange Mailboxes before use. If it doubt, test with a single account before hand and/or use the -whatif flag. (More about this below) Ok now then, on to the good stuff.

There are a few ways you might approach the task of deleting mailboxes. Much of that comes in the form of how you come up with the list of mailboxes and/or users to delete.

This example assumes the following approach:

  • You are creating a text file with a list of accounts to remove.
  • You want to delete both the user and the mailbox.

So then to create a list of user and their mailboxes you want to delete, simply place a list of users in a text file one user per line. You might fetch the list using a Get-QADuser or Get-Mailbox as a filter, more on this later.

Example text file:

jsmith
msmith
jlittle

etc

Call the file MailboxesToDelete.txt and we’ll assume its on the C:\ drive.  Then create a script to run, in this example I’ll call it Delete_Mailboxes.ps1

#Add Exchanage snapin
add-pssnapin Microsoft.Exchange.Management.PowerShell.Admin

#Get list of mailboxes to delete
$users=Get-Content C:\MailboxesToDelete.txt

#For Loop to delete them
foreach ($user in $users)
{
#Print to screen user mailbox to delete
$user
#Delete AD user and Mailbox
Remove-Mailbox -Identity $user -Permanent $true -whatif

#Remove the -whatif if you want to really delete some users.
}

That is pretty much it.

You should then be able to type [PS]C:> Delete_Mailboxes.ps1 and delete users and their mailboxes based on the text file.

You might also, assuming you have some search criteria, use the Get-QADuser or Get-Mailbox command to filter out the list of users. Say all of those in a specific OU and turn this into a single one liner.

Example:

Get-QADUser -SearchRoot 'OU=INTERNATIONAL OFFICE USERS,DC=contoso,DC=com' | Remove-Mailbox -Identity $user -Permanent $true

Or you could use my script and simply Get-QADUser -SearchRoot ‘OU=INTERNATIONAL OFFICE USERS,DC=contoso,DC=com’ >> C:\MailboxesToDelete.txt and then run the above script. Again there are many ways to approach the actual search/list creation. This is just a few ways you might do it.

Be warned:
The -Permanent $true will not only delete the mailbox, it will also delete the user. If you don’t want the user account deleted and just the mailbox just remove -Permanet from the above or set it to $false.

If you just want to test at the end of the Remove-Mailbox statement put a -whatif at the end of the line.

Example:
Remove-Mailbox -id jsmith -whatif

I added “-whatif” to the script to hopefully save someone some pain while testing.  Remove it only when you are ready to actually delete some data.

Please reference: Technet if you have questions about the Remove-Mailbox command, it is a delete command so use with care.


, , ,

13 Comments

Powershell – Active Directory CSV User list for an Audit

If you ever have someone come along and ask for a full list of AD users, and they want to know if an account is disabled, LastLogon etc etc for say a Audit of some sort.  Here then is a simple one liner using Quest Software (Link over on my links page) Powershell add-on to do just that and export it to a csv for use in Excel.

Example

C:\>get-qaduser | select-object DisplayName, Description, Department, Manager, LogonName, AccountIsDisabled, LastLogonTimestamp, PasswordExpires, ParentContainer | export-csv C:\AD_Users.csv -NoTypeInformation

Then import the AD_Users.csv to excel and delimited by commas.

If you are interested in some other field you can look at your options by listing all the attributes for a single users like so:

C:\>get-qaduser username | fl

Leave a comment

How to fix the issue of a user not showing up in the Global Address book.

This little one liner can possibly fix a issue where a user doesn’t show up in the Global Address book.

To run the following powershell script, you must be a Domain Admin and an Exchange Admin.

get-mailbox -resultsize unlimited | Where-Object {$_.PrimarySMTPAddress -ne $_.WindowsEmailAddress} 
| foreach { set-mailbox $_.identity -windowsemailaddress $_.primarySMTPAddress }

Explanation:
This Script will set the Email address field found in Active Directory Users and Computers for a User/Object that has a email account in Exchange to the same value as that set in Exchange as that of the User/Object’s primary SMTP email address.

This will fix the issues where the users doesn’t show up in the global address book.

Finally after running the script you must update the OAB in exchange and all clients must update their local address books by running send and receive.

MS Technet Support Article
http://support.microsoft.com/kb/936197

, , ,

Leave a comment

Powershell Script to Notify Users of Expired or About to Expire Passwords in Active Directory.

So where I work we use AD for single sign on (sso) for many of our systems both Windows and Nix. Some of our users only access the Nix systems and are not actually on our domain. They have no way of knowing when their passwords are about to expire and when their passwords do expire they just can’t log in without any visible reason why. In order to address that I started looking around the net for a powershell script and found one over at Dan Penning Blog but it didn’t address all of my needs. So using Dan’s script as the basis for a new script I came up with the following.

Synopsis of Goal:
Email the User when their password is about to expire or has expired and Supply a URL Link to reset their password.
Notify the Admin of certain conditions

  • Users Have Expired Passwords And No Primary SMTP Address to notify them
  • Users Password’s is About To Expire That Have No Primary SMTP Address
  • Users With Expired Passwords – Purely to report on it
  • Users Password’s About To Expire
  • Users with no Expiration Date

And Supply the Admin with the Location of the User account in question in the report.

Other Notes:
Included Options in the script without major rewrite

  • Adjust timing to being alerting (default is at 10 days start sending alerts to the user.)
  • Admin report is optional
  • Admin report can be sorted by Password Expiration, First, or Last Name.
  • Alerting Users is optional
  • Assign self service URL
  • Adjustable From Address and Relay Mail Server.
  • Change Font size and style for majority of text
#=====================================================================================================#
#    Copyright 2011 Robert Stacks
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#=====================================================================================================#
# Author: Robert Stacks
# URL: RandomTechMinutia.wordpress.com
# Updated: 06/21/2012
# Version: 1.2
#
# Based on a script by Dan Penning http://danpenning.com
#
# Purpose:
# Powershell script to find out a list of users
# whose password is expiring within x number of days (as specified in $days_before_expiry).
# Email notification will be sent to them reminding them that they need to change their password.
#
# Requirements:
# Quest ActiveRoles cmdlets (http://www.quest.com/powershell/activeroles-server.aspx)
# Powershell 2.0 ~ may work in 1.0 but I haven't tested it.
#
# Script must be run as a user with Permission to view AD Attributes, Domain Admin for example.
#
#=====================================================================================================#
#Add Snapins
Add-PSSnapin "Quest.ActiveRoles.ADManagement" -ErrorAction SilentlyContinue

#Get todays date for use in the script
$date = Get-Date

#===========================#
#User Adjustable Variables  #
#===========================#

# How many Days Advanced Warning do you want to give?
$DaysOfNotice = 10

#Generate a Admin report?
$ReportToAdmin = $true
#$ReportToAdmin = $false

#Sort Report
#===========================#
# 0 = By OU
# 1 = First Name Ascending
# 2 = Last Name Ascending
# 3 = Expiration Date Ascending
# 4 = First Name Descending
# 5 = Last Name Descending
# 6 = Expiration Date Descending
#===========================#
$ReportSortBy=1

#Alert User?
#$AlertUser = $true
$AlertUser = $false

#URL for self Service
$URLToSelfService = "http://"

#Mail Server Variables
$FromAddress = "DoNotReply@yourdomain.com"
$RelayMailServer = "mail.yourdomain.com"
$AdminEmailAddress ="Admin@yourdomain.com"

# Define font and font size
# ` or \ is an escape character in powershell
$font = "<font size=`"3`" face=`"Calibri`">"

# List of users whose Password is about to expire. The following line can be added to limit OU's searched if so desired
#$users += Get-QADUser -SearchRoot 'DN' -Enabled -PasswordNeverExpires:$false | where {($_.PasswordExpires -lt $date.AddDays($DaysOfNotice))}
#$users = Get-QADUser -SearchRoot 'OU= Company USERS,DC=contoso,DC=com' -Enabled -PasswordNeverExpires:$false | where {($_.PasswordExpires -lt $date.AddDays($DaysOfNotice))}
#$users += Get-QADUser -SearchRoot 'OU=INTERNATIONAL OFFICE USERS,DC=contoso,DC=com' -Enabled -PasswordNeverExpires:$false | where {($_.PasswordExpires -lt $date.AddDays($DaysOfNotice))}

# Search Whole Root
$users = Get-QADUser -Enabled -PasswordNeverExpires:$false | where {($_.PasswordExpires -lt $date.AddDays($DaysOfNotice))}

#===========================#
#Main Script                #
#===========================#

# Sort Report
Switch ($ReportSortBy)
{
'0' {$users}
'1' {$users = $users | sort {$_.FirstName}}
'2' {$users = $users | sort {$_.LastName}}
'3' {$users = $users | sort {$_.PasswordExpires}}
'4' {$users = $users | sort -Descending {$_.FirstName}}
'5' {$users = $users | sort -Descending {$_.LastName}}
'6' {$users = $users | sort -Descending {$_.PasswordExpires}}
}

if ($ReportToAdmin -eq $true)
{
#Headings used in the Admin Alert
$Title="<h1><u>Password Expiration Status and Alert Report</h1></u><h4>Generated on " + $date + "</h4>"
$Title+="<font color = red><h2><u>Admin Action Required</h2></u></font>"
$Title+="<font size=`"3`" color = red> An Admin needs to update these accounts so that users can be notified of pending or past password experation<br></font>"
$Title_ExpiredNoEmail="<h3><u>Users Have Expired Passwords And No Primary SMTP to Notify Them</h3></u>"
$Title_AboutToExpireNoEmail="<h3><u>Users Password's Is About To Expire That Have No Primary SMTP Address</h3></u>"
$Title2="<br><br><h2><u><font color= red>No Admin Action Required - Email Sent to User</h2></u></font>"
$Title_Expired="<h3><u>Users With Expired Passwords</h3></u>"
$Title_AboutToExpire="<h3><u>Users Password's About To Expire</h3></u>"
$Title_NoExpireDate="<h3><u>Users with no Expiration Date</u></h3>"
}
#For loop to report
foreach ($user in $users)
{

if ($user.PasswordExpires -eq $null)
{
$UsersList_WithNoExpiration += $user.Name + " (<font color=blue>" + $user.LogonName + "</font>) does not seem to have a Expiration Date on their account.<font color=Green> <br>OU Container: " + $user.DN + "</font> <br>"
}
Elseif ($user.PasswordExpires -ne $null)
{
#Calculate remaining days till Password Expires
$DaysLeft = (($user.PasswordExpires - $date).Days)

#Days till password expires
$DaysLeftTillExpire = [Math]::Abs($DaysLeft)

#If password has expired
If ($DaysLeft -le 0)
{
#If the users don't have a primary SMTP address we'll report the problem in the Admin report
if (($user.Email -eq $null) -and ($user.UserMustChangePassword -ne $true) -and ($ReportToAdmin -eq $true))
{
#Add it to admin list to report on it
$UserList_ExpiredNoEmail += $user.name + " (<font color=blue>" + $user.LogonName + "</font>) password has expired " + $DaysLeftTillExpire + " day(s) ago</font>. <font color=Green> <br>OU Container: " + $user.DN + "</font> <br><br>"
}

#Else they have an email address and we'll add this to the admin report and email the user.
elseif (($user.Email -ne $null) -and ($user.UserMustChangePassword -ne $true) -and ($AlertUser -eq $True))
{
$ToAddress = $user.Email
$Subject = "Friendly Reminder: Your Corporate Password has expired."
$body = " "
$body = $font
$body += "Greetings, <br><br>"
$body += "This is a auto-generated email to remind you (<font color=blue> " + $user.Name + "</font>) that your Corporate Password for account - <font color=red>" + $user.LogonName + "</font> - has expired. <br><br>"
$body += "This means you will not be able to access any secured system hosted at the Corporate Offices.<br><br> You can log into " + $URLToSelfService + " "
$body += "and reset the password yourself, else you are welcome to contact the Service Desk by Phone for assistance."
$body += "<br><br><br><br>"
$body += " "
$body += "<h4>Never Share Your Password With Others!</h4>"
$body += "<h5>Message generated on: " + $date + ".</h5>"
$body += "</font>"

Send-MailMessage -smtpServer $RelayMailServer -from $FromAddress -to $user.Email -subject $Subject -BodyAsHtml  -body $body

}
if ($ReportToAdmin -eq $true)
{
#Add it to a list
$UserList_ExpiredHasEmail += $user.name + " (<font color=blue>" + $user.LogonName + "</font>) password has expired " + $DaysLeftTillExpire + " day(s) ago</font>. <font color=Green> <br>OU Container: " + $user.DN + "</font> <br><br>"
}
}
elseif ($DaysLeft -ge 0)
{
#If Password is about to expire but the user doesn't have a primary address report that in the Admin report
if (($user.Email -eq $null) -and ($user.UserMustChangePassword -ne $true) -and ($ReportToAdmin -eq $true))
{
#Add it to admin list
$UserList_AboutToExpireNoEmail += $user.name + " (<font color=blue>" + $user.LogonName + "</font>) password is about to expire and has " + $DaysLeftTillExpire + " day(s) left</font>. <font color=Green> <br>OU Container: " + $user.DN + "</font> <br><br>"
}
# If there is an email address assigned to the AD Account send them a email and also report it in the admin report
elseif (($user.Email -ne $null) -and ($user.UserMustChangePassword -ne $true) -and ($AlertUser -eq $True) )
{
#Setup email to be sent to user
$ToAddress = $user.Email
$Subject = "Notice: Your Corporate Password is about to expire."
$body = " "
$body = $font
$body += "Greetings, <br><br>"
$body += "This is a auto-generated email to remind you (<font color=blue> " + $user.Name + "</font>) that your Corporate Password for account - <font color=red>" + $user.LogonName + "</font> - will expire in </font color = red>" + $DaysLeftTillExpire +" Day(s). <br><br>"
$body += "This means you will not be able to access any secured system hosted at the Corporate Offices.<br><br> You can log into " + $URLToSelfService + " "
$body += "and reset the password yourself, else you are welcome to contact the Service Desk by Phone for assistance."
$body += "<br><br><br><br>"
$body += "<h4>Never Share Your Password With Others!</h4>"
$body += "<h5>Auto-Generated Message On: " + $date + ".</h5>"
$body += "</font>"

Send-MailMessage -smtpServer $RelayMailServer -from $FromAddress -to $user.Email -subject $Subject -BodyAsHtml  -body $body

}
if ($ReportToAdmin -eq $true)
{
#Add it to admin Report list
$UserList_AboutToExpire += $user.name + "  <font color=blue>(" + $user.LogonName + "</font>) password is about to expire and has " + $DaysLeftTillExpire + " day(s) left</font>. <font color=Green> <br>OU Container: " + $user.DN + "</font> <br><br>"
}
}
}
} # End foreach ($user in $users)

if ($ReportToAdmin -eq $true)
{
If ($UserList_AboutToExpire -eq $null)  {$UserList_AboutToExpire = "No Users to Report"}
If ($UserList_AboutToExpireNoEmail -eq $null){ $UserList_AboutToExpireNoEmail = "No Users to Report"}
if ($UserList_ExpiredHasEmail -eq $null) {$UserList_ExpiredHasEmail = "No Users to Report"}
if ($UserList_ExpiredNoEmail -eq $null) {$UserList_ExpiredNoEmail = "No Users to Report"}
if ($UsersList_WithNoExpiration -eq $null) {$UsersList_WithNoExpiration = "No Users to Report"}

#Email Report to Admin
$Subject="Password Expiration Status for " + $date + "."
$AdminReport = $font + $Title + $Title_ExpiredNoEmail + $UserList_ExpiredNoEmail + $Title_AboutToExpireNoEmail + $UserList_AboutToExpireNoEmail + $Title_AboutToExpire + $UserList_AboutToExpire + $Title_Expired + $UserList_ExpiredHasEmail + $Title_NoExpireDate + $UsersList_WithNoExpiration + "</font>"
Send-MailMessage -smtpServer $RelayMailServer -from $FromAddress -to $AdminEmailAddress -subject $Subject -BodyAsHtml -body $AdminReport
}



Sample Email to the user.

Sample of Admin Report

Updated on May 1, 2012

Added feature to sort Admin report by First Name, Last Name, or Password Expiration Date.

Updated on June 21, 2012

Minor code revision to fix logic errors, still debugging/testing.

, ,

62 Comments

Add permissions to public folders in Exchange 2007

So say you want to add permissions to a large group of public folders. Unlike Windows folders, public folders do not replicate permissions down through a tree. So the trick is to recursively go through the tree and apply permissions to the folders. This can be done with a very simple one liner.

Note:You want to run this on the Exchange server with the Mailbox role that houses the Public Folder database.

Example:

[PS] C:\Windows\system32>Get-PublicFolder "\IS Department\Software Installs" -recur 
| Add-PublicFolderClientPermission -user lmichel -accessrights Owner

So if you had a folder structure like

Public Folders
  -> IS Department
        -> Software Installs
            -> Lots of folders
  -> Marketing
  -> etc etc..

Then we just gave jsmith permissions to all of the “Lots of folders” under software installs. If you wanted you could go back a single tree or go further down the tree depending on your needs.

, , ,

Leave a comment

Remove Disconnected Mailbox – Exchange 2007

A simple bit of Powershell to remove a Disconnected Mailbox. Normally Exchange will take care of this itself at the predetermined time as set under Database properties, under the limit tab, via the GUI or via Exchange Powershell

[PS]C:\> Get-MailboxDatabase "ExchangeClusterName\DatabaseName" | fl DeletedItemRetention

Note: You must run this on a mailbox server.

This just tells Exchange to hold onto deleted mailboxes for x number of days at which point permanently delete the mailbox. So that said what if you have a really large mailbox that you want to delete, or a mailbox you want to remove more quickly, for some other reason. In that case you can’t use the Exchange gui to select and delete them, instead you’ll need to ID the disconnected mailbox by its Name and then reference its GUID to delete it. The commands to do so are listed below. Nothing fancy here just two lines of code.

You need to make sure the Exchange\DatabaseName is the one where the mailbox actually was stored otherwise nothing will happen.

[PS] C:\> $Temp = Get-MailboxStatistics | Where {$_.DisplayName -eq "John Doe"}
[PS] C:\> Remove-Mailbox -Database "ExchangeClusterName\DatabaseName" -StoreMailboxIdentity 
$Temp.MailboxGuid

, ,

Leave a comment

Exchange 2007 Powershell Mailbox Export to PST in Mass

So today I was asked to delete a bunch of email accounts off of Exchange that were tied to users that are no longer with the company. Due to the security requirements we follow where I work, we have to maintain a list of users that previously worked for the company. We maintain them in a Disabled User OU in AD to easily ID said users. However we are not required to maintain email for nearly as long, so we were asked to make a backup of the mailbox’s to PST files, just in case, and put them on a drive and into a vault prior to removal of the emails. In this 1st run after the policy was created we found we had a bunch of mailboxes to export so we came up with a simple one liner to do this for us.

To that end we used Powershell to export the users in the “Disabled OU” in AD and find any mailboxes associated with those users and export them.

The requirements to make this work under Exchange 2007 are a bit of a pain if you are running Windows 7 64bit those requirements are listed below.

A Windows 7 32bit machine
Exchange tools (sp1) installed on the local machine
Outlook 32bit installed

Once you have that you can actually run the Exchange Powershell script I used:

[PS] C:\>Get-Mailbox -OrganizationalUnit "domain/Disabled User OU" | 
add-mailboxpermission -accessrights fullaccess -user ADAdminAccount -confirm:$false | 
Export-Mailbox -PSTFolderPath "C:\Path\"

So this script, goes in and retrieves a list of mailboxes in a given OU, grants the user running the script “ADAdminAccount” permission to export the mail, and then exports it to a local drive with one pst file per user in the OU in question. Very handy.

, ,

5 Comments

Exchange Powershell Script – Mailbox Size Daily Report

One of the things I like to monitor on a daily basis is mailbox sizes.  Quota’s or no, it helps you figure out who your big storage crunchers are, and can be used as a education tool for management to better understand just how much storage is being used and where when it come to exchange.

I wrote this script when I 1st got into using Powershell and I’ve no doubt there are tools to make it prettier but in the end this is small and very functional.

#Print the date to the email

date > C:ScriptsMailboxsize1.txt

#Put in some line returns for a cleaner look

echo "`n`n" >> C:ScriptsMailboxsize1.txt

#Report the size of each mailbox on the exchange server in GB

Get-MailboxStatistics -server exchccr | Sort-Object TotalItemSize -Descending | ft DisplayName,@{label="TotalItemSize(MB)";expression={$_.TotalItemSize.Value.ToMB()}},Itemcount >> C:ScriptsMailboxsize1.txt

#Email out results

$date = get-date

$content = get-content C:ScriptsMailboxsize1.txt

$body = $content[1]

$i=2;do {$body=$body + $content[$i] + "`n";$i+=1} While ($content[$i] -ne $NULL);

Send-MailMessage -To users@mydomain.com -From ExchangeServer@mydomain.com -Subject "User Exchange Mailbox Sizes for $date" -Body $body -SmtpServer relayserver.mydomain.com

The results look something like this

Wednesday, October 12, 2011 8:00:04 AM

DisplayName                         TotalItemSize(MB)                 ItemCount
-----------                         -----------------                 ---------
User1                                           12109                     92101
User2                                           11259                    141870
User3                                            9812                    128396

etc

Again just some useful information you might want to report on.

, , , , ,

Leave a comment