两个相关因素决定了<代码>-ErrorAction和/或$ 参考代码>在发出特定指挥时无效:
从根本上说,由于强权 壳牌复印件工程,在script模块(即,在PowerShell实施,而不是通过汇编的网络组装)上安装的指令,见p参引变量,包括<$_ErrActionorActionor。 参考代码>,但从全球范围,即not<>> 当你要求使用(非专用)文字或功能时。
使用.implicit remoting - which are by definition script <>>>>>>>>>>>>>>>>>> 复杂性:
由这些模块指挥的,甚至<代码>-ErrorAction Stop 无效,因为这一参数为propagated至remotelycut的指挥,而设计为remotely。 正在发生的断层错误将 当地<>m> /em> 转化为 无终止错误。
- I believe the design rationale behind this to be the following, related to PowerShell remoting in general:
- When targeting multiple remote machines, such as via
Invoke-Command
s -ComputerName
parameter, a terminating error occurring remotely should not terminate the multi-machine operation overall, therefore such as remotely terminating errors are translated into locally non-terminating ones.
- This logic applies to scenarios with implicit remoting too - despite the fact that by definition only one remote machine is being targeted.
虽然使用隐含的重温通常是要求采取明确行动,例如使用Import-PSSession
。 厘米度——有一种假设,即暗中转动automatically。 缺省:
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell. Ravi/about_PowerShell_Compatibility" rel=nofollow nore参赛人>>自动进口。
While this isn t technically remoting, given that everything happens on the local machine, the underlying cross-process communication mechanism is the same as in true remoting, which - as an aside - also reduces type fidelity - see this answer.
The only way to turn such remotely occurring, invariably non-terminating errors into terminating ones that can be caught with try
/ catch
is to (temporarily) set the global incarnation of the $ErrorActionPreference
variable to Stop
, as shown below.
Workarounds:
For commands from regular script modules , i.e. modules implemented in PowerShell code that do not use implicit remoting, which includes CDXML-based modules):
For commands from modules that use implicit remoting, which includes those loaded via the Windows PowerShell Compatibility feature (and which are by definition also script modules):
<>strong>(当时)将global$ErrorAction> 缩略语条码>改为<条码>
& { # Simulate running in a child scope.
$prevGlobalPref = $global:ErrorActionPreference
$global:ErrorActionPreference = Stop
try {
Get-AppLockerFileInformation NoSuch.exe
}
catch {
"OK, now we get here: $_"
} finally {
$global:ErrorActionPreference = $prevGlobalPref
}
}
As for how to tell whether a given command is from either module type:
The following helper function, Get-CommandModuleType
, tells you what type of module a given command is from, with output Script
indicating a regular (non-implicitly-remoting) script module, and ImplicitRemoting
an implicitly remoting one; see the comment-based help in the source code for details.
Sample calls, from PowerShell (Core) on Windows:
# -> Script
Get-CommandModuleType.ps1 Get-NetAdapter
# -> ImplicitRemoting
Get-CommandModuleType.ps1 Get-AppLockerFileInformation
function Get-CommandModuleType {
<#
.SYNOPSIS
Indicates the type of module that the specified command is from.
.DESCRIPTION
Aliases are automatically resolved to their underlying commands.
Note:
* If the command *isn t from a module*, there is no output.
* The output is a *string* that is one of the following:
* ImplicitRemoting for an implicitly remoting module.
* Script for regular script modules (that don t use implicit remoting)
* Otherwise, the stringified version of the System.Management.Automation.ModuleType
value reported by the `.ModuleType` property of the underlying module.
* IMPORTANT:
* Not all script modules report themselves as such via the underlying
module s manifest; some of them report just Manifest . If you want
to see this formal value, use the -Raw switch.
.EXAMPLE
Get-CommandModuleType Get-NetAdapter
Reports the *de facto* type of module that hosts the Get-NetAdapter command.
.EXAMPLE
Get-CommandModuleType Get-NetAdapter -Raw
Reports the *formal* type of module that hosts the Get-NetAdapter, as implied
by its manifest.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string] $CommandName,
[switch] $Raw
)
$command = Get-Command $CommandName
if ($command -and $command.ResolvedCommand) {
$command = $command.ResolvedCommand
Write-Verbose "Resolved command is: $command"
}
if ($module = $command.Module) {
Write-Verbose "Source module is: $module"
if (-not $Raw -and $command.CommandType -eq Function -and $module) {
# a script module
if ($module.PrivateData.ImplicitRemoting) {
# an implicitly remoting module
ImplicitRemoting
}
else {
Script
}
}
else {
if ($Raw) { Write-Verbose Reporting raw module type, i.e as manifested. }
$module.ModuleType.ToString()
}
}
}