powershellconsoleps1

Suppress messages in console from apps launched by PowerShell script


I have a ps1 script which runs some set of apps. All are run with the commands like:

$this.apps.Add($(Start-Process "$($global:openTrackDir)\opentrack.exe" `
-WorkingDirectory "$($global:openTrackDir)" -Verb RunAs -PassThru)

Add is used because I need reference to those apps to close them later.
Problem is opentrack generates in console some debug messages:

DEBUG [C:\repos\opentrack\api/plugin-support.hpp:106]: library "kinect-face" failed: "Cannot load library C:\\Program Files\\opentrack\\modules\\\\opentrack-tracker-kinect-face.dll: Can't

I would like to get rid of those messages but I don't know how to do this.
I found page https://powershell.one/code/9.html and those solutions seems to be something I look for, but when I try to apply something there is no effect.

How to remove not wanted messages from console effectively (if it is possible).


Solution

  • In order to silence the output from your elevated process, you need to call via a shell and use its redirections (you cannot use -RedirectStandardOutput / -RedirectStandardError, because it cannot be combined with -Verb RunAs).

    While you could use powershell.exe, cmd.exe is more lightweight; the following silences both the stdout and stderr streams:

    $this.apps.Add(
      (Start-Process -Verb RunAs -PassThru `
        -FilePath cmd.exe -Args "/c cd /d `"$global:openTrackDir`" && `"$global:openTrackDir\opentrack.exe`" >NUL 2>&1"
      )
    )
    

    Note that I've omitted -WorkingDirectory "$global:openTrackDir" and have instead included a cd command as part of the shell command to pass to cmd.exe, because the -WorkingDirectory argument would be ignored in combination with -Verb RunAs.[1]

    Limitations:


    [1] -WorkingDirectory would be honored by .NET applications in general, such as pwsh.exe, the PowerShell (Core) 7 CLI, but, curiously, not by powershell.exe, the Windows PowerShell CLI, which in this context behaves like a native application such as cmd.exe - see this answer for details.

    [2] Note that killing the directly launched elevated process works even when running in a non-elevated session, but only if the process-information object - obtained via Start-Process's -PassThru switch - is passed to Stop-Process. That is, $this.apps[$i] | Stop-Process and Stop-Process $this.apps[$i] both work, but Stop-Process -Id $this.apps[$i].Id does not.
    However, killing only the cmd.exe intermediary isn't sufficient, because the child process launched from it lives on.