While working with (playing around with) PowerShell on Exchange 2007 I found myself typing in the same series of commands over and over. These were commands that I was using on a regular, repeated basis while managing my particular environment. Being the efficient (lazy?) person that I am, I did a bit of quick reading and found the Windows PowerShell profile.

The windows PowerShell profile is a special .ps1 file that PowerShell will load when you initially start your session. PowerShell will automatically load any aliases, function, or variables defined in this file. The profile can be defined on a per system or per users basis. For more in depth information on the Windows PowerShell profile check out this MSDN article http://msdn2.microsoft.com/en-us/library/bb613488.aspx .

For my profile.ps1 I wanted to cover some of the basics and eliminate some of the annoyances that I was having when working with my systems. So I wrote six small functions that help me with the day to day workings of Exchange in PowerShell.

Functions: fhelp and ehelp

In the PowerShell beta when you typed "help <cmdlet>" you would get the full help output, all big and messy with all of the parameters and everything you ever wanted to know about the cmdlet. For the release version "help <cmdlet>" will just get you the basic quick help. When I am writing a script many times I need the full help for more information about the switch I am using. Thus the fhelp function was born.

Typing "fhelp <cmdlet>" will give you the full help just like in the beta days; and it is much faster than typing out "help <cmdlet> -full".

This is a very simple function that just takes the input parameter of the cmdlet name and runs "help $cmdlet –full" thus saving me from a bit of typing.

The ehelp function works exactly the same way as fhelp but it gives you the examples rather than the full help. I zipped this one out about two weeks after fhelp after catching myself trying to scroll down to get to the example section after running fhelp against a cmdlet.

Functions: Dismount-alldatabase and mount-alldatabase

This function probably doesn't have that much usefulness outside of a test lab but I do use it in my environment to quickly dismount all databases on a server.

The dismount-alldatabase function is just two long piped together commands. One to dismount all of the mailbox databases and one to dismount any public folder databases that maybe on the server. Both commands are basically the same they just start out with get-publicfolderdatabase vs. get-mailboxdatabase.

In either case I use the –status parameter on the get cmdlets to force them to query the store so I can get the database's mounted status. Then we pipe that into a where command to filter it down to just the currently mounted database (this is mostly so I don't see a bunch of error messages for databases that are already dismounted). Finally using the foreach-object cmdlet we take that and generate a screen output to tell you what database we are dismounting then we dismount that database.

The neat thing here with the foreach cmdlet is that you can perform multiple operations on the same input data simply by use the ";" to terminate each individual statement within the script block. This allowed me to output common warning text in yellow "Dismounting database", followed by the identity of the database we were about to work on, and then perform the task to dismount the database all within the same script block. (What can I say... I like screen feedback as to what is happening)

The mount-alldatabase function works almost exactly the same way. But rather than filtering out for what databases are mounted, I filter for what databases are dismounted and then run mount-database rather than dismount-database, oh and the text is green rather than yellow.

Function: Reset-eventloglevel

This function was born out of some frustration with diagnostic logging in Exchange 2007. It isn't too bad to go and turn up a given set of diagnostics categories (and each set that I have to turn up is unique). But going back and resetting them to the default values when you are done is something that I do over and over and since the defaults aren't all lowest is something that requires multiple lines to accomplish.

Thus another simple function that goes and gets all objects that have an event log level higher than lowest and sets them to lowest. Then we just go back and set the two that don't default to lowest back to their default values of low.

Easy to write, quick to implement, and it saves me tons of typing when I have to get everything back to default.

Function: set-sharedmailboxpermissions

I don't really use this one in my environment but I thought I would throw it in after a customer asked me about it. Setting shared mailbox permission for normal users is something that folks who have exchange integrated services like Unity or BlackBerry might have to do on a normal repeated basis. Here is where a function that does the process for you can really help out.

This function structure is very straight forward. I simply take two inputs. The mailbox you want to be able to access and the user you want to grant that access to. Then we set the two permissions needed per the article How to Allow Mailbox Access.


I hope this has provided everyone with an understanding of how the PowerShell profile works and given you some functions that you can use to start your own. I encourage everyone to identify those tasks that you are doing over and over again (be that in the shell or in the GUI) and turn them into a function that will do all of the work for you. After all everyone likes doing things the easy way, so take a little time and indulge your efficient side!

As always, if you have an idea for a script or you run into something that you think I should write about don't hesitate to post that idea here or send me an email matbyrd AT microsoft DOT com and your idea (with credit to you) could be my next scripting corner post.

The script mentioned in this blog post can be found here.

Please note - this script is not officially supported by Microsoft. Please see the script for details!

- Matthew Byrd