1

Doing a Start-Transcript to capture logs from a node program. After starting the transcript the following command is entered:

PS > node . 2>&1

The above program outputs everything to console. After running the program, I ended it and stopped the transcript. Now I inspect the transcript to find specific application logs; I don't find them, and instead I find the below error:

At line:1 char:1
+ node . 2>&1
+ ~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (2023-07-11T10:5...nabled":false}}:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

Am I doing something wrong?

deostroll
  • 11,661
  • 21
  • 90
  • 161
  • `node` probably uses stderr to output certain messages - PowerShell then wraps them in ErrorRecord instances (because they're coming from the error stream) and you see this annoying output – Mathias R. Jessen Jul 11 '23 at 11:29
  • Windows you command is appending the error output (2) to the standard output. In power shell there are other types of outputs beside error and standard. See : https://learn.microsoft.com/en-us/powershell/scripting/developer/cmdlet/types-of-cmdlet-output?view=powershell-7.3 – jdweng Jul 11 '23 at 12:20

1 Answers1

0

tl;dr

Call the .ToString() method on each output object to ensure string-only output (%, the built-in alias of ForEach-Object is used for brevity):

node . 2>&1 | % ToString

Caveat:

  • Capturing output from external programs or piping it to another command invariably subjects it to decoding into .NET strings, which can reveal a mismatch between the actual character encoding a given program uses and the one PowerShell uses for decoding, as reflected in [Console]::OutputEncoding, which itself defaults to the console's active code page.

    • Thus, you may have to (temporarily) set [Console]::OutputEncoding to the actual encoding to ensure correct interpretation.

    • Indeed, given that node invariably produces UTF-8-encoded output, you'll need to (temporarily) set
      [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new() if your output comprises non-ASCII characters - see this answer for details.


Background information

By using PowerShell's 2>&1 redirection, a single stream of objects containing the merged stdout and stderr lines of the external program is sent to the success output stream.

While the objects representing stdout lines are strings, those representing stderr lines are [System.Management.Automation.ErrorRecord] instances.

In Windows PowerShell, these [ErrorRecord] instances render like PowerShell errors, which is what you saw. This is unfortunate, because stderr output may or may not represent actual errors, given that stderr is more generally used for anything that isn't data, such as status information.

Fortunately, this display problem has been fixed in PowerShell (Core) 7+.[1]

As an aside: That PowerShell uses distinct data types for stdout vs. stderr lines actually offers an advantage: If you capture the resulting objects, you can determine each object's stream of origin via its data type (-is [string] vs. -is [System.Management.Automation.ErrorRecord])

See also:

  • For a comprehensive discussion of redirecting output from external programs in PowerShell, see this answer.

[1] In the context of PowerShell remoting, however, [System.Management.Automation.ErrorRecord] still render as if they were errors, though in v7+ in a much subtler form: their text prints in red as-is, without the extra information and multi-line representation seen in Windows PowerShell.

mklement0
  • 382,024
  • 64
  • 607
  • 775