0

Sql output works in main as expected, but not in the DoWork function. Why?

function Main {
    $result = DoWork
    $result | Format-Table -AutoSize
}

function DoWork {
    #return results without assigning to variable
    
    $result = Invoke-Sqlcmd -Query "select top 1 * from customer" -ServerInstance "(localdb)\MSSQLLocalDB" -Database "Database1" -OutputAs DataTables
    #$result | Format-Table -AutoSize
}

Main

enter image description here

6
  • 4
    Format-Table doesn’t write to the console by itself - it just formats an object into “meta formatting” objects. You need to pipe it into out-host to render it in the console. Your DoWork is sending the formatting objects into the output pipeline from DoWork and they’re being captured into the $result variable in ```Main’`` Commented Jun 11, 2022 at 22:22
  • 4
    By contrast, the output fromMain is being returned to the top-level scope and is getting automatically sent to out-host and shown in the console. Commented Jun 11, 2022 at 22:28
  • @mclayton sounds like a proper answer ;) Commented Jun 11, 2022 at 22:35
  • 1
    @SantiagoSquarzon - I’m stuck posting from my phone and can’t test any code so didn’t want to write an answer with typos. Feel free to write one, or I’ll check back when I’m at a PC :-) Commented Jun 11, 2022 at 22:40
  • @mclayton can you make that an answer and I'll give you creds. Commented Jun 11, 2022 at 22:40

1 Answer 1

2

To expand on the comments...

Background

Format-Table and Format-List don't actually write to the console themselves - they just convert an object into "meta formatting" objects. You need to pipe these into out-host to render output to the console:

You can, in fact, also just pipe the original value to out-host as well, but you'll get the default formatting without any customisations you might want to specify in Format-Table or Format-List:

Out-Host - Notes

The cmdlets that contain the Out verb, Out-, don't format objects. They render objects and send them to the specified display destination. If you send an unformatted object to an Out- cmdlet, the cmdlet sends it to a formatting cmdlet before rendering it.

You can see this if you try the following:

PS> $x = @( "aaa", "bbb" ) | format-table

PS> $x | foreach-object { $_.GetType().FullName }
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData

PS> $x | out-host
aaa
bbb

You might also note this:

PS> $x
aaa
bbb

But that's because the top level scope (including the interactive prompt) is special - any uncaptured objects returned to the top level scope will be automatically passed to Out-Host to be formatted and displayed in the host (i.e. the console):

Out-Host - Description

Out-Host is automatically appended to every command that is executed. It passes the output of the pipeline to the host executing the command.

Answer

In your script, $result | Format-Table -AutoSize in your DoWork function is converting $result into formatting objects and sending them into the output pipeline from DoWork and they’re being captured into the $result variable in Main, never to find their way to the console.

By contrast, the output from $result | Format-Table -AutoSize in Main is being returned to the top-level scope and is getting automatically sent to out-host, and then rendered to the console.

If you want DoWork to write output to the console you can do this instead $result | Format-Table -AutoSize | Out-Host or, my personally preferred approach Write-Host ($result | Format-Table -AutoSize | Out-String) as it's easier to scan the code for Write-Host on the left of the line rather than | Out-Host on the right, but that's a stylistic choice...

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.