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


73

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

如果我du c:\Backup在控制台中运行,它可以按预期运行,但是在ISE或PowerGui中运行的同一行代码给出了预期的结果以及错误

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

这是为什么?如何避免此错误?我尝试使用调用invoke-expression &,但没有成功。

谢谢您的帮助。


4
请注意,如果您$ErrorActionPreference设置为Stop此项,则实际上将停止脚本的执行。我的解决方案是将其设置为Continue,调用命令,然后将其设置回Stop
Ohad Schneider


1
@OhadSchneider谢谢,您为我节省了几天的痛苦!我只是无法理解为什么在Docker容器中运行时我的脚本结果会有所不同并$ErrorActionPreference = 'Continue'解决了问题
Oliver Dungey

Answers:


50

为了避免这种情况,您可以将stderr重定向为null,例如:

du 2> $null

本质上,控制台主机和ISE(以及远程处理)对stderr流的处理不同。在控制台主机上,PowerShell支持诸如edit.com之类的应用程序与其他将彩色输出和错误写入屏幕的应用程序一起使用非常重要。如果未在控制台主机上重定向I / O流,则PowerShell将为本机EXE提供控制台句柄以直接写入。这会绕过PowerShell,因此PowerShell无法看到写入的错误,因此它无法通过$ error或写入PowerShell的stderr流来报告错误。

ISE和远程处理不需要支持此方案,因此它们确实会在stderr上看到错误,然后写入错误并更新$ error。


与PSEXEC正常工作!谢谢!
山本彰(Akira Yamamoto)

2
在一般情况下,隐藏stderr是个坏主意,最好将其重定向到stdout。
伊万

但是,的价值$?仍然是False?也许这仅在我的特定情况下(docker-compose远程运行命令)。
Anthony Mastrean '17

3
该答案将丢弃stderr,因此从根本上讲是疯狂的。有关单行将stderr重定向到stdout保留标准选项传递语法的信息,请参见sschuberth的答案–与下一个答案不同,下一个答案在传递选项时在语法上会崩溃。
Cecil Curry

44

我最近遇到了同样的问题,但是我想将stderr输出定向到stdout。您会认为以下方法会起作用:

    & du 2>&1

但是PowerShell将解释重定向并在“ du”完成后对其进行处理。我发现的解决方法是使用cmd.exe / c调用它:

    & cmd /c 'du 2>&1'

在我无法使用KeithHill的答案的情况下,这为我工作。谢谢SimonEjsing!
mbourgon 2013年

这对我有用,没有在cmd上下文中执行,我仍然收到错误。
乔恩·H

6
这对我有用。我还需要传递选项,所以对我来说完整的语法是& cmd /c 'foo.exe 2>&1' option1 option2。(请注意,只有可执行文件名和2>&1单引号中的go
为止

实际上,您可以将重定向放在最后,并可以使用带空格的路径(用引号引起来)等。例如: cmd /c ('"' + $ezfuscator + '" ' + $obfuscatedFolder + $targetName + '.exe' + ' -k ..\strongkey.snk' + ' 2>&1')
drizin

如果您要重定向,或者有$ ErrorActionPreference =“ Stop”,则这是当前唯一可行的答案。
aggieNick02 '19

36

抑制NativeCommandError输出的另一种方法是将管道中的对象转换为此答案底部概述的字符串

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

13
我恨你,PowerShell。尽管厌恶这种厌恶,但我还是赞赏上述一线内含的精神错乱。是的,它不可读。但是不是吗?这是明确的解决办法。而被接受的答案会丢弃所有stderr(明显有害!),并且未来的答案推迟至CMD.exe甚至更少传球选择时相比,该解决方案可读取!),这个答案既stderr重定向到标准输出蜜饯标准选项传递语法。
Cecil Curry

请注意,当您也要重定向标准输出(例如,重定向到文件)时,需要将对象转换为字符串执行此操作:du c:\backup 2>&1 | %{ "$_" } >outputfile.txt
Ignitor

1
其次,您的观点@Cecil Curry。请注意,虽然我喜欢这个答案的清洁程度,但是不幸的是,它不适用于$ ErrorActionPreference =“ Stop”。因此,cmd / c包装是我不得不采取的措施。叹。
aggieNick02 '19

2

以前的FIX将重定向错误,但是如果您的用户名或密码不佳,或者使用集成身份验证没有访问权限,则可能会导致真正的错误。

因此,这是一种实现错误处理并绕过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
}


1
如果您可以填充其余代码以使其可编译,则该代码当前无效。
肖恩
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.