So You Thought PowerShell Was Only For Exchange 2007

PowerShell makes a lot of sense as a means of gathering information, and automating large sections of your administration tasks. It is not just for the latest version of Exchange, though. Powershell can be used on previous versions too. Jonathan Medd gets you started!

Introduction

When Microsoft released Exchange 2007 they built the Exchange Management Console on top of Windows PowerShell 1.0; when you execute commands from the console, underneath it uses PowerShell cmdlets to carry out the requested actions. Exchange 2007 SP1 ships with around 400 native PowerShell cmdlets to efficiently configure, manage and automate your messaging environment; everything from mailbox and database management, through junk mail settings and public folders. Whilst this has been a fantastic move forward for those organisations who have either migrated from previous Exchange versions or other messaging platforms or even a completely fresh Exchange 2007 installation not every Exchange administrator is lucky enough to be in that boat and may well still be managing an Exchange 2003 (or earlier) environment.

The aim of this article is to demonstrate how you can use standard PowerShell techniques to query information stored in Event Logs, WMI and Active Directory to make management of your pre-Exchange 2007 environment more efficient than with the standard GUI based tools provided.

What Do I Need To Get Started

Installation of Exchange 2007 has a dependency on Windows PowerShell 1.0 being installed on the server so that you are able to execute commands from the Exchange Management Console. For the purposes of what we are going to look at it is not recommended that you install PowerShell on your Exchange 2003 server, rather install it on your management workstation. (It would be unlikely to cause an issue on your Exchange 2003 server, but it’s not good practise to install unnecessary software there).

On your management workstation you require the following:

  • Windows XP (or above)
  • .NET Framework 2.0 or above
  • PowerShell – installed by default on Windows 7 SP1 and later, and on Windows Server 2008 R2 SP1 and later
  • For the WMI queries we are going to run you will need to provide an account with local admin rights on the Exchange Server since that is a requirement for remote WMI access

Querying Event Logs Using WMI

Later on we’ll come onto using some of the Exchange specific WMI classes which are available to us for extracting information from an Exchange server, but for now I will show you how you can use WMI to query the Event Logs on any Windows based server.

Windows Management Instrumentation (WMI) is the infrastructure for management data and operations on Windows-based operating systems, think of it as a database of the OS. You may have previously used other tools for querying WMI such as WMIC or VBScript and consequently not had the easiest experience with WMI – I recently heard WMI described as ‘Voodoo’! It doesn’t need to be like this either with the previously mentioned tools or best of all with PowerShell which makes WMI your friend.

Using the PowerShell cmdlet Get-WmiObject you can query WMI on local or remote computers and easily obtain valuable results. For instance with a very simple example you could use Get-WmiObject Win32_ComputerSystem to return information about the local computer.

716-so_you23.gif

PowerShell by default will return a standard set of properties for the WMI class you have queried as above, however there are typically many more properties hidden away underneath which can be exposed. You can pipe the results of your WMI query to the  Format-Listcmdlet to discover what  properties are available to you.

716-so_you10.jpg

Now you know what’s available you can stipulate the particular properties you wish to display. PowerShell will then only output the results for the information you are specifically interested in.

716-so_you11.jpg

Moving on, we can now use some slightly more advanced techniques to query the event logs on remote machines. If you are an experienced Exchange administrator it is likely that at some point you will have taken your mailbox databases offline so that they can be defragged to reclaim the white space inside them. In a large environment you may have hundreds of databases and looking for candidates for defragging could be a time consuming process, typically you would use an event log entry similar to that below from the Application log which shows how much free space is in a database after the online defragmentation process has completed. You would not want to manually browse through these records on multiple Exchange servers over multiple mailbox stores.

716-so_you12.gif

Instead, it is far better to use PowerShell to query those entries in the event logs and return to you only the information you need. For instance, give you only those databases which have over 2GB free space in them. The following command will carry out most of this work for you:

(Do not worry too much about $WmidtQueryDT, it’s supplied for you in the full script file, Get-FreeSpace.ps1, where we use some .NET code to get a date into a format that WMI likes)

Step-by-step we use the:

  1. Get-WmiObject cmdlet to query the remote server ExchangeServerName by using the -computer parameter
  2. Use the query parameter to specify a SQL style query
  3. Select everything from the Win32_NTLogEvent WMI class
  4. Filter it on the Application Log
  5. Filter it on Event ID 1221
  6. Filter it on the last 24 hours – this assumes that you run online maintenance on your databases daily

This will return the information we need. In the script file we then run some extra code to read those log files and filter it down so that only those whose Message Text includes a value over 2GB and export the results to a CSV file ready for use.

Exchange 2003 WMI classes

When you install Exchange 2003 some additional WMI classes will be added specific to Exchange information which you are able to query. These are documented on MSDN (http://msdn.microsoft.com/en-us/library/ms876479(EXCHG.65).aspx ) where you can find full details of what they have to offer and some VBScript examples of how you might use them. (Note: these classes have been removed from Exchange 2007 and above) Fortunately for you I’m going to show you how to use them in PowerShell instead. The best one to start with is the Exchange_Mailbox class.

So far I have not mentioned WMI namespaces. In the previous examples the WMI classes we have been using are all part of the default WMI namespace Root\CIMV2. Since it’s the default, PowerShell assumes that’s the namespace you wish to use if you don’t specify one. The Exchange 2003 classes do not live in this namespace; they belong to the root\MicrosoftExchangeV2 namespace, so when using the Get-WmiObject cmdlet with these classes we must use the namespace parameter. A simple command to query an Exchange server about its mailboxes is the following:

This will return information about mailboxes across all Mailbox Stores on the specified Exchange server. By using a couple of additional standard PowerShell cmdlets we can produce more readable output. Firstly we can use the Sort-Object cmdlet and specify the property MailboxDisplayName so that the mailboxes are returned in alphabetical order. Then we can use Format-Table to specify which properties are returned.

The below example shows the kind of results this would produce.

716-so_you13.jpg

A common scenario for Exchange management is the demand from users for large mailboxes and consequently lots of storage. Your manager may well want to know who is using up all the extra storage he only just paid for last month that you told him you needed. Using the GUI Exchange tool it is not easy to aggregate this information across your server farm if you have multiple databases over many Exchange servers. However, we can take the previous example, make some modifications to it and hey presto you will have the report for your manager.

This time instead of sorting by MailboxDisplayName we sort by the Size of the mailbox, then we use the Select-Object cmdlet and use the -First parameter to return only a subset of the results – in this case 10. This will give us the top 10 largest mailboxes (you can obviously adjust the number of results returned to suit your needs). Since we return the Exchange Servername, Storage Group and Mailbox Store it also makes it simple to track these mailboxes down.

716-so_you14.jpg

It’s not just mailbox data we can query though with Get-WmiObject, another useful Exchange WMI class is the Exchange_Logon class. Not surprisingly this will tell us about who is logged into Exchange and other useful information like what client they are using, for instance you might wish to report on which of your users are logged in using Outlook Web Access.

This time we use the -filter parameter of Get-WmiObject to return a restricted amount of data, in this case where the ClientVersion reported by the Exchange_Logon class matches ‘HTTP’ ; we also exclude entries where the LoggedOnUser is NT Authority\System which is something we are obviously not particularly interested in. We may well get multiple results per user returned via the Exchange_Logon class for the same client connection so when sorting the data with Sort-Object we use the -unique parameter so that we only get one relevant result in the output.

716-so_you24.jpg

(In the demo environment used for this article I was not able to simulate multiple logons, but you can imagine the kind of output you would receive in a larger environment.)

As an Exchange administrator another common best practise is to keep mailboxes spread evenly over Mailbox Stores and Storage Groups as best is possible. To do that though you need the information easily to hand of the number of mailboxes across these areas; again the out of the box Exchange GUI tools do not help you with this task, particularly across large environments. PowerShell can again come to your rescue and very simply provide this information.

We use the Exchange_Mailbox class again, but this time instead of returning names, locations and sizes of mailboxes we count the results and return that data. We store in a text file the names of the Storage Groups we are interested in (as below) and use the Get-Content cmdlet to store these names into a variable.

716-so_you15.jpg

We then use a foreach statement to loop through each of these Storage Groups and count the number of mailboxes in each one. You will see below that the WMI query is filtered on the StorageGroupName property and the entire command is encapsulated in brackets with .count added at the end to give us the total in that query. Finally Write-Host is used to display some text and the results to the screen.

716-so_you16.jpg

It doesn’t take a genius to extend this to be more granular and look at Mailbox Stores instead of Storage Groups.

Provide your list of Mailbox Stores to PowerShell with

716-so_you17.jpg

Then use a foreach statement to loop through each of the stores and return the number of users in each one.

716-so_you18.jpg

Querying Active Directory to Determine Exchange Information in a Network

Another way we can use PowerShell to garner information about our Exchange environments is to query Active Directory which stores a lot of Exchange configuration information. One of the ways to do this is to use a couple of classes within the .NET DirectoryServices Namespace which is a .NET wrapper for ADSI (http://msdn.microsoft.com/en-us/library/system.directoryservices(VS.71).aspx ), in particular the DirectoryEntry and DirectorySearcher classes.

I have heard stories of administrators being put off getting into PowerShell because they’ve been told that you need to be a .NET programmer to use it – this is so not true. You don’t need to know any .NET to effectively use PowerShell, however PowerShell does have access to .NET so it can be to your advantage and potentially open a few doors if you just explore some of the basics.

In this example we are going to query Active Directory to find out the names of the Exchange servers in our environment. First of all we create a DirectoryServices.DirectoryEntry object for the current Active Directory domain.

Then we use ADSI to get a reference to the configuration naming context within AD. All Exchange information in AD (except for per-recipient information) is in the configuration naming context.

Create a directory search object

Filter the search on the Exchange  Server objectclass

Use the FindAll method to execute the search

Finally, return the names of all the results.

In my demo environment there is only one Exchange server so the results are not particularly exciting, however you can imagine how useful this could be in a large deployment of Exchange servers.

716-so_you19.jpg

To save typing all of those lines out each time you want to run the code you could turn it into a filter like this:

and then you can either include it in a script or if it’s something you might run regularly then include it in your PowerShell profile (http://www.microsoft.com/technet/scriptcenter/topics/winpsh/manual/profile.mspx ).

Note: a filter is similar to a function in PowerShell, however it enables you to take advantage of the pipeline.

What we have now though is something potentially very powerful. By putting the GetExchangeServers filter together with one of our earlier WMI queries we can now run that query against all of our Exchange Servers without even having to specify their names!

To find the top 10 largest mailboxes on each Exchange server run the GetExchangeServers filter and pipe it to the Get-WmiObject command.

Other objectclasses you could also query in Active Directory include:

Storage Groups: msExchStorageGroup

Mailbox Databases: msExchPrivateMDB

Public Folder Databases: msExchPublicMDB

Simply replace the value for the objectclass in the $searcher.filter line.

Exchange 2003 Powerpack for PowerGUI

You might be reading this article and thinking “Well this scripting stuff is all very well, but it’s really not for me, I’m a GUI kind of administrator and what I’d really like is someone just to package up all these scripts for me and let me run them from the click of a button”.

If that’s you then you are in luck because Quest has created a tool to make that dream a reality by creating a fabulous free tool called PowerGUI (http://powergui.org). Not only do you get a brilliant scripting editor (yes for free) the package also includes a tool which lets you create custom management consoles. So say you don’t like the console which ships with Exchange or it has something missing and you don’t want to wait for the next product release, you can create your own console by packaging up PowerShell scripts into PowerPacks – or even better download one which somebody else has already created for you.

Simply download and install PowerGUI, then head over to the PowerPacks part of the site (http://powergui.org/kbcategory.jspa?categoryID=21) and you will find many pre-made PowerPacksfor a variety of different products including Exchange, SQL, VMware, Citrix, etc ready to download.

The PowerPacks are completely open so you can modify / add / delete any part of them to make it more suitable for your own environment. However, as of version 1.7 it is also now possible to lock down and brand a PowerPack, for instance if you wanted to provide one for helpdesk use.

I made a PowerPack for Exchange 2003 (http://powergui.org/entry.jspa?externalID=1956&categoryID=47) which when plugged into PowerGUI will give you easy access to most of the scripts already mentioned in this article plus many more which you can see below.

716-so_you20.jpg

Simply click one of the script nodes and the script will go off and do its work in the background and return the results into the grid pane. For instance if you chose ‘Top 10 Largest Mailboxes Per Server’ the exact same PowerShell script as previously mentioned will be used and you will see the results like below.

716-so_you21.jpg

Included is a section for managing the user and groups part of Exchange management. These require the AD PowerShell cmdlets also provided free by Quest (http://www.quest.com/activeroles-server/arms.aspx). A good example for their use would be the node ‘Get-EmptyDistributionGroups’. It’s pretty common for a distribution group to be set up for short-term use, say for a project and then at the end of the project people are removed from the group, but nobody ever thinks to tell the administrator that the group is no longer needed. Simply run this PowerShell script and it will give you a list of all distribution groups which are empty – it’s even got a Delete button so that you can remove them from the same console.

716-so_you22.jpg

Conclusion

So you have seen that just because you may not be using Exchange 2007 you don’t have to be a second-class citizen in terms of managing Exchange from scripts or the command line.

Using PowerShell and underlying technologies like WMI and Active Directory you can quickly and simply gather information from your Exchange environment where using the standard GUI tools for the same tasks requires far more manual effort. Make one further step by scheduling these scripts to run and you will soon be automating large sections of your admin tasks and  be free to get on with those interesting projects you never have time to work on.