Powershell basics

Welcome to a new series about managing Windows servers, computers, and Microsoft 365. Most of the management will be done in PowerShell and there are certain quirks to using it that should be known from the outset. We will build a simple one liner that will tell us in sentences what mailboxes on our exchange server or 365 account that are not hidden have archives.

To start we will look at “@”. @ has 3 different functions that are very similar and hard to notice the difference of sometimes. “@()” with parentheses creates an array. “@{}” with brackets creates a hash table. “[class-name]@{}” use curly brackets and a class name in regular brackets to create objects of the class specified. The class PSCustomObject can be used to create custom objects.

There are some commands that return different sorts of objects depending on if there is one result or many. An example might be:

Get-Mailbox

This command will get you the mailboxes. If you only have one you will get the object that is the mailbox. If you have a result with more than one mailbox you will get an array of objects that you will need to loop through to get at the data. The bad side of this means that sometimes code will fail when you think you will get more than one result that you try to loop through.

A common way around this oddity is to wrap the code in an array declaration. Then if one result is found, it is added to an array and your loop will run one time. If more than one result is found, the redundant array is ignored and you will loop through the result set. An example would be:

@(Get-Mailbox)

Now that we have our list of mailboxes we want to filter it to only be users with the last name of Smith. We could assign the array to a variable then loop through it or we can just pipe it into our next command. We pipe using “|” found between backspace and enter key on your keyboard.

We want to pipe it into the next command called Where-Object it is also aliased to ? meaning these 2 commands are identical:

@(Get-Mailbox) | Where-Object {$_.HiddenFromAddressListsEnabled -eq $false}
@(Get-Mailbox) | ?{$_.HiddenFromAddressListsEnabled -eq $false}

$_ is the variable PowerShell holds each object in the array as it does the loop for you to filter. We then have a dot “.” to access the object’s properties and the name of the property we want. We then use “-eq” that means equal. Comparisons in PowerShell is a bit different than other languages. You can see all of the comparators here: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comparison_operators

Next we want to loop through each result and output if they have an archive mailbox. First we will build the loop.

@(Get-Mailbox) | ?{$_.HiddenFromAddressListsEnabled -eq $false} | ForEach-Object {Write-Host $_.Name}

Now we will simplify it with the ForEach-Object alias %. We will also add in some wording around our output to make it look pretty.

@(Get-Mailbox) | ?{$_.HiddenFromAddressListsEnabled -eq $false} | %{Write-Host “The archive status of $($_.Name) is $($_.ArchiveStatus).”}

We can output variables in our statement by using double quotes. Single quotes are outputted exactly as written. For example: 

PS C:\> write-host “Our Home is $Home”
Our Home is C:\Users\Derek
PS C:\> Write-host ‘Our Home is $Home’
Our Home is $Home

Next we are using the SubExpression operator to get to the property of our object. So “$($_.Name)” allows us to access the properties while building our output.

Now when we run our contrived command we have pretty output.

PS C:\> @(Get-Mailbox) | ?{$_.HiddenFromAddressListsEnabled -eq $false} | %{Write-Host “The archive status of $($_.Name) is $($_.ArchiveStatus).”}
The archive status of bob is Active.
The archive status of cody is None.
The archive status of dave is None.
The archive status of derek is Active.