Reputation: 33
I am trying to learn how to import a csv in Powershell and create users out of it.
One of the values I need to import needs to be converted to a boolean. These values will only be $true
or false
.
My current code is
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
}
With the current code, my only problem (currently) seems to be I am unable to parse this string to a boolean. The error:
Exception calling "ToBoolean" with "1" argument(s): "String was not recognized as a valid Boolean."
Anyone who knows the best way to resolve this issue?
Upvotes: 1
Views: 2091
Reputation: 439247
Theo's helpful answer provides an effective, streamlined solution; let me add some background information:
The property values of the objects created from CSV data by Import-Csv
are invariably strings (i.e. of type [string]
).
You fundamentally cannot pass [string]
values to [bool]
or [switch]
parameters - even if those string values are 'True'
and 'False'
.
[bool]
is [bool]::Parse($stringContainingTrueOrFalse)
(case does not matter, and the conversion works irrespective of what culture is in effect).[bool]
parameters, which are rare, unlike the much more common [switch]
parameters (see below), accept numbers too: 0
converts to $false
, and any non-zero number to $true
.
[switch]
parameters only accept actual [bool]
values, though note that they rarely require an explicit argument, because it is their presence or absence that implies their value; e.g., -Force
is the same as -Force:$true
(note the need to follow the parameter name with :
in this case); and not specifying -Force
is (typically) the same as
-Force:$false
; there are only two scenarios in which passing an explicit argument is needed:
-Force:$value
)-Confirm:$false
to skip a confirmation prompt that would otherwise be shown based on the value of the $ConfirmPreference
preference variable); in this specific case passing $false
as an explicit argument does more than omitting the switch altogether would do.Note:
The above applies to parameter binding.
By contrast, in expression contexts strings (and other objects) can be cast or coerced to [bool]
, though the behavior can be surprising:
$false
, whereas any non-empty string is $true
, i.e. irrespective of its specific content.Notably:
PS> [bool] 'False'
True # !! Evaluates to $true, because 'False' is a *non-empty* string.
In general, though, this behavior is helpful, as it allows you to use strings directly as conditionals; the following statements are equivalent:
if ($string.Length -gt 0) { 'non-empty' }
# Equivalent shorthand
if ($string) { 'non-empty' }
See the bottom section of this answer for an overview of PowerShell's implicit to-Boolean conversion across all types.
Pitfall, as of PowerShell 7.2:
While a casting a string to [bool]
works as shown above, a [bool]
variable type constraint unexpectedly behaves like a parameter declaration:
That is, while you would expect $var = [bool] 'foo'
to work the same as [bool] $var = 'foo'
(aside from the latter locking the variably type in), the latter fails:
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.
This problematic asymmetry is discussed in GitHub issue #10426.
Upvotes: 1
Reputation: 61168
If the CSV contains string values for Enabled
and ChangePasswordAtLogon
literally as '$true'
or '$false'
, you need to remove the dollar sign from it to be able to convert them into real Boolean values.
Also, I would suggest using Splatting the parameters to New-ADUser
, so you can get rid of all those unneeded extra variables and especially those pesky backticks:
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
}
Upvotes: 3