1 Question: Is there a functional difference between -OutVariable and variable assignment?

question created at Sat, Jun 1, 2019 12:00 AM

I came across the following bizarre behavior and I was hoping someone could point me to some documentation that can explain why this behavior happens or what is causing it.

I have tried looking at the documentation for New-SelfSignedCertificate to see if there was a remark explaining this or a parameter that "forced" it to complete but didn't find anything useful. https://docs.microsoft.com/en-us/powershell/module/pkiclient/new-selfsignedcertificate?view=win10-ps

I also tried searching google for OutVariable vs assignment but didn't find anything helpful either.

Consider the following functions:

function Why-DoesThisFail {
    $cert = New-SelfSignedCertificate -Type Custom -Subject "CN=test" -KeyAlgorithm "RSA" -KeyLength 2048 `
        -CertStoreLocation "Cert:\CurrentUser\My" -NotAfter (Get-Date).AddDays(1) -KeySpec Signature `
        -KeyExportPolicy NonExportable;

    # Note that this outputs fine.
    Write-Host $cert.Thumbprint;

    # Prints nothing
    Get-ChildItem -Path "Cert:\CurrentUser\My\$cert.Thumbprint";

function Why-DoesThisPass {
    New-SelfSignedCertificate -Type Custom -Subject "CN=test" -KeyAlgorithm "RSA" -KeyLength 2048 `
        -CertStoreLocation "Cert:\CurrentUser\My" -NotAfter (Get-Date).AddDays(1) -KeySpec Signature `
        -KeyExportPolicy NonExportable -OutVariable cert;

    # Note that this outputs fine.
    Write-Host $cert.Thumbprint;

    # Prints Cert as expected
    Get-ChildItem -Path "Cert:\CurrentUser\My\$cert.Thumbprint";

Notice that the only difference between the 2 functions is one is using variable assignment and one is using the OutVariable. Is this a behavior of Powershell itself in how it is handling OutVariable vs assignment; or is this because of something that New-SelfSignedCertificate is doing behind the covers? It feels almost as if the Certificate isn't being registered on the machine until after the New-SelfSignedCertificate completes and it doesn't complete for some reason when variable assignment is used. Note that after the function completes and control is returned to Powershell, you can successfully run the last line (replacing the thumbprint with the one written from Write-Host) and retrieve the certificate from the machine.

I'm puzzled.

Thanks for any help!

1 Answers 1

Your issue, is not with any confusion or context with this?

-OutVariable and variable assignment?

It's because you are using the line in the first one wrong. Double quotes do coerce variable expansion, but in your case you need to change the string interpolation for that dotted $cert variable. So, you are having a misunderstanding about string expansion.


Get-ChildItem -Path "Cert:\CurrentUser\My\$cert.Thumbprint";

... should be done this way.

Get-ChildItem -Path "Cert:\CurrentUser\My\$($cert.Thumbprint)"

... otherwise, PowerShell does not know what it is. Also, those semi-colon(s) is never really needed in PowerShell proper. It is a special marker separating distinct code segments. If you had this all on one line, that's at thing, but not how you are using it here.

If you are doing this in the ISE or VSCode, you'll see the color coding change to reflect the which will be expanded and which will not.

See this article. Powershell String Expansion

Variable Interpolation, or Two Types of Strings Strings with single quotes (') are literal strings, meaning there are no special characters; every character in the string will output as itself. Strings with double quotes (") in powershell will expand variables and escape characters inside the string; this is referred to as interpolation.

And this one, though it talks to Here-Strings, it still covers the point I am trying to make here.

Variable expansion in strings and here-strings

Now as for your post question...

Is there a functional difference between -OutVariable and variable assignment?

... The send result of either is the same. However, this is the deal... You can store the output of a command in a variable and at the sametime have this output on the screen. This what Out-Variable also does, whereas variable assignment does no output. Yet it can, if you use variable squeezing. So, this...

Get-ChildItem -OutVariable files

... this ...

($files = Get-ChildItem)

... will do the same thing. Assign the results to the variable, and output to the screen at the same time.

See this --- 3 ways to store and display PowerShell Variable simultaneously

Using -OutVariable parameter

PowerShell Variable squeezing Using

Tee-Object Cmdlet

Lastly, avoid the use of Write-Host, unless you are doing text screen coloring. PowerShell, will output to the screen is the default, unless you tell it otherwise. So, this

Write-Host $cert.Thumbprint
Write-Host 'Hello'

... and this …


... will do the same thing.

If you must use Write-*, because of your chosen coding practice, then choose Write-Output.

Update for Andrei Odegov point / pointer

Yes, they just output hello to the screen. Try it.

Write-Host 'hello' 

# results 


# results 


As for your link ...

Is your last statement that Write-Host "Hello" and "Hello" do the same thing, correct? Look at stackoverflow.com/questions/8755497/…

... these all do the same thing. Output to the screen.

$count = 5 

write-host "count=" + $count

# results 
count= + 5

write-host "count = $count"

# results 
count = 5

"count =  $count"

# results 

count =  5

"count=" + $count

# Results


That first one is why string concatenation can be, well, has issues. I am not the only one who thinks so. See this video.

From the authors ofThe Big book of 'The PowerShell Gotcha's'

Don't Concatenate Strings



2019-06-01 07:41:29Z
  1. Is your last statement that Write-Host "Hello" and "Hello" do the same thing, correct? Look at stackoverflow.com/questions/8755497/… .
    2019-06-01 07:04:19Z
  2. Thank you @postanote . I appreciate you taking the time to answer this very thoroughly.
    2019-06-01 07:40:54Z
  3. No worries. I do what I can when I can. If it resolves your query, be sure to mark is a accepted, for the benefit of others that come across it.
    2019-06-01 07:48:19Z
source placed here