Page 1 of 2

PowerShell writing to console out of order

Posted: Fri Jan 11, 2019 1:11 pm
by 4lch4_ExtraTxt
Hey all,

I've been working on this script for work and ran into something weird. My script is available here and I've focused near the problem line.

When I run this script it will output "Returned services:", then outputs the text for the Get-Index function, and after receiving the input will output the content of $Services to the console. I need it to output the content of $Services so the user knows which service to select in Get-Index.

Any suggestions would be greatly appreciated.

Re: PowerShell writing to console out of order

Posted: Fri Jan 11, 2019 1:25 pm
by jvierra
Please attach your script to your post. The "Full Editor" has a place to attach scripts.

When using Write-Host to output lines to the console the output is independent of the pipeline and, most of the time, will come out before pipeline output. See the main PowerShell documentation for more information on output in PowerShell.

Re: PowerShell writing to console out of order

Posted: Fri Jan 11, 2019 1:42 pm
by 4lch4_ExtraTxt
I'm not sure how Write-Host relates to this problem, as I'm using Write-Output.

And instead of combing through documentation for an answer, I was hoping someone here could help.

That said, I've attached my script to this reply.

Re: PowerShell writing to console out of order

Posted: Fri Jan 11, 2019 1:48 pm
by 4lch4_ExtraTxt
I believe I get what you mean with Write-Host. If I swap out Write-Output with Write-Host, it does go to the console in the correct order.

The problem at this point is the output that Write-Host sends, isn't formatted the way Write-Output is, so I'm wondering if there's a way to get Write-Output to send this output to the console so I don't have to manually format the content.

Re: PowerShell writing to console out of order

Posted: Fri Jan 11, 2019 1:57 pm
by jvierra
Thankyou fir fixing the post.

Your code is quite odd. I recommend not using a bunch of one time functions and build this as a simple script that uses more standard coding for WMF 3 and later. This will help simplify your code. Also when trying to debug issues that you do not understand start by throwing out all code that is decoration and concentrate on the basic minimal needs of the task.

Here is an example of how to clean up the code so that it is easier to debug. Also use a PS1 file until you resolve all coding issues then move it to a module.

Code: Select all

function Restart-JBService {
    param (
        [Parameter(Mandatory = $true,Position = 0)]
        [Alias('Name', 'Service')]
        [string]$ServiceName,
        [Parameter(Position = 1,HelpMessage = 'Which computer would you like to reset the service on?')]
        [Alias('Computer', 'ServerName', 'Server')]
        [string]$ComputerName = $env:COMPUTERNAME
    )
    Process{
        [array]$services = Get-Service -Name $ServiceName -ComputerName $env:COMPUTERNAME |
        ForEach-Object{ $x = 0 } {
            $x++
            [pscustomobject]@{
                Index  = $x
                Status = $_.Status
                Name   = $_.Name
            }
        }
        if($x){
            'Returned services:'
            $Services | sort Index
            $index = Read-Host "Which service would you like to restart? (1 - $x)"
            Restart-Service $services[$index]
        } else {
            Write-Warning "No services found matching $serviceName"
        }
    }
}
Of course you need to implement some form of error control.
help about_try_catch

Re: PowerShell writing to console out of order

Posted: Fri Jan 11, 2019 2:00 pm
by 4lch4_ExtraTxt
It may seem odd, however, I find it much easier to read and document than the alternative you posted with piping.

I appreciate the help though, I'll see what I can do from here, thanks.

Re: PowerShell writing to console out of order

Posted: Fri Jan 11, 2019 2:28 pm
by jvierra
D.Leaman wrote: Fri Jan 11, 2019 2:00 pm It may seem odd, however, I find it much easier to read and document than the alternative you posted with piping.

I appreciate the help though, I'll see what I can do from here, thanks.
That is because you are using and used to old V1 methods. It is also because you are not a Net programmer and do not recognize how to best use the net objects.

Once you get more experience with PowerShell you will understand the direction I am pushing you in.

Still stripping out all unnecessary code and comments will make understanding the code you have written easier and will make debugging much easier.

As for the order of output, my code example has no issues with order.

Re: PowerShell writing to console out of order

Posted: Fri Jan 11, 2019 2:37 pm
by jvierra
One obvious mistake is the following:

[System.Management.Automation.PSObject]
$Services,[/b}
$services can be an array. If you don't declare it as an array funny things will happen.

The normal method would be:
[object[]]$services

or

[array]$services

or

[psobject[]]$services

The better design practice would put index generation and screen menu code in one place and not scattered all over. Just get all services and keep the complete object. Use the services ID to identify the service.

Re: PowerShell writing to console out of order

Posted: Fri Jan 11, 2019 2:59 pm
by jvierra
Ok - now that I have fixed PSS, there is another issue that is common with design of scripts. The use or "Read-Host" in the pipeline will also cause all output to cease until the CmdLet is answered. This is a drawback to using Read-Hot in a pipeline.

In modules and scripts files you either need to arrange to use console output to prompt or you need to not use Read-Host. This is where Write-Host gets you out of the box.

Re: PowerShell writing to console out of order

Posted: Fri Jan 11, 2019 3:04 pm
by jvierra
The following kludge will get your output correctly:

Code: Select all

function Restart-JBService {
	[CmdletBinding(PositionalBinding = $true)]
	param (
		[Parameter(Mandatory = $true,
							 Position = 0)]
		[Alias('Name', 'Service')]
		[System.String]
		$ServiceName,
		
		[Parameter(Position = 1,
							 HelpMessage = 'Which computer would you like to reset the service on?')]
		[Alias('Computer', 'ServerName', 'Server')]
		[System.String]
		$ComputerName = $env:COMPUTERNAME
	)

	$Service = Get-Service -Name $ServiceName -ComputerName $env:COMPUTERNAME
	if ($Service.Length -gt 1) {
		$Services = @()
		
		for ($x = 0; $x -lt $Service.Length; $x++) {
			[hashtable]$Data = @{}
			$Data.Add('Index', $x)
			$Data.Add('Status', $Service[$x].Status)
			$Data.Add('Name', $Service[$x].Name)
			
			$DataTable = New-Object -TypeName System.Management.Automation.PSObject -Property $Data
			$Services += $DataTable
						
		}
		
		Write-Host 'Returned services:'
		$Services | ForEach-Object{Write-Host $_.Index $_.Status $_.Name -fore green}
        	
		$Index = Get-Index $Services $x
	} else {
		$CorrS = Get-CorrectService
		
		if ($CorrS.StartsWith('y') -or ($CorrS.Length -eq 0)) {
			Stop-Service $Service
			$ContFlag = Get-ContinueFlag
			
			if ($ContFlag.StartsWith('y') -or ($ContFlag.Length -eq 0)) {
				Start-Service $Service
			}
		}
	}
}