Join Mike Pfeiffer for an in-depth discussion in this video Automate Tasks With The Scripting Agent, part of PowerShell 2.0 for Exchange Server.
- The Exchange Scripting Agent gives you the ability to kind of call some custom code after something else runs. So, this is really kind of a cool way that you can override some default values and do some different things. Let me show you a quick example. What I want to do first is I'm just gonna create a mailbox so I can kind of make this make a little sense. So, to create a mailbox I'm gonna first create a secure string object for my password. Then I'm gonna do new, mailbox name and we'll just go with Dave Smith.
Alias will be dsmith. User principal name will be dsmith.uss.local. Set the password to my $password object that I just created. So right now we go out to the server, we execute new mailbox that creates the mailbox connected to the new active directory user. Now when we look at dsmith, you know, we get the default properties, but if I look at something like single item recovery, that's set to false.
And that's kind of a default. Anytime you create a mailbox, whether you're doing new mailbox to create a new AD user that's mailbox enabled or you just mailbox enable an existing AD user, the single item recovery enabled property is always set to false. Now, I'm just picking this particular property as, you know, kind of a way to show you this. But this property particularly is for when you're using an exchange native data production kind of scenario where you're running without backups. You would want that to be true in that case.
But this is something you can't really override global and there's nowhere to go in the console and say, "Hey, anytime you create a mailbox "set this thing to true." So, a good use case for the Scripting Agent is to have some custom code fire. After new mailbox has run go ahead and set this to true. A cool thing is the Scripting Agent will work both for the graphical and for the command line because no matter where you're at creating mailboxes, at the end of the day we're just running PowerShell commands under the covers. Now in order to set this up, we use something called Cmdlet extension agents.
So if you do a get cmdletextensionagent and select the name and the enabled property, you'll notice that we've got the scripting agent and he's not enabled by default. And this is the piece that it actually makes all these work. You write some custom code, enable the scripting agent and he'll look at that code, and make sure a fire is based off of the criteria that you define. Now this custom code is all written in kind of an XML document.
So, let me go out to the exchange server. I'll show you what this looks like. So I'm gonna go out to exchange/c$. This will go out to the C, share and on Program Files, Microsoft Exchange Server. V14 in the Bin folder, and this Cmdlet Extension Agents Directory. You're gonna have this samplescriptingagentconfig.xml.sample. So there's actually some good examples in here but what you really need to have is you need to have a file out here called Scriptingagentconfig.xml and that needs to be on every Exchange Server in your environment because if you're running the commands against a particular server and the scripting agent is enabled, that's where we're gonna look to actually look for the code.
So what I'm gonna do is I'm gonna create a blank one of these. Just do a File, New. So we'll have a blank XML file. And if you actually go to the sample document it's got a bunch of custom code they've written to kind of show you some examples. I'm gonna show you some examples that I wrote for this. The first one's going to be something real basic. And that's to enable the scripting agent. So I'm opening this in the ISC so you can see the code a little better.
If I opened it in Notepad, all the XML would be kind of hard to read. So, here we've got XML encapsulating our custom PowerShell code. So really what we're saying is we're looking for calls to new mailbox using this OnComplete API. So really what we're saying is telling the scripting agent, "Hey, when new mailbox runs after it's finished "and when it's completed, "go ahead and check to see if that succeeded "and then let's run some code." So the code I have out here the first one it's a little hard to read or kind of understand what's happening rather, but I'm doing a $mailbox.
So I'm storing some information in a variable. This information is actually the bound parameters when the command was ran. So $provisioninghandler.userspecifiedparameters name. And really what I'm saying here is if somebody ran new mailbox, give me the name. I'm capturing this. So, the OnComplete API is hey, this command just ran. What was the value assigned here? So Dave Smith for example. So we're saving that information in this variable and we're turning around right after that and then we're gonna set mailbox against that guy, and actually enabling single item recovery.
So to make this work, I just want to copy this code into that XML file. So open this in Notepad. Just gonna paste it straight in. And then I need to enabled that scripting agent. So I need to do an enable cmdletextensionagent scripting agent. And the case doesn't matter here. That's just something that I find myself doing all the time.
So I run that. Don't get any errors back so that's good. Do a get cmdletextensionagent just to check it, select name and the enabled parameter. So that looks good. Now at this point, usually what I need to do, what I've noticed is you need to restart the tools. So if you have the console open or you got the shell open, probably need to restart this for that change to take effect. So let's restart that. What we'll do is create another mailbox and then check that property to see if the scripting agent was able to set it.
Okay, let's clean the screen up a little bit. So again, we'll do $password. And we'll create a new mailbox. This time we'll do Bob Smith. Alias bsmith, user principal name bsmith.uss.local. Password is $password.
Now we'll do get mailbox bsmith. And look at the single item recovery property. And you can see that now it is actually set to true. So the scripting agent fired, changed the property and everything's good. So what you can do here is when you're doing this is you know, you could actually specify a list of cmdlets here. So you could do new mailbox and you could also do a comma and then enable mailbox. So that would cover you for creating new users with mailboxes or just creating mailboxes for existing users.
There's also other APIs. So let me show you another example. I got another piece of code out here that I've got. So I could actually take this code and add it to my XML document as well. But this one's a little bit different. We're using a different API here. The validation API. So, in addition to kind of running things after a command completes, you could run things before something happens. And what I'm doing with this one is basically validating the name input into the console.
And I'm using a regular expression for this. So this one's kind of tricky but what I'm doing here is saying if anybody runs the new mailbox database or set mailbox database, I want them to use a database name that I've kind of predefined. And notice that I've actually passed in a custom error if they don't define that, that name that I'm looking for. So, please use a proper naming convention. In this case I'm wanting them to do basically a three-digit city code followed by a dash and DB, followed by a dash and then a two-digit numeric code.
And the way I'm doing that is with a regular expression. And if you read this it's actually ... It looks kind of crazy at first glance but it actually kind of makes sense. So the caret here is kind of the start of line anchor and basically what we're saying is we'll accept any character A through Z three times then we're looking for the -DB- then we're looking for a two-digit number. And then we have the dollar sign as the end of line anchor here. You can see that I'm using the cnotmatch comparison operator.
So we're looking for an actual case-sensitive match and you can kind of just play with these in the shell. Now regular expression are something you really need to know as an administrator but that's something the developers use. We have a saying that, developers have a saying that is, you know, you have a problem and you use regular expressions, well now you have two problems because it's so darn complicated. But let me show you this. phx-db-01 -cmatch and then my regular expression.
You can see that that's false. But if I enter it in like this, then it does match, I get back true. So really what I'm doing with this code, this custom code is ensuring that administrators are entering the database names in my predefined kind of format. So let's go ahead and take this code. Update our scripting agent XML file. I'm actually just gonna replace this.
I actually got the code for this out of this sample XML file. I modified it quite a bit but part of the problem here with figuring out how this works is the documentation. A documentation's a little light right now so I'm hoping they update that. But you can see here, you know, again we're kind of capturing the name parameter I've used to create the database. I'm kind of comparing it to this regular expression. The tricky part is acquiring this custom error. You know, you got to call new object to kind of create an instance of this provisioning validation error object, and then you're passing in a custom error.
So that's kind of tricky but that's actually in the sample file. Let me go ahead and create a database. So I'll do a new mailbox database. So we'll see db- well, city code. So like maybe Seattle-db-01. Put that on a specific server. Pick the defaults and just kind of hit all the buttons all the way through.
And notice that if I were the administrator and I had the scripting agent kind of setup for this, I would come to the wizard and hopefully, you know, they would read the error that would say, "Hey, "please use the proper naming convention for databases." And here's an example. You need to enter them like this and that needs to be in caps. So the administrator at that point could go back. Correct their mistake. This is is all very, you know, dependent on the fact that they're really gonna read the error which is a stretch but as you can see, this time I've entered it in properly and we get green ticks and life is good.
So obviously, this takes a little bit of kind of playing around with but it's actually really useful. And just remember that if you're going to use this you got to make sure that the XML file is on every server in your environment, and don't forget to enable the scripting agent.