-1

I'm stuck in a probably dumb problem :( Basically I have a function that write some output, and I would wait before exiting the script with a Read-Host command after the output of the function.

Here you are the code:

Function Get-FileMetaData { 

 <# modified script from:
 NAME:  Get-FileMetaData 
 AUTHOR: ed wilson, msft 
 LASTEDIT: 01/24/2014 14:08:24 
 Http://www.ScriptingGuys.com 
 Requires -Version 2.0 
 #> 

 Param($folders)
 $tagList = @()
 $tagListUnique = @()

 foreach($folder in $folders) {
    $i = 18     # attribute for Tags
    $objShell = New-Object -ComObject Shell.Application 
    $objFolder = $objShell.namespace($folder.FullName) 

    foreach ($file in $objFolder.items()) {
        if($objFolder.getDetailsOf($File, $i)) {
            $objEntry = New-Object System.Object
            $objEntry | Add-Member -type NoteProperty -name File -value $file.Path
            $objEntry | Add-Member -type NoteProperty -name Tags -value $objFolder.getDetailsOf($File, $i)
            $tagList += $objEntry
            $tagListUnique += ($objFolder.getDetailsOf($File, $i) -split ";").trim()
        }
    }
 }
 Write-Output $tagList
 Write-Output ""
 Write-Output "unique tags"
 Write-Output "-----------"
 $tagListUnique | Sort-Object -unique

 Read-Host "Press ENTER to exit"
}

$baseFolder = "C:\MyPictures"
Write-Host ""
Write-Host "Base folder: " $baseFolder
Get-FileMetaData -folder (Get-ChildItem $baseFolder -Recurse -Directory)

Basically it prints out the final statement "Press ENTER to exit" before the $tagList array.

I would like exactly the opposite, as in the order written in the code. With my limited ps skills, I understood there is something related in the different management of output "stream" and the input, but I cannot figure out how to "flush" all the output before it writes in the host.

Thanks in advance

doraz
  • 1
  • 1
  • 3
  • If you're trying to simply 'view' the result.. force it by using Write-Host, instead of Write-Output. The Output is returned as part of the Get-FileMetaData, not to the Host itself. You'll also want to do: Write-Host ($tagList | Out-String) – Marc Kellerman Feb 22 '16 at 22:26
  • If you are using PowerShell v5, then it is possible duplicate to [this question](http://stackoverflow.com/q/34835327). – user4003407 Feb 23 '16 at 03:20
  • @MarcKellerman thanks for your advice, actually with Write-Host everything is smooth, I had already tried that. But, as you mentioned, I cannot redirect output – doraz Feb 25 '16 at 23:30
  • @PetSerAl do you work at MS Powershell team?! :) Yes, I'm using Win10 w/ PS v5... your explanation in the mentioned post worked like a charm, thank you! – doraz Feb 25 '16 at 23:37
  • Or you can take the Read-Host out of your function, and place it at the end of your script (after the execution of Get-FileMetaData) – Marc Kellerman Feb 26 '16 at 00:06
  • @MarcKellerman, of course I can, but when I will "print" out the result of the function, I will be in the same situation, with Write-Host that is executed before Write-Output finishes (already tried with any possible combination outside / inside the function :) – doraz Feb 27 '16 at 14:57
  • @doraz No, I do not work at Microsoft. – user4003407 Feb 28 '16 at 04:21

2 Answers2

1

Not sure what the technical difference is between Write-Host and Out-Host, but I got around it by piping the customobject ($oOptions) to Out-Host. For example:

Write-Output "Set subscription:"
$oSubscriptions = Get-AzureRmSubscription
If($Subscriptions.count -gt 1)
{
    Write-Verbose "Multiple subscriptions found. "
    $i=1
    $oOptions = @()
    $oSubscriptions | ForEach-Object{
        $oOptions += [pscustomobject]@{
            Item = $i
            SubscriptionName = $_.SubscriptionName
        }
        $i++
    }
    $oOptions | Out-Host
    $selection = Read-Host -Prompt "Please make a selection"
    $Selected = $oOptions | Where-Object{$_.Item -eq $selection}
    $ActiveSubscription = Select-AzureRmSubscription -SubscriptionName $Selected.SubscriptionName
    $ActiveSubscription
    Write-Output "Subscription '$($ActiveSubscription.Subscription.SubscriptionName)' active."
}
else
{
    $Subscriptions | Select-AzureRmSubscription | Out-Null
}

Hope that helps.

woter324
  • 2,608
  • 5
  • 27
  • 47
0

Try this:

Function Get-FileMetaData {

    Write-Output ([PSCustomObject]@{Value="this function is executed"}) | Out-String

}

Write-Output "Before function execution"
Get-FileMetaData
Read-Host "Press ENTER to continue"

Putting the Read-Host AFTER the execution of your function, will make it output everything to the console, THEN wait for the Read-Host to be done.

Result:

enter image description here

I've updated the code above to include the [PSCustomObject] to the Write-Output, and by adding a Out-String at the end, everything works fine for me. Please let me know if this works!

Marc Kellerman
  • 466
  • 3
  • 10
  • Try to change `Get-FileMetaData` to `Write-Output ([PSCustomObject]@{Value="this function is executed"})` and see what happens. – user4003407 Feb 28 '16 at 03:58
  • Now try: Write-Output ([PSCustomObject]@{Value="this function is executed"}) | Out-String – Marc Kellerman Feb 28 '16 at 04:08
  • You answer is: *Putting the Read-Host AFTER the execution of your function*. But does it work if you not convert objects to string before output? Does it necessary to put `Read-Host` after function, if you convert objects to string? Does placement of `Read-Host` (after or at the end of function) change something? – user4003407 Feb 28 '16 at 04:18