PSI: Using $Test in ExchangeOnline PowerShell Scripts
Posted by TheBlueFireKing@reddit | sysadmin | View on Reddit | 13 comments
In the last days we suddenly had multiple scripts fail with the following Error:
Cannot convert value "System.Management.Automation.PSCustomObject" to type "System.Boolean". Boolean parameters accept only Boolean values and numbers, such as $True, $False, 1 or O. (Cannot convert value "System.Management.Automation.PSCustomObject" to type "System.Boolean". Boolean parameters accept only Boolean values and numbers, such as $True, $False, 1 or O. (Cannot convert value
"System.Management.Automation.PSCustomObject" to type "System.Boolean". Boolean parameters accept only Boolean values and numbers, such as $True, $False, 1 or O.))
There were no changes to the Script itself. We are running them over AzureAutomate on Hybrid Workers. Up to date ExchangeOnline Module running Windows Powershell.
Now we do have the following parameter on most scripts so we can run / test them without it doing modifications:
param
(
[Parameter(Mandatory = $False)]
[Bool] $Test = $False
)
Now it seems like Microsoft push some kind of change that the Get-Mailbox cmdlet now internally sets the variable $Test to something else which triggers the error. Why the f $Test would be set in a Prod environment is beyond me.
We changed all $Test to another variable name and everything is running fine again.
Just dropping this here if someone else runs into this problem ...
purplemonkeymad@reddit
Looking more it appears that it might be a debugging result that was left in. The culprit is the function PrintResultAndCheckForNextPage which has this at the top:
Looks like someone was fixing this and left in the debug info.
justaguyonthebus@reddit
They used a global variable that should have been script scoped. Shame on them.
But now I have a fresh real world example of why they are bad.
purplemonkeymad@reddit
It's not even used in the rest of the function. Literally should have been picked up by the PR reviewer.
justaguyonthebus@reddit
This is a scoping issue and exactly why global scoped variables are shunned. MS should have scoped it differently. But it's a good practice to initiate variables with initial conditions before you use them, and that's what your fix does.
Frothyleet@reddit
Couple of notes:
Powershell already has a built in for this: -whatif. That is what you should incorporate into your scripts for the exact functionality you are looking for. It's not like, an actual technical obligation, but as a good practice for portability and support you should do things "the powershell way" in a powershell script.
Setting that aside, the way you are trying to use that "$Test" parameter in your script, you can replace everything in that param() block with:
[switch]$Test
Switches are never mandatory and will default to $false, unless the parameter is called (without any arguments). Your way technically works but again you are reinventing something powershell does already.
omglazrgunpewpew@reddit
Nice catch. Exactly the kind of change that eats half a day because nothing in your script changed, yet suddenly PS is deadpan insisting PSCustomObject is a boolean now.
I’ve started avoiding names like $Test, $Mode, $Action, $Debug, etc. in automation for this reason. Too many modules, proxy functions, hidden scopes, generated commands, and mysterious Microsoft “quirks” all swirling about in the same session.
ExchangeOnline PS does sometimes feel like, “we changed something behind the curtain, enjoy your morning!”
Thanks for posting the fix. May it spare someone else from the sacred ritual of angrily adding
Write-Hosteverywhere.Secret_Account07@reddit
Be nice if they actually documented this stuff properly
NaturalIdiocy@reddit
What do you mean, one of them just slapped u/purplemonkeymad's explanation on an internal ticket and closed it. They are now one ticket closer to a pizza party and one more man page towards meeting their KPI.
Cormacolinde@reddit
Best can do is an AI-generated mess that misses half the changes and hallucinates a few that don’t exist.
omglazrgunpewpew@reddit
Right? Half the pain isn’t even the change itself, it’s the “congrats, you are now the release notes” experience.
TheBlueFireKing@reddit (OP)
I avoid reserved Variables but $Test isnt one of them. Well it is now. I did spend like an hour debugging but if I can spare one from the pain as well then thats something at least.
purplemonkeymad@reddit
Looks like it's the graph api result. Also funny to see that the exchange team must just use the beta endpoint in prod for the same reason i see other people doing it.
Also happens for other exchange commands eg Get-DistributionGroup.
ParamedicSwimming961@reddit
Underrated comment right here. API design doesn't get enough attention.