The below code is annoyingly not just returning the contents of the $t
variable, of even if the contents of $t
are instead returned like return "!! Quitting..."
:
function AddADUser
{
....
$Answer = [System.Windows.Forms.MessageBox]::Show("WARNING: The below account already exists in domain $domain. Continue to update it (yes), or quit and rerun should it be needed after investigation (no)?", "$ScriptFileName", "YesNo")
if($Answer -eq "no")
{
write-host "Before return"
$t = "!! Quitting script on user cancellation, due to not wanting to update existing user(s) data with new details provided`r`n"
write-host "$t"
return $t
}
}
Instead the console output before and after the function returns:
Before return
!! Quitting script on user cancellation, due to not wanting to update existing user(s) data with new details provided
System.Management.Automation.PSCustomObject !! Quitting script on user cancellation, due to not wanting to update existing user(s) data with new details provided
$t contains nothing prior to being assigned after the first write-host
This must be a quirk to Powershell function return, but I can't figure it out where the darned System.Management.Automation.PSCustomObject
is coming from, apart from maybe if the function returned at a later stage, it would contain an object (I have checked with a write-host
it is not proceeding to that stage though). What is going on!?
While the question doesn't contain enough information to diagnose the source of the unwanted output, let's imagine a simple scenario:
function AddUser {
param(<# ... #>)
# oops, accidentally leaking a custom object
[pscustomobject]@{ lol = 123 }
$t = 'Value we actually want'
return $t
}
It's important to understand here that PowerShell functions can emit output at any time before the function returns - in fact, any pipeline or value expression that outputs anything during invocation will have its resulting output slipstreamed back up to the caller, as suggested by the inline comment above.
What this means is that if we invoke AddUser
as-is, it'll emit the custom object first, followed by $t
, so any variable you assign the output of AddUser
from will suddenly contain an array with $t
in the last slot, rather than just the scalar value stored in $t
on its own.
Thankfully, there's a generic workaround you can use in this situation:
AddUser
with the dot-source invocation operator (.
)$t
from the wrapper$onlyT = & {
$null = . AddUser @paramArgs
return $t
}
Value of $t
is returned and assigned to $onlyT
outside the wrapper, whereas anything emitted during execution of AddUser
is suppressed with the inner assignment to $null
.
The reason this works is that .
invokes AddUser
in the calling scope, meaning local variables like $t
will linger inside the wrapper block.