1

i want to use format-list inside a function in a powershell script to have some nice-formatted output. But when I use it, it simply doesn't print anything. In this thread the author had the same problem. He was told not to call fl inside a function, but pipe the result back to main and output there.

Piping the results back to the caller sounds like a good idea, sure.

But what if functions are nested + already have a return value?

I want to output Certificate-Information for an sslstream. To do this, I have to use a custom Callback-Function for Validation. In this Callback-Function, the Certificate-Chain is available (and should be printed to screen). The Function is required to return $true

Simplified:

function write-CertDetails([System.Security.Cryptography.X509Certificates.X509Certificate]$cert){
    #perform some conversions etc... e.g.:
    $certprops = new-object psobject
    $certprops | Add-Member -MemberType NoteProperty -Name "FriendlyName" -Value $Cert.FriendlyName
    $certprops | Add-Member -MemberType NoteProperty -Name "SubjectName" -Value $Cert.SubjectName

    $certprops | fl #this does not work!
}

[System.Net.Security.RemoteCertificateValidationCallback] $CertValCallback = {
param($sender, $certificate, $chain, $sslPolicyErrors)
    for($i = $chain.ChainElements.Count; $i-- -gt 0; ){
        write-CertDetails $currElement.Certificate
    }
    $true
}

# Create a TCP-Connection, open it in $tcpstream
Pseudo: $tcpstream = new-Object tcpConnection($host)
# now SSL/TLS-Handshake is performed. This calls the CertValCallback (which has to return true). New SslStream-Object is returned.
$sslStream = New-Object System.Net.Security.SslStream($tcpstream,$false,$CertValCallback)

I have no idea, how I should get the $certprops-Collection back to Main-Function...

Thanks for your Help

Filipp

  • Maybe you can return the $certprops object to a global variable inside write-certdetails. [object[]]$global:certs += $certprops – Mathias R. Jessen Jun 24 '15 at 23:15
0

Hm this is tricky. I agree with the assertion that you should not use Format- cmdlets in functions, and should let the caller work with the objects.

But if the information is only available as a callback, you don't have control of the caller nor the function definition nor the parameters getting passed in so you can't really workaround much of this to get a value back to your code. So I'm assuming writing to the screen really is the only option here.

The reason piping the value to fl doesn't work in the function, is that the Format- cmdlets don't actually write anything to the screen. They merely format the output. Typically in a function those format objects get returned, and returned from whatever function called that function, and so on. Eventually if you're not in a function anymore, the objects are written to the screen by the host.

To see how this differs from explicitly writing to the host, consider $v = $obj | Format-List vs $v = Write-Host $obj. The latter will write $obj to the screen and $v will be empty/null. The former will output nothing to the screen and $v will contain the format object(s).

So to answer your question, you can try this:

$certprops | Format-List | Out-Host

That should force it out to the host without returning anything, so it won't mess with the callback's return value. Write-Host in this case wouldn't work because it would just display the class name.

  • Thank you briantist! $certprops | Format-List | Out-Host does just what I want to have. I tested tons of different comandlets, pipes etc - but I never tested Out-Host (and $certprops | Format-List | write-host doesn't work, just like you described). Also thank you for your explanation regarding "Format-" cmdlets – Filipp Jun 25 '15 at 21:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.