Finding Exchange Online cmdlets in a script

I needed to find all the Exchange Online cmdlets in a bunch of my scripts. Should be easy, right?

I could do something like this:

But that’s a bit too generic. For one it returns all cmdlets, and for another the regex pattern also pulls up text like “re-run” for instance.

I should be able to get the Exchange Online cmdlets from the module, right? Of course not, that’d be too easy! :)

Remember the module doesn’t actually have anything in it. It downloads stuff when you connect. So how can I find the cmdlets in that?

If you run with the -Verbose script you can see where it downloads the script for instance.

This can also be seen in the output of Get-Module.

So all I need to do here is run the following cmdlet:

Or even better:

Update: I changed the above to the following later.

This was because by default cmdlets like “Get-DistributionGroup” come above “Get-DistributionGroupMember” so my loop below wasn’t matching the longer cmdlet. So I decided to sort beforehand by length in descending order.

And now I can rewrite the original search query as:

Or, to find all the Exchange Online cmdlets used across all my scripts:

Nice!

So why am I doing this? Coz since last week whenever I do a Connect-ExchangeOnline using a service principal it errors. Here’s the result of this cmdlet with the -Verbose switch. The error is in red. “A task was canceled.”

I tried from different machines, networks, etc. Same results everywhere. Same results with other Service Principals too! But, if I use a user account instead it works fine.

If I run a Fiddler trace I can see it trying to download the actual module file after authentication and that just hangs.

(On that note, I hate the ExchangeOnlineManagement module! It’s one of the worst. Graph, great! PnP.PowerShell, great! But the Exchange one is so bad. Not one day goes by without my Runbooks erroring coz some cmdlet or the other randomly fails. I’d get it if it was throttling and just told me so, but no… it’s just random failures due to timeouts and all that. Raised a ticket with Microsoft and they were so useless).

Anyways, while trying to figure out what I can do here I came across this note (from):

That seems to make a difference in my limited testing with one or two cmdlets. So I want to see if I can add all the Exchange Online cmdlets I use to this parameter and see if that still works. Hence all this effort!

I modified the above like this:

This gives me all the cmdlets like this which I can easily add to the CommandName switch:

Fingers crossed that helps! Nope, it didn’t help. 🙁 Stupid module. 🤬

Updates: Other things I tried:

1. Copy pasting the folder in %LOCALAPPDATA%\Temp where the downloaded modules are stored from a machine that has the full set to one where it doesn’t. That doesn’t help, it ignores it and tries to download the modules again and fails.

2. These switches. -SkipLoadingFormatData -SkipLoadingCmdletHelp. Didn’t help.

3. The combination of -CommandName along with -SkipLoadingFormatData -SkipLoadingCmdletHelp seems to help. At least in my testing right now.