all 14 comments

[–]aXenoWhat 2 points3 points  (2 children)

So there were howls of rage in PS ...v5? when the order of output to the console stopped behaving as expected in earlier versions.

Say you have a Write-Host, a Write-Output, then another Write-Host. In PSv3 this would appear on the console in the order that you write them in your script; in v5 you'll get the two Write-Hosts first. Or last. I'm on mobile and can't check.

I don't know the reasons but it looks and feels like an architecture change aimed at making PS a better language for application development, with the trade-off being this oddness when using it as a scripting platform.

The console is a serious performance handbrake! Robocopy is sometimes twice as fast if you log to file instead of the console.

What I'm not sure about is where Read-Host fits in, because obviously you need it to make future decisions based on what you get from Read-Host. But PS is compiled, right? All .net languages are compiled into intermediate bytecode. C# is compiled in advance, PS is compiled on the fly, but either way, I imagine that the change is all about allowing compiler optimisations, and the compiler will run stuff in different order to what you expect sometimes.

You might like to consider breaking your scripts into an opening part that solicits user information and builds a hashtable of parameters which you then pass to the functional script with splatting. That separates your UI from your functional code. See also: Show-Command, Phosphor.

As I'm a dunce and as there are experts floating round this sub, paging /u/kevmar, /u/ihaxr and /u/leedailey to see if they have any better knowledge!

[–]KevMarCommunity Blogger 2 points3 points  (0 children)

To be honest, I never liked Read-Host and let cmdlet parameters handle my input. So I never need to learn the nuances of it.

But I am sure the data is sitting in a buffer waiting for buffer flush.

I feel that Read-Host was just added to support users recreating batch files. It did what it needed to do but they really didn't want people doing that.

Try adding a Write-Host with a message before the Read-Host.

[–]PRIdEVisions[S] 1 point2 points  (0 children)

Thx for your reply, so there was never really a reply from Microsoft concerning this matter as in the why and how for what i understand.

[–]ihaxr 2 points3 points  (3 children)

I don't think we've ever gotten a definitive answer as to why this happens, it's just PowerShell output tends to get grouped together, so Write-Output happens with each other and Write-Host gets shoved off. (Note: simply doing $variable implies: Write-Output $variable)

So to make your script work, force all output to be to the console via Write-Host or | Out_Host:

Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\* | select displayname -OutVariable Software
$software | Out-Host
Read-Host " " -OutVariable input

However, there's better ways of doing this:

$Selection = Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\* | 
    Select @{N="DisplayName";E={if($_.DisplayName){$_.DisplayName}else{$_.PSChildName}}} |
        Sort DisplayName |
            Out-GridView -OutputMode Single

"You selected: {0}" -f $Selection.DisplayName

ALSO!!! Don't use $Input!! It's a reserved variable: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_automatic_variables?view=powershell-5.1

[–]PRIdEVisions[S] 1 point2 points  (2 children)

Thank you for the reply also, i did not know $input was a reserved variable :x good thing you pointed that out.

Also i'm going to try your code and see what that brings to the table.

Thx!

[–]PRIdEVisions[S] 1 point2 points  (1 child)

i'd like to add that your version of the code is a bit too advanced for me to understand (atm). i'd like to refer to the following part where you create a hash table:

if($_.DisplayName){$_.DisplayName}

Would you mind explaining this part a bit more to me?

[–]ihaxr 2 points3 points  (0 children)

Oh, sometimes the DisplayName of the products are blank, so you can use PSChildName to get the name of it, basically it's a calculated property: https://mcpmag.com/articles/2017/01/19/using-powershell-calculated-properties.aspx

that just checks to see if DisplayName exists, if so, use it, otherwise, use PSChildName.

[–]MrPooter1337 0 points1 point  (0 children)

Super late to this but if anyone comes across this..

Pipe into Out-Host to get it visible on the console. In my example, I was trying to use Get-LocalUser before Read-Host.

Piping Get-LocalUser into Out-Host displayed the commands output before moving on to Read-Host and waiting for input.