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

使用IDE时从Powershell调用第三方可执行文件时出错,ide,powershell,powergui,du,Ide,Powershell,Powergui,Du,我有一个PowerShell脚本,它使用du.exe(最初来自Sysinternals)来计算目录的大小 如果我在控制台中运行du c:\Backup,它会按预期工作,但在ISE或PowerGui中运行的同一行代码会给出预期结果和错误 + du <<<< c:\backup + CategoryInfo : NotSpecified: (:String) [], RemoteException + FullyQualifiedErrorId : Nat

我有一个PowerShell脚本,它使用du.exe(最初来自Sysinternals)来计算目录的大小

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

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

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

du 2> $null
本质上,控制台主机和ISE(以及远程处理)以不同的方式处理stderr流。在控制台主机上,PowerShell必须支持edit.com等应用程序与其他将彩色输出和错误写入屏幕的应用程序一起工作。如果未在控制台主机上重定向I/O流,PowerShell将为本机EXE提供一个控制台句柄以直接写入。这将绕过PowerShell,因此PowerShell无法看到已写入的错误,因此无法通过$error或写入PowerShell的stderr流来报告错误


ISE和远程处理不需要支持这种情况,因此它们确实可以在stderr上看到错误,然后写入错误并更新$error。

我最近遇到了相同的问题,但我希望将stderr输出定向到stdout。您可能认为以下方法可行:

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

    & cmd /c 'du 2>&1'

抑制
NativeCommandError
输出的另一种方法是将管道中的对象转换为字符串,如下图底部所示:


以前的修复程序将重定向错误,但如果您的用户名或密码不正确,或者如果使用集成身份验证,您没有访问权限,则可能会丢失真正的错误

因此,这里有一种实现错误处理并绕过psexec引发的特定错误(不是一个)的方法

试试看{
whoami#powershell命令
}
catch[System.Management.Automation.RemoteException]{
如果($\.TargetObject-如“连接到*”-和$\.CategoryInfo.Category-如“未指定”-和$\.FullyQualifiedErrorId-如“NativeCommandError”-和$\.InvocationInfo.MyCommand.Name-如“psexec*.exe”){
$error.Remove[$error[0]]
}
否则{
扔
}
}        
抓住{
扔

}
在我无法使用基思希尔的答案的情况下,这一点对我很有效。谢谢SimonEjsing!这对我有效,没有在cmd上下文中执行,我仍然得到错误。这对我有效。我还需要传入选项,因此我的完整语法是
&cmd/c'foo.exe 2>&1'option1 option2
。(请注意,只有可执行文件名和
2>&1
在单引号内。)实际上,您可以将重定向放在末尾,并且可以有带空格的路径(用引号括起来)等。例如:
cmd/c(“''+$ezfuscator+''+$obfuscatedFolder+$targetName+'.exe'+'-k..\strongkey.snk'+'2>&1')
如果您正在执行重定向,或者有$ErrorActionPreference=“Stop”,这是当前唯一有效的答案。与PSEXEC配合使用效果良好!谢谢在一般情况下,隐藏stderr是个坏主意,最好将其重定向到stdout。但是,
$?
的值仍然是
False
?或者这只是在我的特定场景中(远程运行
docker compose
命令)。这个答案抛弃了stderr,因此从根本上说是疯狂的。请参阅的答案中的a–不同于,传递选项时语法会发生故障。请注意,如果将
$ErrorActionPreference
设置为
停止
,这将实际停止脚本的执行。我的解决方案是将其设置为
继续
,调用命令,然后将其设置回
停止
。可能重复@OhadSchneider谢谢,你帮我省去了好几天的痛苦!我无法理解为什么在Docker容器中运行时脚本结果不同,并且
$ErrorActionPreference='Continue'
修复了这个问题,如果您可以填充代码的其余部分使其可编译,因为目前代码无效。注意:
$ErrorActionPreference=“stop”
是实际输入catch块所必需的。我恨你,PowerShell。尽管这种憎恶深重,我还是为上面这一行中所包含的疯狂鼓掌。是的,看不懂。但什么不是?这是最终的解决办法。虽然丢弃了所有的stderr(明显有害!),并遵从
CMD.exe
(传递选项时比此解决方案更难阅读!),但此答案既将stderr重定向到stdout,又保留了标准的选项传递语法。请注意,当您还想重定向stdout(例如,重定向到文件)时,在将对象转换为字符串后,您需要执行以下操作:
du c:\backup 2>&1 |%{“$\u”}>outputfile.txt
Second your thoughts@Cecil Curry。请注意,虽然我喜欢这个答案有多干净,但不幸的是它不适用于$ErrorActionPreference=“Stop”。所以cmd/c包装是我不得不求助的。叹气。如果您使用$ErrorActionPreference=“Stop”,您可以将其设置为“SilentlyContinue”,运行此行,然后将其设置回“Stop”。
du c:\Backup 2>&1 | %{ "$_" }