Catch块在控制台中没有打印出警告消息。

huangapple go评论69阅读模式
英文:

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&#39;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) 为 `&#39;Stop&#39;`**:

```powershell
function checkAccount($user)
{
    # 让这个范围(和后代范围)中的所有错误都成为(脚本)终止错误,
    # 这使得它们可以使用 try / catch 捕捉到。
    $ErrorActionPreference = &#39;Stop&#39;
    try {
       Get-CimInstance Win32_UserAccount | 
         Where-Object -Property Name -eq $user | 
         Select-Object -ExpandProperty Name
    }
    catch {
        Write-Warning -Message &quot;Oops, ran into an issue&quot;
    }
}

此外,请注意,我已经将 -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 and Select-Object<sup>[1]</sup> - so you should use -ErrorAction Stop with both.

  • A simpler alternative is to set the $ErrorActionPreference preference variable to &#39;Stop&#39; 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 = &#39;Stop&#39;
    try {
       Get-CimInstance Win32_UserAccount | 
         Where-Object -Property Name -eq $user | 
         Select-Object -ExpandProperty Name
    }
    catch {
        Write-Warning -Message &quot;Oops, ran into an issue&quot;
    }
}

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>

huangapple
  • 本文由 发表于 2023年1月9日 02:27:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/75050330.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定