PowerShell 101 for Messaging Administrator and IT Pros (Part 1)
In this article series the author reviews the basics of PowerShell. This will help Messaging Administrators and IT Pros build scripts from scratch and learn how to automate tasks in Exchange administration. |
Introduction
I’m a big fan of discussion groups about Unified Communications, and I noticed that in most of the cases the IT Pro knows how to get stuff done, however, some have difficulties in creating scripts for large group of objects using PowerShell to facilitate the process.
So, the idea of this article series is to go over the basics of PowerShell and then see how we can create scripts to help us in our daily administration tasks on Exchange Servers while, you can use and apply the same concepts to different products that use PowerShell. As you may have noticed the list is getting bigger and bigger, from the top of my head we have Lync, DPM, System Center Virtual Machine Manager, System Center Operations Manager and bear in mind that Windows 7 and Windows Server 2008 R2 already have PowerShell built in.
One last piece of advice before starting this journey, I’m not a programmer, well I started my career programming in some old languages such as Pascal and Cobol, however, that is not my best suit and for that reason we are going over PowerShell from an IT Pro point of view. There are several ways to accomplish things so, if you find a way to do something better please, drop me a line in the MSExchange.org Blog and I will be glad to update the article or add the updates in the blog.
In this article and the next one we will be working on the requirements to build a certain level of scripts and after that we are going to explore a couple of scenarios and create some scripts from scratch. Then, we will tackle a couple of issues and use different techniques to get better results.
The basics and a little bit grammar
The first thing is how to get around and understand the commands within PowerShell even if you don’t have an Internet connection and you can do that easily using the PowerShell/Exchange Management Shell.
The first thing to understand is that all cmdlets are formed by a Verb + Noun and the most common verbs are: Get, Set, Remove, Add, Clear and so forth and the noun portion is based on the settings that we want to perform but for us exchange guys a few common nouns are: Mailbox, MailEnable, Contact DatabaseAvailabilityGroup (by the way we are going to see how to reduce this name using an alias :)).
Taking advantage of Autocomplete and help features…
One of the best features of PowerShell is the autocomplete functionality, which facilitates life for the administrator during a shell session. Basically, at any time you can hit the tab button and the text auto-completes for you. Let’s say that you just remember the option database in order to list the databases, then you can type in Get-Mailbox and start hitting the tab button, all options after Mailbox will be shown (database is the 5th or 6th option ahead) however, the tab feature does not stop there, you can also use it for parameters. Let’s say that you finally found the cmdlet that you were looking for and now you want to list the databases of a specific server but you don’t remember the full syntax, so you can type in – (dash) and start hitting the tab again and all options will be displayed. If you know that it starts with an “S” then just type S and hit the tab button and all parameters starting with “S” will be displayed. Not so bad, isn’t it?
Now that we know how to search commands we can use the built-in help of PowerShell. There are a lot of ways to do that and the first one is to use man *string* where the output will be all cmdlets with that string. In Figure 01, we are getting information about all cmdlets for our users with contact string, and we have a nice list with all cmdlets including a synopsis that gives you a good idea what to do with that cmdlet.
If you need further details about the cmdlet, then you can run man <cmdlet> -detailed which will display information including: parameters, examples, remarks, description, syntax and synopsis. If you want to cut to the chase and just see a couple of examples then run man <cmdlet> -examples, or if you are alone on a Saturday night, and you have nothing to do, then I would suggest running man <cmdlet> -full!
Cheating and finding out the cmdlets required, using Exchange Management Console
If for some reason you have no idea about the command you need to use, you can always cheat and use Exchange Management Console to find out what cmdlet you are looking for. Basically, any change that you do in the console will enable an icon on the lower left corner, and clicking it will have the cmdlet used to process the change that we have defined (Figure 02). This helps the administrator who wants to create a script but may not remember how to define a certain property or even the cmdlet. In Figure 02, we opened properties of the user and checked the Hidden From Address List on the General tab, the PowerShell button will be available and the result will be the cmdlet code to be used to perform such change when we hit either Apply or OK.
Building your first “Hello world!” script
If you have already done that, you can skip this section, but if this is your first time congratulations and I’m glad to help you on your first “Hello world!” script. It has been a while since I wrote mine but I still remember it when I was learning my first language (Pascal). I had several classes and readings to understand variables, procedures, vectors, functions, and so forth before going to the computer lab to test it (Yeap, it was a long time ago when computers were not that popular in my hometown). At that time as a learner I wanted to see some action, and the coolest moment ever was when I was able to write something and get results on the screen using some information entered by the user.
In order to define the output text of a script you can run Write-Host “String”, and if you want to show a warning message (the ones in yellow and black background) you can use Write-Warning “String”, while, you can also use Write-Error, you got the idea, right?
So, in order to build your first script open the PowerShell or Exchange Management Shell, type in notepad myfristscript.ps1 and in the first line type Write-Host “Hello World”, save it and then run .\MyFirstScript.ps1 (remember that you can also use tab to autocomplete) and here we go we have the text defined in our script, as shown in Figure 03.
Bear in mind that you may need to run Set-ExecutionPolicy Unrestricted in case you get an error about signed scripts when running your script.
So far, we know that by just saving a simple notepad with a .ps1 extension we can start building scripts. We have enough base to create a simple set of tasks in a script, we can also add some text before and after with the write-host as we have just seen and voilĂ a useful script. A good example is the report of mailbox sizes in an organization Exchange server, where we could just save that long line in a ps1 file and you don’t need to find that on the Internet every time you need it.
Before going to the script we are going to do a short detour and see a few concepts required for our future scripts, such as: Variables, Operators and If Statement.
Using Variables…
Using PowerShell we can create variables to receive content and there are several types of variables but for the purposes of this article series we can just use the syntax $VariableName = <Value> which can be a numerical, string and any other thing that you want to add there. An example of using a string and numerical value:
$vName =”Andy”
$vUsers = 10
The good thing is that we can manage these variables after definition, in the example (Figure 01) below we defined the variables, then we print and after adding more content to them, we finally print again (we added string “ Patricio” to the $vName, and added 5 to the vUsers). The result can be seen on the right side where the string was added and the numerical value was added.
Managing Operators…
PowerShell provides a universe of operators and you will get used to them as you go, but to build scripts the arithmetic operators (+-*/) and comparison operators are the most important. We saw in the previous sections an example of the arithmetic operator. Here is a list of a couple of useful operators.
- -eq : if the both values are equal
- -ne: If the both values are not equal to
- -gt: if one of the values is greater than the other value
- -lt: If one of the values is less than the other value
If Statement…
Now that we have an idea about comparison operators, we can check the If statement. Basically, the If Statement will check one expression against another expression using one comparison operator, and then we can define action if the result is true or another action if it is false. Simple as that! The following syntax shows how the If statement is organized.
If ( Variable <operator> Variable) {
[Commands]
} Else {
[Commands]
}
Note: There is also ElseIf that we can use but for the sake of simplicity we can start just with If and Else.
We are not going over examples on this section because in the following section we are going to use If statement.
Starting more complex scripts…
In some situations the script must be dynamic and the IT Pro must be able to pass information to the script to perform a task. In a more automated scenario the script can receive just a file containing several objects to perform its tasks. In this section we will check how we use parameters with a script and use switches to manage script actions.
In the first example, let’s say we want a script that is given the mailbox name, and the script returns the Display Name, Mailbox Database, and Exchange Server. We do know that Get-Mailbox retrieves all information related to a mailbox, we can run Get-Mailbox <mailbox> | FL and the output will result all attributes and its values. Let’s find what we are looking for - Name, ServerName and Database. Let’s run the cmdlet again but now selecting just the output that we need for our script and the result will be similar to the one in figure 02 below.
Now, that we have tested with a single user and we are sure that the cmdlet is working properly we can create a new file called mbxinfo.ps1, insert the first line write-host “Hello world” like we have done in the previous article, and then run .\mbxinfo.ps1. We can pass 9 parameters on a second attempt and the results are the same, as shown in figure 03.
The issue here is that we are not working with the parameters in our script and that is the reason why the information entered is not being used. Each parameter is identified by a space after the script name and they always start with 0. In the script file we can use $args[X] where X is the position of the parameter entered in the command line. Let’s change our simple script to write also the second and seventh position as shown in figure 04.
Now if we run the same script we can see that the results of write-host (Figure 05) showing the content at positions 2nd and 7th which are possible parameters for our script.
Cool, isn’t it? So, now it becomes easier to put pieces together and have the results that we expect from our script.
Let’s remove all lines from our current script and add the cmdlet that we tested before, however let’s replace administrator by $args[0], as shown in Figure 06. Also, let’s give more information to the user that is running the script by using the first line Write-Host Retrieving info of $args[0].
Now if you need a helpdesk to retrieve that information you just need to run .\mbxinfo.ps1 <mailbox-name> and the results will be similar to the one show in the Figure 07.
The Helpdesk loved your script and now they want some improvements where they require a switch to list the same information but for the entire server. So, we defined that if the user add –server <ServerName> we are going to do just that.
First of all, let’s evaluate the two possible entries that we can receive, the first one is –Server <Server-name> and for that we need to change our cmdlet to list all mailboxes of that specific server and it can be easily done using the following cmdlet. Bear in mind that we cannot use static values in the script because we want the user to enter which servers he wants to retrieve information.
Get-Mailbox –Server <ServerName> | Select Name,ServerName, Database
Now, that we have the cmdlet tested we can start updating our script and use the IF statement. Basically, we are going to use the following logic: If the user enters –Server we are going to list by server, if he doesn’t we are going to list by individual, let’s review the previous section about IF statement and build our script. The deal here is that the first parameter can be either a mailbox or a server, so our first task is to evaluate what the end-user entered and it can be easily done by checking if the –server was entered using If ( $args[0] –eq ‘-server’) and if that statement is true we know that the second parameter is going to be the server name. Also, if the user hasn’t entered the server he probably entered the mailbox (individual) and then we will use the Else portion of the script, as shown in Figure 08.
Using the script above, we can start testing. Start by using .\mbxinfo.ps1 –Server POAEX01 (where POAEX01 is my Exchange Server) and the result will be all mailboxes of that server; secondly we can use .\mbxinfo.ps1 anderson.patricio and we have the expected results on both tries (Figure 09). The beauty of PowerShell is that we are not reinventing the wheel to bring the information. Just play with some parameters from existent cmdlets and in a really easy way we are able to get the results. From there we can take some actions and add intelligence to our scripts.
We are using static positioning here, first to exercise the If Statement. In the next article we will be looking at a more dynamic way to get similar results.
PowerShell 101 for Messaging Administrator and IT Pros (Part 3)
In this third article about PowerShell 101, the author will be adding some improvements to the script of the previous article and discusses some of the challenges users will encounter when the script complexity increases.
Introduction
In the previous article we started by creating a script to our help desk team, and they really liked the stuff, and proposed new improvements such as: they want to get more details about the Exchange Server when they run –Server within the current results, they need to know the Server FQDN, Mailbox Roles, Server Edition and how they would retrieve that information. Using Get-ExchangeServer we can have all the information requested, and as soon as we identify the cmdlets and the format to display, we can move on and change the script (Figure 01). We are going to use | FL at the end of the script for a better visualization of the information. The Server Role column is too big and all information won’t be displayed if we don’t use | fl.
Since the request is when using the –Server switch only, we need to add the new cmdlet before the lines that we already have as shown in Figure 02. A new line such as Mailboxes hosted on <ServerName> was added right underneath the cmdlet to retrieve the server settings.
When the Help Desk uses the same switch they will have the information that they requested, as shown in Figure 03.
Now, the Help Desk team wants to add a switch to pass a CSV file containing users and retrieve information about them, and here we may face some challenges, such as;
- The If statement is good for two options, if you have several options than the Switch statement is a better way to go; we can write three IF statements totally independent of each other but it creates more work and increases script flow control.
- When using several options, just the $args[] may not be suitable because it controls only the position, and since the user can add –file or –server or even a user then we need better control of how the data is entered. The same issue is when you have several parameters and for this kind of situation using Param () is the best way to go.
A different approach to work with parameters passed to the script…
If you are developing a simple script where you can easily narrow down the parameters passed by the end-user then the previous section is more than enough, however as your script becomes more complex that solution won’t be doable and there is a better way to deal with parameters being passed to our scripts.
Let’s use the following script where we basically write in the output the first 4 parameters passed to the script (Figure 04).
Now, we are going to run the script twice changing the order of the parameters, but from an end-user perspective should be the same (Figure 05). Imagine if all cmdlets were created with that logic, the only way to get it right is to make sure to pass the parameters exactly as the programmer thought during development or the developer creating a lot of logic to make sure that it has all parameters in the proper order. Either way is not good from any perspective.
In order to solve the issue we can use Param () and specify the parameters that will be passed to our script, in Figure 06 we defined two fields called File and Server and these are the strings that must be used by the end-user to run the script. If they user –Servers (plural instead of singular) it’s not going to work, because the parameters specified must be File and Server.
If you run the script and change the order of the parameters we can see that the results will always be the same. This saves us a lot of work in trying to identify which parameters are being entered by the code to test all possibilities (Figure 07).
Now, let’s say that we require a specific parameter to start the script otherwise we cannot run the script. If that is the case we can define a specific parameter as mandatory using [parameter(mandatory=$True)] and the results of this change can be seen as the script is being executed (Figure 08) on the right side. The user hasn’t specified the –File parameter and the script requested the information before continuing.
Reading information from the script...
In some cases we many need to request information from the user, information that he is not expecting and he hasn’t done using parameters. A good example is a menu or a confirmation before taking action. In order to ask the information we can use Read-Host “Question string” and it is nice to use a variable to receive the content of our input otherwise we cannot use the data entered. A simple example can be seen on Figure 09. After the user types in the option, we can write it down using the write-host $vOption.
Note: We are using Write-Host alone in some lines and that creates a single line space.
Thinking about multiple If Statements? Time to meet the Switch statement...
Let’s use the previous script and say instead of 3 we have 7 options, so we can display the seven options but how are we going to take action? It’s doable but not practical with 7 If Statements checking for the seven possible options If ( $vOption –eq 1) { commands }. Well, there is is a better way to do that using the Switch Statement, as shown in the following syntax:
Switch (<Variable>) {
<value> { command-block }
<value> { command-block }
}
The use the switch statement with the previous script is shown below (Figure 10).






















No comments:
Post a Comment