使用 IDE 从 Powershell 调用第三方可执行文件时出错

我有一个 PowerShell 脚本,它使用 du.exe (磁盘使用情况最初来自 Sysinterals)来计算目录的大小。

如果我在控制台中运行 du c:\Backup,它会像预期的那样工作,但是在 ISE 或 PowerGui 中运行的同一行代码会给出预期的结果加上错误

+ du <<<<  c:\backup
+ CategoryInfo          : NotSpecified: (:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError

为什么会这样? 我如何避免这个错误? 我尝试使用 &调用表达式,但是没有成功。

谢谢你的帮助。

80163 次浏览

To avoid this you can redirect stderr to null e.g.:

du 2> $null

Essentially the console host and ISE (as well as remoting) treat the stderr stream differently. On the console host it was important for PowerShell to support applications like edit.com to work along with other applications that write colored output and errors to the screen. If the I/O stream is not redirected on console host, PowerShell gives the native EXE a console handle to write to directly. This bypasses PowerShell so PowerShell can't see that there are errors written so it can't report the error via $error or by writing to PowerShell's stderr stream.

ISE and remoting don't need to support this scenario so they do see the errors on stderr and subsequently write the error and update $error.

I've recently been facing the same issues, but I would like to get the stderr output directed to stdout. You would think that the following would work:

    & du 2>&1

But PowerShell will interpret the redirection and process it after 'du' is completed. The work-around I found is to invoke it using cmd.exe /c:

    & cmd /c 'du 2>&1'

Another way to suppress the NativeCommandError output is to convert the objects in the pipeline to strings as outlined at the bottom of this answer:

du c:\Backup 2>&1 | %{ "$_" }

Previous FIX will redirect errors but you could lose a real error if by example your user name or password is not good or if using integrated authentication, you do not have access.

So here is a way to implement the error handling and bypass the specific error (that is not one) raised by psexec.

try {
whoami # powershell commands
}
catch [System.Management.Automation.RemoteException] {
if ($_.TargetObject -like "Connecting to *" -and $_.CategoryInfo.Category -eq "NotSpecified" -and $_.FullyQualifiedErrorId -eq "NativeCommandError" -and $_.InvocationInfo.MyCommand.Name -like "psexec*.exe") {
$error.Remove[$Error[0]]
}
else {
Throw
}
}
catch {
throw
}

After pulling a load of hair out, I realised that actually, these errors only occur when running the .ps1 file from "Windows PowerShell ISE".

When I ran the same .ps1 script from a Command Line, the errors didn't happen.

powershell.exe .\MikesScript.ps1

Write this script at the top of your PowerShell script it will solve this issue and even it will not affect the whole behavior of all error commands

#prepare powershell for docker-compose commands
if((select-string -Path $profile -Pattern "Set-Alias docker-compose 'docker-compose.cmd'") -eq $null ){
Add-Content -Path $profile -Value "Set-Alias docker-compose 'docker-compose.cmd'"}
$str = "@echo off
docker-compose.exe %1 %2 %3 %4 %5 %6 %7 %8 %9 2>&1"
if ((Get-Content "C:\Windows\System32\docker-compose.cmd" -ErrorAction Ignore) -ne $str){
$str.Trim() | Out-File "C:\Windows\System32\docker-compose.cmd" -Encoding ascii}