Author Archives: Irwin Strachan

About Irwin Strachan

“Those that don't script are doomed to repeat their tasks” - Unknown Hi, and welcome to my blog. I've been in IT some 20 years now, give or take. My specialty (I use that term loosely) is Microsoft infrastructure. I’m passionate about Active Directory (and yes, you guessed, in the scripting thereof) and all of the components that come to play. With Windows 2012 R2, it’s all about PowerShell!!! So join me in spreading the gospel of PowerShell!!! Well, that's a little bit about me. I’ll be blogging mostly about how I used PowerShell to help me with whatever I’m working on at the moment and what I’ve found useful or recently learned about the program. This is my way of giving back to the PowerShell community. Thank you, and you're welcome :-)

YaExOs (Yet another Exchange Online script)

Sup’ PSHomies,

Exchange online… I’ll be honest… In my many years in IT, I avoided Exchange like the plague! I’ve seen many colleagues crumble under it’s weight! (Sounds more dramatic don’t you think?) But with Office 365 being all the rage now, I guess I better get with the program, so here goes…

So there was recently a bit of a commotion on twitter about sharing level 200 stuff. We all were beginners at some point, so if you already know this then I guess this blog wasn’t meant for you… 😉

So how do you go about creating a mailbox for a user in Office 365 Exchange? Using PowerShell of course… Hehe…

Ok there are modules for AzureAD and MSOnline and stuff but where are the Exchange Online cmdlets? That was my first step. Luckily I found an excellent blog on how to go about doing this. The rest after that is pretty straightforward…

Looking at the cmdlet I wanted to figure out if there were any mandatory attributes.

(get-command New-OnlineMailbox).ParameterSets.Parameters | Out-GridView


No mandatory parameter(s)… I’ll just stick with the basics on this one:

  • Alias
  • Name
  • FirstName
  • LastName
  • DisplayName

Feel free to add any other parameters you need… 😉

You’ll need Global Admin credentials to create your Mailbox Online so have that at hand…

Once the Mailbox is created you’ll need to assign a license to the user. I’m using the MSOL cmdlet for this just because it’s still around (and way easier to implement). Having said that here’s a link to how it’s done using AzureAD cmdlets. That practical365 site is definitely a good source for anything Office365 related! 😉 Oh and the book is definitely worth having as a reference too!

Ok here’s the script:

So that’s how to get started with Exchange Online.

I’ll leave you with a lil’ thought from the Austrian Oak himself…


Hope it’s worth something to you,






Reverse engineering email address from OneDrive personal site Url

Sup’ PSHomies,

Migrations… Gotta love ’em!!!

I’m doing a OneDrive for Business tenant to tenant migration using Sharegate. If you ever decide to do any sort of SharePoint affiliated migration, best to use Sharegate! Their support is top notch! Shout out to Jimmy De Santis!

Sharegate has a cmdlet Get-OneDriveUrl that will retrieve or provision you ODFB URL (OneDrive For Business). Depending on a user’s Primary SMTP Address the URL format may not be what you expected.

Here’s a link to the script to get your ODFB information of your organization.  Be sure to follow the setup instructions.

This will generate a simple text file (I used it as-is, a rare occasion, I know… Don’t judge me…). To generate the URL, you need to swap any ‘.’ and ‘@’ for ‘_’.  I’m looking to reverse this process. Why? Well because I hate manual work. I’m almost certain I have to do this again sometime in the near future…

Those who forget to automate are doomed to repeat their work…

Words to live by…

My hunch paid off! By reverse engineering the email address from the ODFB URL, I could use that email address to retrieve the ODFB URL using Get-OneDriveUrl. I needed to provision the URLs in the target domain, fortunately the email addresses in the Target tenant are uniform.

Ok here’s the code:

Having the email address I can generate the source URL and verify if it is what I expected it to be. The samaccountname remained the same, so it was easy enough to generate the new email address and the expected target URL which once I provision, can also be verified that it is what I expected it to be. Still with me? Just have a look at the image… 😉

Generated ODFB Urls

You can generate quite the information by just have a personal ODFB Url!

Not being content with just the generated information, I did one last check using Sharegate’s Get-OneDriveUrl:

This aligns the source and target URLs nicely! Now I can migrate from tenant to tenant without to much hassle… Well at least that’s the plan… 😉

Hope it’s worth something to you,



Taking ADUser validation a step further…

‘Sup PSHomies,

This is me every single time I sit down to use Pester…



While I do enjoy using Pester for operational validation, what do you do with the ones that fail? Most of the time you’re the one doing the validation in the chain of process and everything goes right! Because you’re that good… 😉 Hehe…  I’ve been recently asked to update some users where some attributes didn’t get populated during a migration… Are you thinking what I’m thinking? 😉

The first thing I did was export the attributes they needed, easy enough. Next was to change the necessary attributes to the correct value. The ones that differ will fail (Of course they will Urv, not a total retard here… get on with it… )

Here’s where having proper descriptions can go a long way.


This is what a Test ErrorRecord looks like when you capture the results:PesterError

At first I thought of using regex on the ErrorRecord. Some of the  attributes aren’t set which gave me some issues, so I decided to breadcrumb the name. First do a split on the colon ‘:’ grab the last part and do a split again using ‘/’ to get the attribute name and value. Don’t forget to trim() 🙂

There were some other Attributes that weren’t part of the default parameter set of the Set-ADUser cmdlet. To change those attributes you need to use the DisplayName and the Replace Operator. For the attributes “not set” that need to be cleared, use the Clear operator. Just don’t use both the parameter and the DisplayName! I had EmailAddress and mail in the CSV file, one passed and the other failed… I got rid of mail…

Ok here’s the code to get things done:

First get failed Pester tests.

This will give me a csv file with the following Columns, SamAccountName, Property & Expected (Value).

The set failed Pester tests will either set or clear the attribute depending on it’s value. If it’s $null it will be cleared.

Here are some screenshots to give you an idea what to expect.

Ideally you’d only have a few failed tests. I wouldn’t use this to reset entire User attributes. Moving and/or renaming an object isn’t supported… yet! 😉

So there you have it, taking failed Pester tests values and setting them accordingly!

Hope it’s worth something to you,





Microsoft Teams MessageCards

‘Sup PSHomies,

I was excited to give the MS Teams module a go! I was secretly hoping for a cmdlet to send messages to channels. Unfortunately no such luck… yet! If push comes to shove you can always take the Graph route! 😉

I posted the blog on social media and that generated some interesting ideas. Emotions and opinions varied quite a bit. Prateek raised an interesting question on whether slack would become obsolete in the near future. MS Teams is gaining momentum and it integrates nicely in Microsoft’s eco system, so why wouldn’t you use it? It doesn’t have to be black or white, use whatever adds value to your business I’d say!

This is where social media can be a treasure trove at times, got an interesting tip from Brett Miller on posting messages to channels using webhooks! Ah! the missing cmdlet I was hoping for! “So basically it’s just an Invoke-RestMethod?” Cool! I gave it a spin:


Nice! Hmmm… Webhooks eh? Sounds familiar… Where did I read about that? Ah yes! Stefan Stranger did a blog about that. To be honest, I did read his blog, but at that time I didn’t have access to Teams… 😉 Just follow his instructions and you’re golden!

Here’s when the fun really started! Come to find out that there’s a lot more you can post using the message card reference! There’s even a card playground where you can try out your message cards. It’s all JSON, no problem, we’ve got cmdlets for that.

There’s a whole design guide on Messagecards. Best of all it supports MarkDown format! I tried a sending a table but that didn’t work as planned.

Just imagine the automation possibilities here… I understand now why ChatOps is really taking off…

My first attempt at DSL

Looking at the MessageCard format I thought: “This would be interesting as a DSL (Domain Specific Language) implementation… Hmmm…” I’ve been meaning to look into DSL after reading Kevin Marquette’s blog series on the subject. Seems now is a good time as any to start! This is what I came up with so far… It’s a work in progress ( sharing is caring) , but it works!

And here’s the result:


I used the full card format as reference.  I realize that others in the community could easily knock this out the park. Maybe we can make this a community project? I would love to see what the possibilities are here…

Turns out not having a Send-TeamMessage wasn’t as painful as I thought it would be. Many ways to Rome…

Shout out to Brett & Stefan! Gotta love the PowerShell community!!!

Hope it’s worth something to you,



PSConfAsia 2017

I recently had the pleasure of presenting at in Singapore. This was my very first conference as a speaker! As a first time speaker a great way to get started.

Jaap Brasser approached me at PSConf.Eu about doing a session (or two) at At first I was hesitant…  me, a speaker… Hmmm… I need to think about… Let me get back to you on that… Jaap was clever enough to appease my ego, now how could I say no?

I decided to get out of my comfort zone and said yes, much to Jaap’s delight! Alright! Another PSConf, this time in Singapore, how cool is that!

So after I said yes I did some googling… Let’s see Singapore… Wait what? 12 Hours??? Oh boy… Flying isn’t really my favorite passtime…

ba plane

Hehe… Fortunately I had night flights so…

Singapore has my kinda weather, tropical! I came well prepared. Poor Rob Sewell was melting in Singapore. Transportation is awesome in Singapore. From and to the conference was about 1 SGD.

The organizers did an awesome job! Great location! I met up with old acquaintances and made some new ones!

Finally got to interact with David das Neves. I wanted to attend his session but I opted for Steve Hosking session on Graph. In case you missed it Graph is going to interconnect everything. Definitely have a look at it. I liked David’s approach on having a Class for different types of log format. So I asked him “Hey no  love for Robocopy?” Next thing I knew it was in it! You can read all about hereRaimund Andrée was also there. I told him how NTFSSecurity module saved me on quite a few occasions. He has some serious plans for the module on PowerShell core, so stay tuned!

Rick Taylor won a book on Windows PowerShell for Developers by Doug Finke! Rick was like: “Wait I know this guy!” So I said we need to take a pic featuring Doug’s book! :-). Max Trinidad is a great guy! Been in IT for some time and has loads and loads of skills and it definitely shows!

The keynote is always the highlight of the Conference. Angel Calvo delivered the keynote like a boss! How can I do the key note justice? It’s all about Digital Transformation.

Digital Transformation

Digital tranformation

This is something we all need to consider. It’s not a question of if but when and how. If you’re content with where you’re at right now then you will be obsolete in the near future. What I really appreciated, was the fact that Angel acknowledged that this change can be overwhelming, but it isn’t an all-or-nothing situation. Start where you can, with what you can and take it from there. This digital transformation may take you places you never thought possible. I spoke to Amanda Debler , her transformation has her working more with kurbernetes, how cool is that?

Azure is about adding value to your business

If you’re still under the impression that Azure is just for offloading servers to the cloud, you’re sorely mistaken. We got some excellent demos by Micheal Greene and Ravi Kiran Chintalapudi on Azure Management Services. Azure is about delivering value to your business. And what has value? Data! Lots and lots of it! Having your servers, application, services just to name a few in Azure, will give you the chance to transform metric and monitoring data into added value for your business. As an OPS guy I always thought of monitoring as a necessary evil. Ravi showed us how to manipulate Azure data that is at your deposition and make it valuable! That one server that isn’t patched adequately or that server that’s missing a configuration, the data is there, it’s up to you to turn that into valuable information.


Michael Greene’s demo on ChatOps blew my mind!


I’ve seen chatbots in action but this will take things to the next level! Here are a few links Michael shared to give you an idea where they’re heading:

PowerShell and the future

When Jeffrey Snover said that PowerShell is finished, I died a little inside. Fortunately I was better prepared this time around when Angel said the same 🙂 . PowerShell has gained critical mass. Moving forward, PowerShell Core is where all attention will be placed. Steve Lee had some interesting charts and number he pulled from GitHub (It’s all about data). Mark Kraus is the nr 1 contributor on GitHub! Michael Greene’s go-to PowerShell version is Core! Joey even had a demo on cross-platform administration starting a session on a Windows and Linux. Unfortunately Joey forget about the Timezone difference, so his servers were down.

Keynote conclusion


Pretty much sums it up, no need to reiterate… 🙂

Networking event

Conferences are a great way  to interact with the Microsoft Team and delegates. It was awesome meeting Michael Greene and Steve lee in the flesh! I decided on a different approach when it came to mingling. I wanted to connect on a personal level. I can always reach out when I’m working on something. So here I am sitting in an Irish pub in Singapore knocking over a few with Michael, Amanda, Jason and Max! I asked Michael  what his thoughts were on running Windows for Workgroup 3.11 in Azure… Hypothetically that is :-P. What followed was a lively discussion! Jason had some real great stories to tell! Max told us about his first job in IT back in ’78 when debugging was literally ‘debugging’. Amanda was like: “I wasn’t even born yet…”

Benjamin had Joey finish his demo in the pub. Joey’s demo didn’t go through because of timezone difference (His Azure Servers shutdown automatically after-hours), but Benjamin wasn’t haven’t that. Joey complied and did the demo in the pub, with all attending cheering him on like proper hooligans! For outsiders we may as well have been watching a football game.

I even have my own fan club!


Suresh follows my blog and was pretty excited to meet me! Lil’ ol’ me! Suresh made the 12 hour flight worth it! I enjoy meeting my PowerShell heroes in the flesh, I just never considered myself special… Thanks for the support!!! Appreciate it!

Slides & Code

Before I forget here’s the GitHub link to all my presentation slides and code. So Fabian Dibot was at my Infrastructure session and I almost didn’t recognize him! Both him and Mathias Jessen had fun sending twitter messages during my session 😛 . Tip: make sure you disable browser notification before starting you presentation… I know, a rookie mistake, you caught me guys… 😛

Bartek Bielawski was at my Dependencies session! That was a big honor for me! Bartek is the guy you go to when you’re really stuck! While doing my session I was trying to get a read on Bartek’s facial expression. At some point I could see him scanning the code… was that a smile? Ah! no comment whew! I couldn’t wait to ask him for feedback. Getting a compliment from Bartek on presentation preparation  & code definitely gave me a confidence boost! IMHO I enjoyed presenting this session the most. I did this as a flash session at one of our DuPSUG gatherings. I took a different route using AzureAD instead of plain ol’ AD and came across some fun stuff. AD and AzureAD have different parametersets 😉

I’m really glad I did the sessions. Milton Goh was hinting on a surprise next year? 🙂 If I’m fortunate to be asked next year, I won’t hesitate!

Thanks for a wonderful experience! I can’t wait to see where your Digital Transformation takes you!






Microsoft Teams cmdlets are here!

‘Sup PSHomies,

Microsoft Teams has released the long anticipated Teams module! And with that a great blog to get you started.

Microsoft Teams is Microsoft’s version of Slack (Ok, I oversimplified that… I know). I’ve been following MSTeams development with Graph Explorer for some time now (Something you should definitely look into).

So I followed the blog’s instructions and everything works as expected!

The cmdlets support the pipeline.  (Get-Command -Name <cmdlet>).Parameterset will get you an overview of what’s supported and/or mandatory. Generallyspeaking, GroupId is mandatory and accepted from the pipeline.

TeamChannel supports value from pipeline

Here’s some code to help test drive the cmdlets.

So one thing I was hoping for, was to have a cmdlet to post to TeamChannels. For now posting can be done using Graph beta support for teams. Looking forward to having cmdlets for posting as well (fingers crossed!). Before the cmdlets you needed to do some pre-configuration in order to post using Graph, so the cmdlets definitely makes that step easier!

Well that’s it in a nutshell, happy Testing

Hope it’s worth something to you,




Graph, the endpoint to end all endpoints

‘Sup PSHomies,

My first introduction to Graph was at the Microsoft Technical Summit here in the Netherlands at the RAI march 23,24 this year. It was actually the last session of the day. The intended audience was for developers… I thought to myself, why not? I might pick up a thing or two… It blew my mind!

Then at the PSConfEU at Hannover, Jeffrey Snover’s Keynote ‘State of Union’ really made me reassess my career, so much so that I left my previous employment of 23 years for a much smaller company, Methos! Methos is owned by Jeff Wouters aka “The scripting dutchman”. It’s like Jeffrey Snover said in his keynote: “With transformative change, you need to change the way you think about things.” Graph is one of those transformative thing… Here’s how I got started.

So Jeff came up with an idea:

Jeff : Say Urv, I got something I’d like you to look into…

Me: Sure, what’s up?

Jeff: Would it be possible to get a hierarchy of the entire company from Azure Active Directory?

Me: I don’t see why not?

Jeff: Once you have the data the next step is to visualize it!

Me: Like an organizational chart?

Jeff: Uhuh! (Grinning) Here’s a tip, look into Graph…

I should have known… 🙂 Now at Methos we don’t have an on-premise Active Directory so Azure AD it is. Now as part of my “transformative change” I asked for a Macbook pro. I thought: “Hey if you’re gonna go through the change (wait that doesn’t sound right, you know what I mean) might as well go big or go home! Jeff didn’t disagree, he only grinned and let out a subtle evil laugh… I got a sneaky suspicion that I’m in for a surprise… My other Transformative change: PowerShell Core!

I installed Azure CLI 2.0 as a first attempt. To get Azure AD users:

az ad user list

This gave me a JSON list with few attributes. Maybe I need to add a property list or something. Let do a quick help, Hmmm… Ok… Next approach.

Let’s install AADPreview Core. Say, Get-AzureADUser doesn’t have a -Properties attribute… Huh? So that’s why Jeff was grinning about… Well played Jeff…

So here’s the deal, I’m using PowerShell core, not all modules are applicable. The good thing is that I could login to Graph Explorer.  Graph explorer gives you the opportunity to explore the endpoint and browse around.

“Hey look at that, there’s a get manager query! Maybe there’s a way to get all the data and filter out what I need (Like I always do with PSCustomObject)”

I saw one of the examples use a $select option so I decided to give it a try.

$select=displayName, GivenName, surName, department, officeLocation, jobTitle, userPrincipalName, id, manager

I decided to give it a try. Ok that narrowed things down a bit still no manager in sight! Turns out manager is a special kind of property, a Navigation Property. You can extract it from the MetaData

$graphMetadata = [XML](Invoke-WebRequest -Uri '$metadata').Content
$userMetaData = $graphMetadata.Edmx.DataServices.Schema.EntityType.Where{ $_.Name -eq 'User' }


Ah, that’s why manager is omitted, it isn’t part of the collection! My next challenge was to retrieve the JSON payload. That’s where I ran into the accessToken dilemma.



From the online resources I inspected, authentication is the key to access (see what I did there?). I found Mark Kraus’s module PSMSGraph quite useful to follow his trail of thoughts. It didn’t work for me because I’m using PowerShell core. Now it’s time to read the document! When all else fails RTFM!

I ran into some snags with my application registration, so my next step was to reach out to the Graph team! They are on twitter just no tweets… yet! That got me in contact with Dmitry Pimenov, the PM of Microsoft Graph! I explained him my dilemma and he showed me an easy way to get the accesstoken for proto-type purposes. Finally! I can get some data to play with!

My first attempt was straight forward: get the user, get the manger for each user and then create a PSCustomObject. This isn’t optimal ofcourse. So I sent Dmitry a DM asking what is the optimal way of retrieving manager in an ODATA query. That’s when he explained that the Beta version supports the $expand option in the ODATA query.

Quick side step: Microsoft Graph supports ODATA queries, not all queries are supported yet, it’s a work in progress. ODATA is definitely something to look into… Here’s a link to get you started… Transformative change… 😉

Alright, so the /Beta returned  quite a bit more than I bargained for, but at least I didn’t have to do multiple queries. That’s when I decided to trying something new… JMESPath Query!


While using az I noticed a link to JMESpath query, what’s that?  JMESPath is a query language for JSON. With it, you can extract and transform elements from a JSON document… Sweet! Kinda like what we do with PSCustomObject, just on JSON. Here’s where having a Mac wasn’t a liability after all… I even found a vscode extension for jmespath queries! Many ways to Rome… Transformative change… (Jeffrey Snover was right, you need to rethink the way you think about things)

Using this query on the JSON document gave me the following results:

value[].{DisplayName: displayName, GivenName: givenName, SurName: surname, Department: department, JobTitle: jobTitle, Manager:manager.displayName, Location:officeLocation}


Alright! Prototyping mission accomplished! What I thought was straight forward had quite a few curves, but I wouldn’t have it any other way!

Take away:

Learn to love Graph! Be open to learning new and interesting way to accomplish tasks in a new way. Transformative change  won’t be easy, but it’ll be worth it!!!

Hope it’s worth something to you…