QuickTip: PowerShell scripting – How long did it take to run the script?

QuickTip: PowerShell scripting – How long did it take to run the script?

Have you ever wondered how long it took to run your script? Well, you dont need to wonder anymore. The following couple of lines will provide a visual output how long it take to execute your script from start to finish

$Start = [system.datetime]::Now
Script run….
$End = [system.datetime]::Now
$resulttime = $End – $Start
Write-Host: (‘Execution Time : {0}Days:{1}Hours:{2}Minutes:{3}Seconds’ -f $Resulttime.Hours, $Resulttime.Days, $Resulttime.Minutes, $Resulttime.Seconds)

Image result for meerkat simples


The Author – Blogabout.Cloud

Discovering Distribution Lists using PowerShell

Discovering Distribution Lists using PowerShell

Do you have a requirement to understand how many Distribution Lists exist within your Exchange organization or need to understand if they actually being utilized? Well, this is something I have come across recently while working for the customer. They have a mass of distribution lists across their organization which they are trying to tidy up before migrating to Office 365. The organisation I was working for had over 100,000 distributions list but the state of them was unknown so what challenges did I face?

The challenges faced

  • Unknown the number of DLs that had 0 members
  • Unknown the number of DLs that had 0 managers
  • Unknown the number of DLs that had invalid characters

The solution… PowerShell

So the following script was created to obtain the all the attributes listed before, this enable to put together a business case for which distribution lists should be deleted and which should be migrated.

  • Distribution List Name
  • SamAccountName
  • GroupType
  • DistinguishedName
  • Managedby
  • memberdepartrestriction
  • memberjoinrestriction
  • primartysmtpaddress
  • Number of Members
# Call Distribution Lists
$dist = @(Get-DistributionGroup -resultsize unlimited)
# Start Transcript
Start-Transcript -Path $env:USERPROFILE\desktop\transcript.txt
# Report on Distribution List
foreach ($dl in $dist)
$count =@(Get-DistributionGroup $dl.samaccountname).count
$report = New-Object -TypeName PSObject
$report | Add-Member -MemberType NoteProperty -Name 'Group Name' -Value $dl.Name
$report | Add-Member -MemberType NoteProperty -Name 'samAccountname' -Value $dl.samaacountname
$report | Add-Member -MemberType NoteProperty -Name 'Group Type' -Value $dl.grouptype
$report | Add-Member -MemberType NoteProperty -Name 'DN' -Value $dl.distinguishedName
$report | Add-Member -MemberType NoteProperty -Name 'Manager' -Value $dl.managedby
$report | Add-Member -MemberType NoteProperty -Name 'Member Depart Restriction' -Value $dl.memberdepartrestriction
$report | Add-Member -MemberType NoteProperty -Name 'Member Join Restriction' -Value $dl.memberjoinrestriction
$report | Add-Member -MemberType NoteProperty -Name 'PrimarySMTPAddress' -Value $dl.primartysmtpaddress
$report | Add-Member -MemberType NoteProperty -Name 'Number of Members' -Value $count
Write-Host ('INFO: {0} has {1} members' -f $dl.name, ($count))
$reportoutput += $report
# Stop Transcript
# Report
$reportoutput | Export-Csv -Path $env:USERPROFILE\desktop\DistributionListReport.csv -NoTypeInformation -Encoding UTF8

The Author – Blogabout.Cloud

Goodbye OneNote 2016 from Office Portal

Goodbye OneNote 2016 from Office Portal

Image result for the end is near

Back in September 2018, Microsoft announced it would be removing OneNote from its Office installation and OneNote for Windows 10 will be the default going forward. Microsoft has now announced (12th Feb) that OneNote 2016 will be removed from the Office Portal for installation using Semi-Annual channel.

So all installations from this post forward will not include OneNote 2016 by default when a user on the Semi-Annual channel using Office 365 on Windows 10 from the Office Portal.

So what now?

OneNote is available to download from the following url it is important to note that Microsoft are no longer developing new features for OneNote 2016. If you want to take advantage of the latest that OneNote has to offer, Microsoft state you should consider switching to OneNote for Windows 10

The Author – Blogabout.Cloud

Big News: Microsoft Teams being rolled out with Office 365 ProPlus (CDN)

Big News: Microsoft Teams being rolled out with Office 365 ProPlus (CDN)

Finally, Microsoft Teams will be introduce into Office 365 ProPlus… Microsoft Teams will be introduced into the;

  • February Monthly Channel; the
  • March Semi-Annual Channel Targeted (SAC-T); and
  • July Semi-Annual Channel (SAC)

But will automatically install Teams when Office 365 ProPlus is installed on new PCs and Macs.


Now the million dollar question, how is it being introduced?

As a Consultant that has delivered and spoke about Office ProPlus for a number of years, I do have concerns about how it’s going to be introduced and here’s why.

Office 365 uses the (CDN) Content Delivery Network for providing updates to all the Office ProPlus products, is it not the case with Microsoft Teams.

The update mechanism is completely different as the client is delivered by good old MSI so this will bring a number of questions and challenges to start;

  • What version of Office am I running?
  • What version of Teams am I running?
  • Does Teams need updating?
  • I have this weird problem but my colleague doesnt, is it version related?
  • etc.. etc…

However, if they integrate Microsoft Teams into the CDN it is definitely the way forward and also allows the customer to exclude Teams in the configuration.xml (if this is a requirement). It is very early days and I am sure more information will be released in due case but until then I am looking forward to see what the future holds as Microsoft have stated
Teams will automatically be installed for users who already have Office 365 ProPlus in the future.” So if you’re not using Microsoft Teams today Microsoft are making damn sure its available to increase adoption.

The Author – Blogabout.Cloud

MS-200: Planning and Configuring a Messaging Platform – Study Guide

MS-200: Planning and Configuring a Messaging Platform – Study Guide

Planning on taking the MS-200 Exam but don’t know where to start with your studying? Well do not fear I am in the same boat and looking for the best way to study the required elements to pass MS-200. I have started building a list of all the elements which might be covered in the exam and will continue to update this page until all the things we need know are covered.

Image result for studying stress

If you have any suggestions, please leave a comment below.

Manage Modern Messaging Infrastructure (45-50%)

Manage Mail Flow Topology (35-40%)

Manage Recipient and Devices (15-20%)


The Author – Blogabout.Cloud

Merging Excel files using PowerShell, yes it can be done.

Merging Excel files using PowerShell, yes it can be done.

Have you ever worked with Excel files where you wanted to match and compare Columns/Rows? In the past, this has been quite difficult tasks to achieve using the native commands within PowerShell.

So have you heard of the PowerShell module ImportExcel?

It’s is a PowerShell module that is available on the PowerShell Gallery and introduces a number of functions that allow you to work with Excel files using the good old blue background.

From this module we will be working with the following function;

  • Merge-Worksheet

Merge-Worksheet [-Referencefile] [-Differencefile] [[-WorksheetName] ] [-Startrow ]
-Headername [[-OutputFile] ] [[-OutputSheetName] ] [-Property ] [-ExcludeProperty ]
[-Key ] [-KeyFontColor ] [-ChangeBackgroundColor ] [-DeleteBackgroundColor ]
[-AddBackgroundColor ] [-HideEqual] [-Passthru] [-Show] [-WhatIf] [-Confirm] []

Example usage of Function

The below shows the Reference and Difference Excel files that are being used in this example. I am going to merge the two excel files based on Column A the EmployeeNumber. During my testing, I have had issues using -HeaderName parameter. In this post I will not be specifying the headings and just modify the output file.

# Variables
$ref = “$env:USERPROFILE\desktop\test\ref.xlsx”
$dif = “$env:USERPROFILE\desktop\test\dif.xlsx”
$out = “$env:USERPROFILE\desktop\test\out.xlsx”

# Script Block
Merge-Worksheet -Referencefile $ref -Differencefile $dif -OutputFile $out -WorksheetName Sheet1 -Startrow 1 -OutputSheetName Sheet1 -NoHeader

As we can see from below, the output field has organised Column A and aligned the rows

Every useful if you are working with Excel files but only annoying thing is the HeaderName parameter not working.

The Author – Blogabout.Cloud

Counting Exchange/Exchange Online Mailboxes with a specified SMTP Domain

Counting Exchange/Exchange Online Mailboxes with a specified SMTP Domain

When working with large organisations that have multiple SMTP Domains, you may run into a requirement where you need to know. How many mailboxes have blogabout.cloud as their PrimarySMTPAddress or have blogabout.cloud listed as their EmailAddress.

Using the below PowerShell snippet you can find out exactly

# Primary SMTP Address
get-mailbox -resultsize unlimited | where {$_.primarysmtpaddress -like "*@blogabout.cloud"} | Measure-Object

# Email Address
get-mailbox -resultsize unlimited | where {$_.emailaddress -like "*@blogabout.cloud"} | Measure-Object


The Author – Blogabout.Cloud

Working with Active Directory Attributes with multi-values.

Working with Active Directory Attributes with multi-values.

It is common for organisations to use or create Active Directory Attributes that may contain multiple different values and when trying to obtain the information using PowerShell you might receive


Which isn’t helpful to man or beast. However, I have been recently working with custom attributes so its time to share my experiences once again. In this post I will be working with information that is located within my personal lab, where I have customattribute10 defined with O365.

# Command
Get-ADUser -Properties * -Filter * | Select-Object samaccountname,customattribute10 | export-csv -Path $env:USERPROFILE\desktop\test1.csv

As you can see that from the above I am not receiving the desired output from Get-ADUser. So lets use a PowerShell string that obtains the required information

Let’s discuss the below string in detail to explain what each part does

@{name=” customattribute10 ”;expression={$_. customattribute10}}

The @ symbol, is the property you are retrieving is an array, which means it contains multiple values. Then you gave the property a name/label (you can name it anything you like). This will be the header of the column in the CSV file

@{name=” customattribute10 ”;

Then you provide an expression; this is the script block where you tell the PowerShell cmdlet what you are trying to fetch. For example; we want to fetch the values for the customattribute10 attribute.

expression={$_. customattribute10}}

So, now we understand the require array to pull the multi-values from lets execute the below command

# Command
Get-ADUser -Filter * -Properties proxyaddresses,customattribute10 | select samaccountname, @{L='customAttribute10'; E={$_.customAttribute10}} | Export-Csv -Path $env:USERPROFILE\desktop\test.csv

Now executing this command you will receive the correct output from the attribute which you desired.

The Author – Blogabout.Cloud

Working with Active Directory using Get-ADUsers

Working with Active Directory using Get-ADUsers

When working with Active Directory Users sometimes its a lot easier using PowerShell to obtain all the information you require from your environment. As a Consultant I have lost count how many times I’ve used PowerShell to get information out of Active Directory and its essential to your skill set.

The most simple and effective way by running the following command, as it will dump all Active Directory Users and their properties to a CSV file located on your desktop

# Command
Get-ADUser -Filter * -Properties * | Export-CSV $env:userprofile\desktop\ADExport.csv


# Command
Get-ADUser -Filter * | Export-CSV $env:userprofile\desktop\ADExport.csv

What if you only require bits of information? The command only targets the Name and SamAccountName Field. Simple right?

# Command
Get-ADUSer -Filter * -Properties Name,SamAccountName | Export-CSV $env:userprofile\desktop\ADExport.csv


# Command
Get-ADUSer -Filter * -Properties * | Select-Object -Property Name,SamAccountName | Export-CSV $env:userprofile\desktop\ADExport.csv

The possibilities are endless, you can call all everything from the below table because it exists on the AD object by default. If you have used ExtensionAttributes or CustomAttributes you can also call these as well by adding them to your filter.

AccountExpirationDateDateTimeRWaccountExpires, converted to local time
AccountLockoutTimeDateTimeRWlockoutTime, converted to local time
AccountNotDelegatedBooleanRWuserAccountControl (bit mask 1048576)
AllowReversiblePasswordEncryptionBooleanRWuserAccountControl (bit mask 128)
ChangePasswordAtLogonBooleanWIf pwdLastSet = 0
CountryStringRWc (2 character abbreviation)
DistinguishedNameString (DN)RdistinguishedName
DoesNotRequirePreAuthBooleanRWuserAccountControl (bit mask 4194304)
EnabledBooleanRWuserAccountControl (bit mask not 2)
HomedirRequiredBooleanRWuserAccountControl (bit mask 8)
LastBadPasswordAttemptDateTimeRbadPasswordTime, converted to local time
LastKnownParentString (DN)RlastKnownParent
LastLogonDateDateTimeRlastLogonTimeStamp, converted to local time
LockedOutBooleanRWmsDS-User-Account-Control-Computed (bit mask 16)
ManagerString (DN)RWmanager
MNSLogonAccountBooleanRWuserAccountControl (bit mask 131072)
NameStringRcn (Relative Distinguished Name)
ObjectClassStringRobjectClass, most specific value
ObjectGUIDGuidRobjectGUID converted to string
PasswordExpiredBooleanRWmsDS-User-Account-Control-Computed (bit mask 8388608) (see Note 1)
PasswordLastSetDateTimeRWpwdLastSet, local time
PasswordNeverExpiresBooleanRWuserAccountControl (bit mask 65536)
PasswordNotRequiredBooleanRWuserAccountControl (bit mask 32)
PrimaryGroupStringRGroup with primaryGroupToken
SIDSidRobjectSID converted to string
SmartcardLogonRequiredBooleanRWuserAccountControl (bit mask 262144)
TrustedForDelegationBooleanRWuserAccountControl (bit mask 524288)
TrustedToAuthForDelegationBooleanRWuserAccountControl (bit mask 16777216)
UseDESKeyOnlyBooleanRWuserAccountControl (bit mask 2097152)

The Author – Blogabout.Cloud

Dealing with SQL AlwaysOn in Skype for Business Server 2015/2019 Powershell Style

Dealing with SQL AlwaysOn in Skype for Business Server 2015/2019 Powershell Style

Dealing with a Skype for Business deployment with SQL AlwaysOn isn’t an easy task as there are a number of different elements involved from ensuring your databases are in the correct configuration to security permissions across the nodes.

I did originally create the following script while doing a customer deployment and have improved/modified to ensure I take out most of the headaches involved when deploying your backend databases.

The script runs through the following actions;

  • Check if SQL Instance
  • Check if Failover Clustering Role in configured on the two SQL servers
  • Ask to configure Failover Clustering Role (If required)
  • Convert and backup all Skype for Business Databases
  • Detect Skype for Business Folder on source SQL Server and copy to secondary
  • Configure SQL Server Service for AlwaysOn
    • Repeat task manually on the secondary server

Complete your AlwaysOn Configuration using the SQL Management Studio


Set-SfBSQLDatabases (546 downloads)

Change Log

Version 1.1 – Features

  • Support Skype for Business 2019
  • Support for SQL Server 2014 Enterprise, SQL Server 2016 Enterprise


Reporting Issues

If you identity any issues within running the script please email theauthor@blogabout.cloud

The Author – Blogabout.Cloud