How to set up your Exchange Server Scripting Environment using PowerShell
Instructor: Mike Pfeiffer, Microsoft Exchange MVP
You’re going to spend a lot of time in the Exchange Management Shell (EMS) doing things interactively. For example one‑liners maybe like get-mailbox and sending that down to Set-Mailbox, setting the -Office to Sales etc…
Obviously, this isn’t a great example of a one liner but this is probably something that you would normally do. Now when it comes to building more robust enterprise type of scripts that are running a series of commands maybe four or five different commands all in sequence. Typically people save those in a PS1 Script that can be run over-and-over again.
When it comes to developing those scripts a lot of times people use a scripting editor instead of just you know plain text editor like Notepad. So on Windows 7 you get a scripting editor called the Windows PowerShell Integrated Scripting Environment or what we normally call the ISE.
This comes installed by default. There are also some commercial editors out there as well. There are some good free ones out on the Internet.
But this one typically is easy to use. It’s installed on Windows 7. You can install it as an additional feature on 2008 R2 so it’s just easy to get to but typically what will happen is you’ll come in here post your scripts in this top pane.
Notice that you can just save the PS1 file from there. If you run any commands out of these environments you’ll actually get the output in here.
You can interactively kind of test things out. So for example I can do something like get service now where objects status running.
So this is kind of the beginning of my script. I can run that. I can get the output here in the middle. I can also come down here and do things like service bits.
Kind of check that one then I could know oh yeah the property status.
So I need to kind of do that so that’s kind of the idea. Now the thing here is that I come in here and do a get-mailbox and run it, I actually get an error and that’s because the Exchange Management Shell environment is not loaded in here by default.
Same thing goes for the “blue shell” and run get-mailbox in this environment without first kind of initializing Exchange. It has no idea that the actual tools that are installed locally.
You might not need them tools installed locally, you might want to do that on a machine that does not have them. So let’s take a look at how you would kind of approach this.
What I typically do is set up a profile. Let me show you the profiles that are installed by default or actually set up for you by default. $profile.psextended | fL
We have four specific for PowerShell.exe.
AllUsersAllHosts simply means that if I create this PS1 script here:
It’s like a log in script for PowerShell so I can put my initialization commands there. Any user that logs into the machine regardless of which host they use will get the settings in this profile.ps1 file. So I have to manually create this file in order for that to happen.
Now since I’m the only user in this machine I’m just going to do CurrentUserAllHosts.
This means that whether I run PowerShell here or in the PowerShell cmd line, or PowerShell in the ISE, all of the settings defined here are going to get loaded for me.
So that’s what I’m going to do. I’m actually going to create the CurrentUserAllHosts script. So I’m going use New-Item –ItemType file –path C:\Users\administrator\Documents\WindowsPowerShell\profile.ps1 -Force
Now I’m going to create that file and open it up in the ISE.
So in here in the profile I’ll go ahead and set up my remote Exchange connection:
$s = NewPSSession –ConfigurationName Microsoft.exchange –ConnectionUri http://exchange.uss.local/powershell
So what will happen here when I save this regardless of which instance of the PowerShellI start, I’ll actually go out of the Exchange Server, import the cmdlets and then I’ll have those commands available to me.
I’m going to restart the ISC here so we can see this in action.
Notice that when we first start this up it’s kind of hanging a little bit it’s actually running a script. So it’s actually executing my profile right now and that’s why the stop button is lit up. It’s waiting right now for that initialization to complete.
Here’s the import of my PowerShell command for Exchange.
Once it is complete I can start composing my Exchange Management Shells (EMS) scripts in here.
But just to test this out interactively I can run and get-mailbox. In the output pane you can see that I get the results there.
Up in the top, I can do get mailbox and of tab through all the different options available that help write scripts effectively.
I also get the code highlighting. I get the debugging capabilities of the ISE as well.
Now there is one drawback to using this Manual Implicit Remoting. When I manually import this command into the main scripting environment, I lose some features.
Let me show you this real quick. Let me take the Exchange Management Shell and we’ll look at the administrator mailbox, get mailbox statistics administrator.
Notice that what I get back with this cmdlet is the number of items in the mailbox. If I select total item size, how big is the mailbox type of thing.
Now if I save this in a variable like $var to make this a little easier to work with.
I can actually go as far as doing something like $var.TotalItemSize
Notice that I get back two properties. So total item size is really kind of like a rich property. It’s an object. This point we are saying we have a property that is unlimited and then the value.
But the thing I really want to outline here is if we do a .value with Get-Member. You can see that it’s got some really interesting methods.
So I might not want the byte information. I don’t want these in kilobytes maybe I want this value represented in megabytes. So I could do that. I could do value.ToMB.
In this case that’s not going to be anything because it’s only a couple hundred k. Just to give you an idea here, run ToMB(), and convert that to ToKb().
That strips out the byte information so I just get the actual kilobytes or megabytes or gigabytes or whatever.
Now let’s do this over in the “blue” shell.
PS C:\> $var = Get-MailboxStatistics administrator
PS C:\> $var.TotalItemSize
Then we’ll do:
PS C:\> $var.TotalItemSize.value.tokb()
It produces this error. So let’s double check this in the EMS.
Just to make sure that I’m not typing it wrong let’s copy that and paste it in the main screen.
Still getting an error. So here’s the thing, let’s take a look at this with get-member. If you look at this property with get member notice that in this case total item size is represented as a string.
If we do the same thing over here in this version of the shell, let me clear that. Total item size in this environment the data type is this crazy microsoft.exchange.data.unlimited and on and on.
Thing is this is the exact property we’re looking at here. The difference is that in this environment we got some additional DLLs loaded even though we are still connected remotely to this Exchange Server and running the commands remotely.
The Shell environment has loaded some data in here so we get this rich objects where we can do things like run the 2kb method or 2md method. When we’re in the “blue” script, it’s represented in string.
You will know flat string data because we might be running this on a machine that doesn’t have the tools installed. When I’m actually working in this kind of ISE environment in my profile.ps1
I really don’t want to use this because I kind of lose some of these features, some of those rich objects.
So if I go to the tools installed on my machine what I will do is I will take the actual properties of this shortcut.
And use that as my initialization command for my profile.
So I don’t need to run powershell.exe but I do want to import the PS1 script and I do want it to automatically connect to Exchange.
So in that case when I load the Exchange in my environment into my scripting editor, I’ll get all of the commands and I’ll also get those rich kind of objects that I wouldn’t normally get with that Manual Implicit Remoting.
So I’ll save this and restart the ISE. Upon restarting you can see again it’s running my PowerShell profile and importing those commands. Not a lot has changed at this point. Eventually what I’ll get is my Exchange Management Shell environment and everything will work great. I should be able to run my Exchange commands at this point.
That indeed looks like it’s actually working.
So if you don’t have the actual tools installed the other method to manually import the commands is fine but if you’re on a machine that does have the tools installed I recommend you set up your profile in this fashion. Then again take this information straight out of this Exchange Management Shell shortcut and that will just work just fine. Now the catch to this is at this point this profile is set to current user all hosts.
So if I were to run the Exchange shell at this point I would be easily trying to run these commands twice. So what I would want to do if I’m going to use this configuration is just modify my shortcut and basically tell it to not use the profile when it starts powershell.exe. I would come here and modify this and say -noprofile.
That would mean I could go ahead and start this without any errors and the Exchange Management Shell would be loaded into any PowerShell instance that I would start on this machine. So let me just make sure that this loads up OK.
So that comes out just fine. No red errors and everything looks good.
So that’s process of getting your environment set up for Scripting for Exchange. From here I can go out and compose my scripts save them off to a directory with a PS1 extension. I can execute them either interactively or automatically through some kind of scheduled task.
Using the profile and loading the cmdlets for Exchange should work regardless of whether using the ISE or some of the kind of commercial scripting editors.