1

I am trying to write a Powershell script that will use the Write-Host commands a couple of times. when i run the script i get the output of the Write-host and then the output from the commands themselves. I've looked and Googled this issue but no joy. here is the script if any one can help?

#Use this script to find all acounts in the External Contractors OU with accounts that have expired and will expire with in the next 365 days

$cred = Get-Credential

Write-Host "Accounts due to expire in the next 365 days" -ForegroundColor red -BackgroundColor white
Search-ADAccount -Server teeis0002.europe.tel.com -Credential $cred `
    -searchbase "OU=External Contractors,OU=Users,OU=xxxxxx,DC=xxxxxx,DC=xxxxxx,DC=xxxxx" `
    -AccountExpiring -TimeSpan 365.00:00:00 -UsersOnly -ResultPageSize 2000 -resultSetSize $null | 
    Select-Object Name, UserPrincipalName, DistinguishedName, AccountExpirationDate | 
    Sort-Object -Property AccountExpirationDate

Write-Host "Currently Expired Accounts"  -ForegroundColor red -BackgroundColor white
Search-ADAccount -Server teeis0002.europe.tel.com -Credential $cred `
    -searchbase "OU=External Contractors,OU=Users,OU=xxxxxx,DC=xxxxxx,DC=xxxxxx,DC=xxxxx" `
    -AccountExpired  -UsersOnly -ResultPageSize 2000 -resultSetSize $null | 
    Select-Object Name, UserPrincipalName, DistinguishedName, AccountExpirationDate | 
    Sort-Object -Property AccountExpirationDate

I looked at using Do While and For each

JohnLBevan
  • 22,735
  • 13
  • 96
  • 178
  • 1
    What's the desired output, if `write-host` and what the cmdlets return aren't enough? [Edit] in a sample. Also fix the code formatting while you are at it. – vonPryz Jul 04 '23 at 11:12
  • 1
    How are you running your script? FYI: `Write-Host` outputs to the console, whilst other commands will output to the pipeline; and anything in the pipeline that's not picked up by something else eventually gets dropped out to the console - so my guess is your command's being wrapped in something which is causing the pipeline output to go to the caller before being passed to the console, hence the behaviour you're seeing. – JohnLBevan Jul 04 '23 at 14:13
  • Simple example of something that should work if called as expected: `write-host 'host 1';'pipeline 1';write-host 'host 2';'pipeline 2'`. Vs example of the sort of issue you're seeing: `$(write-host 'host 1';'pipeline 1';write-host 'host 2';'pipeline 2')` – JohnLBevan Jul 04 '23 at 14:16
  • The lack of synchronization between pipeline output and to-host output (`Write-Host`, as well as other output streams) is limited to PS v5+ and a very specific - albeit still common - scenario: implicitly _table_-formatted output for types that do _not_ have formatting data defined for them. The - suboptimal - workaround is to force pipeline output to print _synchronously_ to the host (display), using `Format-Table` or `Out-Host` - see the linked duplicate for more information. – mklement0 Jul 04 '23 at 22:09

2 Answers2

1

If you want to force the output from a command pipeline to be rendered on screen before anything else happens, pipe to Out-Host:

Write-Host "Message 1"
Search-ADAccount ... |Out-Host

Write-Host "Message 2"
Search-ADAccount ... |Out-Host
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
0

If I understand your question correctly, you want to suppress all the output from the commands with the exception of your Write-Host lines.

In PowerShell, you have a couple of options for that:

  1. You can save a Cmdlet result to variable. This often makes sense if you suspect that you could need that information later in your script anyway, e.g.
# outputs a System.IO.DirectoryInfo object
# which it outputs to the terminal
New-Item -ItemType Directory -Name Test

# captures the output in a variable
# hence, you will see no output in the terminal
$Folder = New-Item -ItemType Directory -Name Test
  1. You can also use [void](Verb-Noun) to keep your terminal screen clean, this casts the output to void. There's actually quite a few different ways to go about this, and while they may be technically not doing all the exact same thing, for all intents and purposes it's doing what you want it to do:
# cast to null
[void](New-Item -ItemType Directory -Name Test)

# redirect output to null
New-Item -ItemType Directory -Name Test > $null

# use a Cmdlet to pipe to null (standard output only)
New-Item -ItemType Directory -Name Test | Out-Null

But sometimes that may not be enough if you also want to suppress error messages (although you should think hard about whether that's something you really want to do but that's besides the point here).

Error messages are expected to written to the error stream. You can read more about streams here.

# just redirect the error stream to null
Verb-Noun 2>$null

# redirect success and error stream to null
Verb-Noun 2>&1>$null

# redirect every stream to null
Verb-Noun *>$null
Stefan
  • 115
  • 2
  • 7
  • Good point, I fixed that in my answer! I think the most PowerShell-ish way of doing this would actually be the `Out-Null` Cmdlet. While I can see folks with a strong Unix background lean more towards that stream redirect route; in an org it's probably something you would want to address in a style guide. – Stefan Jul 05 '23 at 07:36
  • Thanks for updating. I'd say `$null = ...` is the best overall solution, as it avoids a potential performance pitfall with `Out-Null` (though that probably often won't matter; e.g., given an array `$a = [int[]]::new(1e6)`, compare the performance of `$null = Write-Output $a` to `Write-Output $a | Out-Null`; interestingly, the performance difference is much bigger in Windows PowerShell)- see [this answer](https://stackoverflow.com/a/55665963/45375) for a discussion. – mklement0 Jul 05 '23 at 13:42
  • As for the question at hand: I think the key phrase is: "when i run the script i get the output of the Write-host and then the output from the commands themselves". That is, I think the OP is asking about the following head scratcher in terms of _output ordering_: `[pscustomobject] @{ foo = 1 }; Write-Host 'Why I do come first?'` - hence the closure as a duplicate of the linked post. – mklement0 Jul 05 '23 at 13:45