Reputation: 224079
In a PowerShell script automating some SVN tasks I have the following function:
function SvnUrlExists($url)
{
svn info $url | out-null 2>&1
return $?
}
Since this explicitly tests whether some SVN repository URL exists, I am not interested at all in any error output. However, despite everything I found about redirecting stderr
in PowerShell suggesting 2>&1
to redirect it to stdout
, this still outputs an error message:
svn: warning: W170000: URL 'blahblah' non-existent in revision 26762 svn: E200009: Could not display info for all targets because some targets don't exist
Unfortunately, this severely messes up the output of my script.
What am I doing wrong, and how should I suppress this error output?
Upvotes: 37
Views: 60238
Reputation: 1510
Important to note is that some Powershell cmdlets do not behave correctly with these methods. Such an example is Get-ADUser
which will output the error in case of failure no matter what trick you use:
PS C:\Temp\2022-09-05T08-28-46_oexvijzd.tfq> Get-ADUser -Identity "CN=administrator,DC=acme,DC=internal" 2>&1 | Out-Null
Get-ADUser : Directory object not found
At line:1 char:1
+ Get-ADUser -Identity "CN=administrator,DC=acme,DC=internal" 2>&1 | Ou ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (CN=administrator,DC=acme,DC=internal:ADUser) [Get-ADUser], ADIdentityNotFoundException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,Microsoft.ActiveDirectory.Management.Commands.GetADUser
PS C:\Temp\2022-09-05T08-28-46_oexvijzd.tfq> Get-ADUser -Identity "CN=administrator,DC=acme,DC=internal" *>$null
Get-ADUser : Directory object not found
At line:1 char:1
+ Get-ADUser -Identity "CN=administrator,DC=acme,DC=internal" *>$null
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (CN=administrator,DC=acme,DC=internal:ADUser) [Get-ADUser], ADIdentityNotFoundException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,Microsoft.ActiveDirectory.Management.Commands.GetADUser
PS C:\Temp\2022-09-05T08-28-46_oexvijzd.tfq> Get-ADUser -Identity "CN=administrator,DC=acme,DC=internal" *>$null | Out-Null *>$null
Get-ADUser : Directory object not found
At line:1 char:1
+ Get-ADUser -Identity "CN=administrator,DC=acme,DC=internal" *>$null | ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (CN=administrator,DC=acme,DC=internal:ADUser) [Get-ADUser], ADIdentityNotFoundException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,Microsoft.ActiveDirectory.Management.Commands.GetADUser
In these cases, you will have to make try
/catch
blocks, or find other alternatives (e.g. Checking for the existence of an AD object; how do I avoid an ugly error message?).
Hope this will save someone some unproductive head scratching.
Upvotes: 0
Reputation: 437823
tl;dr
function SvnUrlExists($url)
{
# Suppress all output streams (external stdout and stderr in this case)
# To suppress stderr output only, use 2>$null
svn info $url *>$null
# For predictable results with external programs,
# infer success from the *process exit code*, not from the automatic $? variable.
# See https://github.com/PowerShell/PowerShell/issues/10512
$LASTEXITCODE -eq 0
}
Your own answer effectively addresses the redirection issue.
Steven Penny's answer proposes *>$null
, i.e. suppressing all output streams as a convenient alternative - it obviates the need for Out-Null
, which I generally suggest replacing with $null = ...
- see this answer.
However, there's another problem with the code in your question:
While it may work with your particular command, $?
, unfortunately, is not a robust indicator of whether an external program succeeded or not - use $LASTEXITCODE -eq 0
instead, because - due to a bug as of PowerShell Core 7.0.0-preview.3, reported on GitHub here - $?
can end up reflecting $false
even when $LASTEXITCODE
is 0
(unequivocally signaling success).
PSNotApplyErrorActionToStderr
becomes an official feature, this problem will go away - see this answer for more information.As for what you tried in your question:
svn info $url | out-null 2>&1 # WRONG
Only success output is sent through to the pipeline (stdout output from external programs is sent to PowerShell's success output stream).
Redirections such as 2>&1
act on individual commands in a pipeline, not the pipeline as a whole.
Therefore, if svn info $url
produces stderr output, it prints straight to the host (console) - Out-Null
never sees it.
Upvotes: 5
Reputation: 224079
Just in case someone else googles for similar terms as I did:
After I have been banging my forehead against this for hours, of course I found the solution within minutes after posting the question here:
svn info $url 2>&1 | out-null
This works like a charm.
Upvotes: 36
Reputation: 3513
If you want to suppress only standard error, use:
svn info $url 2>$null
Upvotes: 49
Reputation: 311
The voted answer generates an error for me. The solution ended up being the following:
cmd /c "MyProgram MyArguments 2>&1" | Out-Null
Upvotes: 5
Reputation: 1
One can also do this:
svn info $url *> $null
See Suppress console output in PowerShell
Upvotes: 9