Pester: Testing Your Module Manifest

I recently ran into a problem when using Pester to test the validity of my Powershell module manifests. My original idea for testing the manifest files came from Dave Wyatt’s tests for the Pester module itself. The first describe block he uses here runs several tests against the module manifest itself such as whether the manifest is versioned, has a valid GUID, and has a name.

One of the problems I sometimes run into when authoring a module is with exporting functions. Sometimes I’ll write a new function and think I’m all set to go but when I import the module the function doesn’t exist. After a few face-palms I’ll realize that I forgot to add the function to the FunctionsToExport array in the module manifest. With this in mind I wrote a test that checks if the functions that are exported from a module match the functions that are enumerated in the module folder itself:

So running these tests against my module returned all green and we were all set, except I noticed a problem – after a successful test run, if I changed the FunctionsToExport value of the manifest to what should be a failing state, such as by commenting out one of the function names, the test still returned a success status. This had me baffled! What I assumed was happening was that Pester tests had some kind of wonky scope rules that I just couldn’t reconcile against what I know about scopes in Powershell.

After much playing around with Describe, Context and It blocks in Pester, though, I came to the conclusion that the problem had nothing to do with scope at all – the problem was with the $Manifest variable I had created using Test-ModuleManifest! Testing outside of Pester I found that the Test-ModuleManifest cmdlet only really works once in a Powershell session and afterwards the output will never change, regardless of the state of the manifest file. Run it once, change a property of the manifest and run it again and you’ll get the same output. So when I commented out one of the function names in my manifest file the Test-ModuleManifest cmdlet was still including it in the list of exported functions and I would continue to get success test results.

A bug for this behavior has already been filed on Microsoft Connect. So to get around this behavior I decided to test the manifest file simply by importing it as a hash table (since that’s what a module manifest really is) and then test the values of each key of that hash table:

I still run the Test-ModuleManifest cmdlet just to get a check on the overall validity of the manifest, but I don’t base my other tests on the result of this cmdlet. Instead I use this line:

To output a hash table for testing. So how are you testing your modules with Pester? And if you aren’t using Pester, you’d better get started!

P.S. Thanks to Jakub Jares and Dave Wyatt for helping me discover the issue with Test-ModuleManifest.

Scripting Games July 2015 Puzzle

The Scripting Games are back for another year and the format has changed quite a bit. This year we’ll be treated to several monthly puzzles with solutions submitted publicly on the website. July’s puzzle can be found here:

The Challenge

The goal is to create a Powershell one-liner that is as short as possible and creates the output given in the example:


In addition the solution should use one or fewer semicolons, should not use Foreach-Object, and should be able to target multiple computers.

Getting the Right Output

Ok, so right off the bat, we can see that we need to use WMI to get our properties. WMI is realtively easy to access with Powershell using the Get-WmiObject or Get-CimInstance cmdlets. Two of the most common WMI classes you’ll see used to get computer information are Win32_ComputerSystem and Win32_OperatingSystem. Let’s try Win32_ComputerSystem first:

There’s a ton of info there for sure, and I see that it contains the PSComputerName property we’re looking for, but not much else. There are no serial number, service pack version, or OS version properties returned. So let’s try Win32_OperatingSystem:

That’s more like it! This ouput all the properties we need to get the intended final output, so next we can put together a working command that outputs just what we need to the console. We can use Select-Object to pick the properties we want out of all those returned:

The above command gets us close to the output we need, but there’s a problem. The example output wants a property called ‘BIOSSerial,’ but we’re outputting a property called ‘SerialNumber.’ Luckily, Select-Object can handle this neatly using a technique called a calculated property:

The Select-Object command above has customized our output by replacing the ‘SerialNumber’ property name with ‘BIOSSerial.’ Now we have the output we need, but the goal is to make it as short as possible. Can we make this one-liner shorter than it already is? Sure can!

Shortening the Command

We can make this one-liner shorter with a few different techniques – positional parameters, cmdlet aliases, wildcards, and removing whitespace. Positional parameters are cmdlet parameters that can be passed a value implicitly. With Get-WmiObject we can pass a value to the -ClassName parameter and omit the actual parameter name from the command. We can do the same with the -Property parameter of Select-Object’s -Property parameter:

Now we can make it even shorter by using cmdlet aliases. Get-WmiObject has the alias gwmi, and Select-Object can be shortened to just Select:

Now we can shorten the property names passed to Select-Object using wildcards. We have to consider this carefully to make sure we use the minimum number of characters that are required to ensure the property name is not ambiguous:

And then we’ll remove the whitespace from before and after the pipe character, and between the property names in the Select-Object statement:

There’s still one more little trick to save a few characters. The Win32_OperatingSystem has a cousin – CIM_OperatingSystem. We can get the same properties from this class and save two characters from our final solution:

Whew! We now have all the output that we need in a short (-ish) command. It only uses one semicolon and does not use Foreach-Object. But there’s one goal that we haven’t approached yet – the final solution should support targeting multiple computers. Hold on a second, it already supports multiple computers! The Get-WmiObject cmdlet’s -ComputerName parameter accepts multiple values:

So we can run this against multiple computers by passing them in using an array, and we can keep it short using the parameter’s alias, -cn:

But we’re not going to include the -ComputerName parameter in the final solution. The goals state that the solution should support multiple computers, but does not state that those have to be included in the end result. Nit-picky? Yes. Technically correct? Maybe.

My solution is one possible approach and I can’t guarantee that it is the best or even the shortest. There are some smart folks out there in the community who often come up with some very unique approaches to problems. The goal of this article was to detail my approach and give the reasoning behind how I arrived at an answer. Thanks for reading!

Powershell Studio 2015 Solarized Color Scheme

I’ve been playing around with a trial version of Powershell Studio 2015 an I must say it’s pretty nice! I don’t typically do GUIs with Powershell, but if I did this would be an amazing tool. Overall there are some great features that really provide some value if you need to move up to a professional editor.

I thought I’d share the color scheme I’ve been using for the script editor:


This is a port of Solarized and it looks pretty good in Powershell Studio! If you’d like to add this as a preset scheme just copy the text below and save it in your presets folder at %appdata%’SAPIEN\PowerShell Studio 2015\Editor Presets.

NOTE: I used the font Source Code Pro from Adobe in the screenshot, but since this is not a Windows included font, I used Lucida Console in the preset file. Feel free to change this as you see fit.



Managing Clutter in Exchange Online

Exchange Online Clutter

Clutter is a new productivity aid in Exchange Online that helps save you time by separating your important messages from the rest of the muck that you get on a daily basis. A description of how this feature works can be found here. Clutter is optional and can be enabled by users should they choose to use the service.

Microsoft believes in Clutter so much, however, that they have decided to make it available by default on all new Exchange Online mailboxes starting in June. If this timeline doesn’t work for your organization, or you would rather give your users the choice to turn Clutter on, there are some new Powershell cmdlets that you can leverage.

First, some prerequisites:

1. You need to have an account that has at least the Exchange Service Administrator role in Office 365 and the ability to connect to Exchange Online with Powershell. Instructions to connect can be found here. I also have a module on Github that can make working with Exchange Online and other Office 365 services a bit easier.

2. The Clutter cmdlets will only work on server version 15.1 (Build 166.22). To manage Clutter with Powershell, both the server that you connect to via Powershell and the server that the mailboxes you are managing must be updated to this version. Microsoft is working to make sure that all Exchange Online servers are updated as quickly as possible, but you may still have some mailboxes that are on a prior version. If this is the case you will get an error when targeting those mailboxes with the Clutter cmdlets:


Turning Clutter Off

There is currently no way to disable Clutter from being on by default for your entire tenant – you will have to do this for all your mailboxes now and for any new mailboxes that you don’t want to have Clutter turned on for.  You can disable Clutter manually for a mailbox by running the Set-Clutter cmdlet:

Or you can disable it for all mailboxes:

However, some of your users may have already enabled Clutter and you won’t want to disable it for them. In this case you will want to filter your mailbox results to only the mailboxes that don’t already have Clutter enabled:

You can fully automate disabling Clutter for your current mailboxes here. Make sure you unblock the script and then run:

for details on how to use the script.

Moving Forward

After you have run the above commands to disable the Clutter for the desired mailboxes, you’ll need a plan to sustain this policy for future mailboxes. If you automate mailbox creations with Powershell, then you’ll need to run Set-Clutter against each one to disable Clutter by default. At some point you may want to embrace the on by default strategy and make your users aware of the change. At that point you can just allow new mailboxes to have this enabled.

I hope this post has clarified the administrative controls for Clutter and will help your organization make it’s decision around this new feature.

The O365 Admin Powershell Module – Part 1

The O365 Admin Powershell Module – Part 1

Connecting to Office 365 Services

If you’re already responsible for managing your company’s Office 365 tenant, then you know that sometimes you need to employ Powershell to get things done. The Office 365 Admin Center is pretty capable of handling your basic admin tasks and it’s getting better all the time, but sometimes you need to do something outside of the box or manage settings in bulk. Powershell is the way to get it done.

Exchange Online has the most manageability of all the Office 365 products and since it’s built on Exchange it is fully exposed to Powershell management. The instructions for connecting to Exchange Online in Powershell can be found here. This process is similar to how Exchange would be managed in an on-premise installation. You initialize a remote session to an Exchange server, pass credentials, and then import the commands from that session into your environment.

That’s quite a bit of typing, and this stinks if you have to come in every morning and type this in. Not to mention that this only connects you to Exchange Online. If you want to manage users or licensing you’ll need to connect to Azure Active Directory, and there are more commands still if you want to connect to Skype (formerly Lync) or Sharepoint Online.

The next logical step for an admin who needs to manage Office 365 tenants regularly is to add all these commands to your Powershell profile. A powershell profile script is simply a script that is launched each time you launch Powershell. This provides a way configure your shell environment and can speed up your day-to-day tasks. But why should every admin who manages Office 365 perform the same repetitive tasks and re-create the same profile scripts that every other Office 365 admin has created?

Enter the Office 365 Admin module. With this module you can quickly and easily connect to Exchange Online and all other Office 365 services. Instead of all the commands above, you can now simply type:

You can pick and choose any of the services you would like to connect to, and the service names also support tab-completion for ease of use.