More PowerShell 7.2 and Azure Automation troubles…

Last week I had blogged about ExchangeOnlineManagement and Az module troubles with PowerShell 7.2. This week I ran into another issue as I moved more Runbooks over to PowerShell 7.2.

Some of them started failing for no reason. It happened when I’d do a Connect-PnPOnline to connect to a SharePoint site, and the error was: Host not reachable.

Such a weird one, coz if I try and connect to the site from the Hybrid Runbook Worker this Runbook runs on, I can connect to the site. Moreover, most of my Runbooks work fine – even though they all connect to the same site and run from the same HRW – just a few failed. This stumped me for a bit.

Then I realized the ones that fail were using this throttling function I had created. It basically checks if there’s another instance of the Runbook already running, and if so quits or waits. Hmm, why was that causing things to fail?

Yes the throttling function connects to Azure and does some stuff, but I was connecting to Azure in all the other runbooks anyway (to read Key Vaults and such) and that had no issue. Digging more, I realized the issue was with the Az.Resources module. The cmdlets used by that function make use of this module, and looks like that conflicts with PnP.PowerShell. Eugh.

Looks like this is fixed in the upcoming 2.3.0 release of PnP.PowerShell (still at 2.2.0 as of writing) – that doesn’t help me currently. I can’t update my production Runbooks to using nightly versions of the module just to fix this issue. I could, of course, remove the throttling function – which is what I did in the interim – but I wasn’t happy with that. I can’t have these Runbooks running concurrently.

An update on the throttling function

Last we met my throttling function it looked like this:

Turns out this doesn’t work with PowerShell 7.2 and HRWs as the PSPrivateMetadata variable is not present in 7.2 + HRWs. (It is present in 5.x + HRWs and even 7.2 running on Azure – so it’s one of those things that will appear in the future I guess).

This means I can’t extract the JobId and use it to search other jobs. What can I do here? After some tinkering I realized I can cheat and extract the JobId from one of the trace log files. You see, every HRW Runbook writes to this path:

The highlighted bit varies per runbook.

The file there looks like this:

Neat, so line 4 has the JobId.

What can I do to find this path to this file? Turns out $PSScriptRoot has it. Split its path to get the parent, tack on "\diags\trace.log" and that’s my file. I can essentially do something like this to get the Id if it’s not found:

With this in hand my throttling function now looks like this:

Getting PnP PowerShell working with this

Ok, so what can I do to fix PnP PowerShell? Can’t I just unload the Az.Resources module after its done? Yes, I can (Remove-Module) but that doesn’t unload any of the loaded assemblies, and since those are usually the source of conflict Remove-Module can’t help us.

What can I do regarding assemblies? In my previous post I had alluded to this very informative article from Microsoft. It suggests three ways to work around this issue:

  • Start PowerShell as a sub-process – I didn’t try that, wasn’t sure if it would work
  • Use the job system – this is what I tried
  • Use PowerShell remoting – won’t work with Runbooks

With the job system you start the function as a separate job basically. And since it runs independent of the main script, the modules & assemblies it loads too are independent. When the job exits these are removed. Awesome!

Tyically the solution is simple:

In my case this is a function. How the heck do I get that in there? I could of course define the function within the Start-Job, but I don’t want that. I want to keep my code consistent across Runbooks. Thanks to a helpful StackOverflow post I learnt I can do the following:

So all I have to do is:

I need to use the curly braces because of the dash in the name, else it complains.

I didn’t know of this function name space. That’s useful.

Two issues with this.

One: my function complains that it can’t find PSScriptRoot any more. Apparently that’s how it is. So I modified the function to take this as an input parameter:

And I will pass that as an input.

The second issue was that none of the Write-Output output from the function was appearing. I got it working by changing things a bit so here’s what my Start-Job looks like now (this includes the change to pass PSScriptRoot to the function; I make use of $using for that):

For some reason having Receive-Job separately got it to show the output.

And that’s it! Now I have throttling working with PowerShell 7.2 and HRWs. I also hopefully know how to tackle any further conflicts between these various modules.

Update (22nd July 2024): Looks like I don’t need the above workaround for PowerShell 7.2. I wrote a new blog post.