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.


  • 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 {
 ## The privilege to adjust. This set is taken from
 ## http://msdn.microsoft.com/en-us/library/bb530716(VS.85).aspx
 "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")]
 ## 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;
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"

#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")



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:



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
#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.


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.

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.

PDFCreator – Handy PDF Print Server for Free

Recently I was asked to address a problem where remote users wanted to be able to print from a legacy Unix/Pick system that normally uses IP based printers.  The remote users connecting to the office using a client side VPN solution didn’t have access to a IP based Printer at home and needed another solution to get their printouts.  Management also didn’t want to spend a ton of money on the solution.  Working with the Unix team I came up with the solution to deploy a Microsoft Windows based PDF printer solution using PDFCreator (http://www.pdfforge.org/pdfcreator).  PDFCreator allows you to setup multiple printers that can be pre-configured to print PDFs to a specific file share that you as an admin can then manage share/file permission as normal.  Another benefit, you can configure these PDFs to be encrypted and have a password on them.  You can also manage if the PDFs can be printed or copied etc.

We ended up deploying this on its own file and print server and then mapping the users computers to their own individual share.  Then on the unix side we instructed them to print to a printer that was pointed back to a PDF printer set to print to their share.  Each user has their own PDF password as well to insure if they print to the wrong printer/share someone else couldn’t open their files.

Then I setup a simple windows script to wipe files contained in the shares older than 7 days.

There are a few catches which are not well covered in documentation which I outline below:

Here is a diagram sort of outlining what I’m talking about

The 1st Catch you need to setup PDFCreator to run as a service.  A good how to can be found over on this blog here.  In short:

  1. Install the Server 2003 resource kit (link).
  2. Create the service with SC:sc create pdfcreator start= auto binPath= “C:\Program Files\oldResourceKitTools\srvany.exe” DisplayName= “PDFCreator”Note the space between the equals sign and the value; it actually needs to be done that way, or SC won’t work.
  3. Check that that worked:sc query pdfcreator
  4. Mangle the service appropriately to actually run the server version of PDFCreator:Start the service and test it out – a file sent to the PDFCreator printer on the server should now pop out in whichever directory you specified back in step 1, regardless of whether or not anyone’s logged in at the server’s console.
    • Edit the key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\pdfcreator.
    • Add a “Parameters” key.
    • Inside the newly-created key, add a REG_SZ value called “Application”, with the path to the PDFCreator executable as the data.
  5. Start the service and test it out – a file sent to the PDFCreator printer on the server should now pop out in whichever directory you specified back in step 1, regardless of whether or not anyone’s logged in at the server’s console.

The next Catch,  how to set a password on a individual PDF printer, again you have to edit the registry

So for example if you setup a printer and call it prITTEST (Used in my Example)  You would need to edit the key found at HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\PDFCreator\Profiles\prITTEST\Printing\Formats\PDF\Security

Then set the PDFOwnerPasswordString and PDFUserPasswordString with a password.  You also need to enable security by setting PDFOwnerPass, PDFUserPass, and PDFUseSecurity to 1.

One last thing of note, when installing PDFCreator, the ESET AV solution we use in the office reported the program containing a virus.  That said I tested the .exe using several other products and I think this is a false positive.  Likely flagging the Windows Tool bar it wants to install as spam-ware.

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
#    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

#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.

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.


[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.

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


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