Powershell 使用 $true 和 $false 导入 csv

Powershell import csv with $true and $false

我正在尝试学习如何在 Powershell 中导入 csv 并从中创建用户。 我需要导入的值之一需要转换为布尔值。这些值只会是 $truefalse.

我当前的密码是

param([Parameter(Mandatory)][string] $inputfile)

$ADUsers = Import-csv $inputfile -Delimiter ';'

foreach ($User in $ADUsers) {
    $Name = $User.Name
    $SurName = $User.sn
    $GivenName = $User.Givenname
    $Email = $User.Email
    $SamAccountName = $User.samAccount
    $Path = $User.ParentOU
    $Password = $User.Password
    $Enabled = [System.Convert]::ToBoolean($User.Enabled)
    $ChangePasswordAtLogon = [System.Convert]::ToBoolean($User.mustChangePassword)
    $Description = $User.Description
    
    New-ADUser `
        -Name = $Name `
        -Surname =  $SurName `
        -GivenName = $GivenName `
        -EmailAddress = $Email `
        -SamAccountName = $SamAccountName `
        -Path = $Path `
        -AccountPassword (ConvertTo-SecureString $Password -AsPlainText -Force) `
        -Enabled = $Enabled `
        -ChangePasswordAtLogon = $ChangePasswordAtLogon `
        -Description = $Description
}

使用当前代码,我唯一的问题(目前)似乎是我无法将此字符串解析为布尔值。错误: Exception calling "ToBoolean" with "1" argument(s): "String was not recognized as a valid Boolean."

谁知道解决此问题的最佳方法?

如果 CSV 包含 EnabledChangePasswordAtLogon 的字面意思为 '$true''$false' 的字符串值,您需要从中删除美元符号才能将它们转换成真正的布尔值。

此外,我建议使用 Splatting New-ADUser 的参数,这样您就可以摆脱所有那些不需要的额外变量,尤其是那些讨厌的反引号:

param([Parameter(Mandatory)][string] $inputfile)

$ADUsers = Import-Csv -Path $inputfile -Delimiter ';'

foreach ($User in $ADUsers) {
    $userParams = @{
        Name                  = $User.Name
        Surname               = $User.sn
        GivenName             = $User.Givenname
        EmailAddress          = $User.Email
        SamAccountName        = $User.samAccount
        Path                  = $User.ParentOU
        AccountPassword       = (ConvertTo-SecureString $User.Password -AsPlainText -Force)
        Description           = $User.Description
        # if these values in the CSV are '$true' or '$false' literally, remove the dollar sign
        Enabled               = [System.Convert]::ToBoolean($User.Enabled -replace '$')
        ChangePasswordAtLogon = [System.Convert]::ToBoolean($User.mustChangePassword -replace '$')
    }

    New-ADUser @userParams
}

提供了一个有效的、简化的解决方案;让我添加一些背景信息:

  • Import-Csv 从 CSV 数据创建的对象的 属性 值总是 strings(即类型 [string]).

  • 从根本上不能将[string]值传递给[bool][switch]参数 - 即使这些字符串值为 'True''False'.

    • 将这些值转换为 [bool] 的最简单方法是 [bool]::Parse($stringContainingTrueOrFalse)(大小写无关紧要,转换工作与文化无关效果)。
  • [bool] 参数 很少见,不像更常见的 [switch] 参数(见下文),也接受数字0转换为$false,任何非零数字转换为$true.

  • [switch] parameters 只接受实际的 [bool],但请注意它们 很少需要 显式参数,因为它们的存在或不存在暗示了它们的价值;例如,-Force-Force:$true 相同(注意在这种情况下需要在参数名称后跟 :);并且 not 指定 -Force(通常)与
    相同 -Force:$false;只有两种情况需要传递显式参数:

    • 通过变量以编程方式传递开关(例如,-Force:$value
    • 覆盖偏好变量(例如-Confirm:$false跳过确认提示,否则会根据$ConfirmPreference偏好变量的值显示);在这种特定情况下,将 $false 作为显式参数传递 比完全省略开关会做 更多

注:

以上适用于参数绑定.
相比之下,表达式上下文中的字符串(和其他对象)可以转换或强制转换为[bool],尽管 行为可能令人惊讶 :

  • 字符串计算为$false,而任何非空字符串$true,即不考虑其具体内容.

值得注意的是:

PS> [bool] 'False'
True # !! Evaluates to $true, because 'False' is a *non-empty* string.

不过,一般来说,这种行为很有用,因为它允许您直接将字符串用作条件;以下语句是等效的:

if ($string.Length -gt 0) { 'non-empty' }

# Equivalent shorthand
if ($string) { 'non-empty' }

请参阅 的底部部分以了解 PowerShell 对所有类型的隐式布尔转换的概述


陷阱,从 PowerShell 7.2 开始:

虽然 将字符串 转换为 [bool] 如上所示,但 [bool] 变量 类型约束 意外地表现得像 参数声明:

也就是说,虽然您希望 $var = [bool] 'foo'[bool] $var = 'foo' 的工作方式相同(除了后者锁定变量输入),后者 失败 :

PS> $var = [bool] 'foo'  # OK: stores $true in $var

PS> [bool] $var =  'foo'  # !! FAILS
... Cannot convert value "System.String" to type "System.Boolean".
Boolean parameters accept only Boolean values and numbers, such as $True, $False, 1 or 0.

GitHub issue #10426 中讨论了这种有问题的不对称性。