英文:
Catch block does not print out Warning message into console after
问题
我正在编写一个简单的脚本来检查本地用户账户。我想使用try_catch错误来处理错误,但我无法弄清楚为什么脚本中的catch块不会打印出警告消息。感谢任何指导。
function checkAccount($user)
{
try {
Get-CimInstance Win32_UserAccount| Where-Object -Property Name -Contains $user |Select-Object -ExpandProperty Name -ErrorAction Stop
}
catch {
Write-Warning -Message "哎呀,遇到了问题"
}
}
<details>
<summary>英文:</summary>
I am writing a simple script that checks for a local user account. I would like to use the try_catch error to handle errors but I am not able to figure out why the catch block in my script won't print out the warning message in the script. Any guidance is appreciated.
function checkAccount($user)
{
try {
Get-CimInstance Win32_UserAccount| Where-Object -Property Name -Contains $user |Select-Object -ExpandProperty Name -ErrorAction Stop
}
catch {
Write-Warning -Message "Oops, ran into an issue"
}
}
</details>
# 答案1
**得分**: 3
* 有两个命令可能会报告流水线中的非终止错误 - `Get-CimInstance` 和 `Select-Object`<sup>[1]</sup> - 因此,你应该在这两个命令中都使用 `-ErrorAction Stop`。
* 一个更简单的替代方法是**为整个函数设置 [`$ErrorActionPreference` 首选项变量](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Preference_Variables#erroractionpreference) 为 `'Stop'`**:
```powershell
function checkAccount($user)
{
# 让这个范围(和后代范围)中的所有错误都成为(脚本)终止错误,
# 这使得它们可以使用 try / catch 捕捉到。
$ErrorActionPreference = 'Stop'
try {
Get-CimInstance Win32_UserAccount |
Where-Object -Property Name -eq $user |
Select-Object -ExpandProperty Name
}
catch {
Write-Warning -Message "Oops, ran into an issue"
}
}
此外,请注意,我已经将 -Contains
替换为 -eq
,因为 -contains
操作符用于测试一个 集合 是否包含给定值,而你是逐个处理用户帐户。如果你的意图是执行 子字符串 匹配,请使用类似 -like *$user*
的东西。
注意:
- 从 脚本 模块 导入的高级(类似 cmdlet 的)函数不会看到首选项变量,除非它们恰好在 全局 范围中定义 - 有关这种问题行为的讨论,请参见 GitHub 问题 #4568。
如果你的意图只是测试 是否存在给定的用户帐户,你可以将函数定义如下,使用 已批准的动词 Test
并相应地使函数返回一个 [bool]
值($true
或 $false
):
function Test-Account($user)
{
[bool] (
Get-CimInstance Win32_UserAccount |
Where-Object -Property Name -eq $user
)
}
涉及的命令在正常情况下不会报告错误,因此不需要显式错误处理。
[bool]
转换利用了 PowerShell 的布尔转换规则,以及一个(非原始的)对象将转换为$true
,而 缺少输出 或$null
将转换为$false
- 请参阅 此答案 的底部部分,以获取转换规则的摘要。
[1] Get-CimInstance
通常只会因为无效的类名而报告错误,而 Select-Object -ExpandProperty
只会因为不存在的属性名称而报告错误(与 -Property
不同)。Where-Object
调用不应该报告错误,因为它不强制要求指定的属性存在(但是,使用 无效的语法 任何 cmdlet 调用都会报告 语句终止 错误)。
英文:
<!-- language-all: sh -->
-
There are two commands that could report non-terminating errors in your pipeline -
Get-CimInstance
andSelect-Object
<sup>[1]</sup> - so you should use-ErrorAction Stop
with both. -
A simpler alternative is to set the
$ErrorActionPreference
preference variable to'Stop'
for your entire function:
function checkAccount($user)
{
# Make all errors in this scope (and descendant scopes) (script)-terminating,
# which enables them to be caught with try / catch.
$ErrorActionPreference = 'Stop'
try {
Get-CimInstance Win32_UserAccount |
Where-Object -Property Name -eq $user |
Select-Object -ExpandProperty Name
}
catch {
Write-Warning -Message "Oops, ran into an issue"
}
}
Also note that I've replaced -Contains
with -eq
, given that the -contains
operator is for testing if a collection contains a given value, whereas you're processing the user accounts one by one.
If, by contrast, your intent is to perform substring matching, use something -like *$user*
instead.
Caveat:
- Advanced (cmdlet-like) functions imported from script modules do not see preference variables, unless they happen to be defined in the global scope - see GitHub issue #4568 for a discussion of this problematic behavior.
If, by contrast, your intent was simply to test if a given user account exists, you could define your function as follows, using the approved verb Test
and - accordingly - making the function return a [bool]
value ($true
or $false
):
function Test-Account($user)
{
[bool] (
Get-CimInstance Win32_UserAccount |
Where-Object -Property Name -eq $user
)
}
-
The commands involved will not report errors under normal conditions, so there's no need for explicit error handling.
-
The
[bool]
cast takes advantage of PowerShell's to-Boolean conversion rules and the fact that a (non-primitive) object converts to$true
, whereas lack of output or$null
convert to$false
- see the bottom section of this answer for a summary of the conversion rules.
<sup>[1] Get-CimInstance
should normally only report an error for an invalid class name, and Select-Object -ExpandProperty
only for a non-existent property name (unlike with -Property
). The Where-Object
call should never report an error, given that it doesn't enforce the existence of the specified property (however, with invalid syntax any cmdlet call would report a statement-terminating error).</sup>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论