2

I'm migrating an on-prem Exchange environment to Office 365 and currently trying to script some of the migration tasks. One task in particular is to export groups and group members to CSV from the on-prem environment, then import the CSV data to Office 365.

I've created the following script to try and import the groups to Office 365:

# Import distribution groups from CSV to Office 365
Import-Csv c:\admin\exchange-migration\exports\distribution-groups.csv | foreach {
    New-DistributionGroup -Name $_.name -Alias $_.alias -PrimarySmtpAddress $_.primarysmtpaddress -Type Distribution -RequireSenderAuthenticationEnabled ([System.Convert]::ToBoolean($_.requiresenderauthenticationenable))
}

I was having trouble with the "requiresenderauthenticationenabled" portion cause I couldn't convert a string to a boolean value, but after some research I came up with the [System.Convert] option. However now every value is being treated as FALSE.

Here's my CSV

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
Nick Myers
  • 21
  • 1
  • 2

1 Answers1

0

Mathias R. Jessen provided the crucial pointer:

You had a typo in the property name you passed to [System.Convert]::ToBoolean(), which caused the property to reference to always evaluate to $null, which the .NET method always converted to $false.

To prevent such typos in the future, you could set Set-StrictMode -Version 2 or higher, which will report a statement-terminating error, if an uninitialized variable or nonexistent property is being referenced:

Set-StrictMode -Version 2

# Try to reference a nonexistent property on an input object.
[pscustomobject] @{ one = 1; two = 2; three = 3 } | % { $_.four }
# -> Error "The property 'four' cannot be found on this object. 
#           Verify that the property exists"

Unfortunately, however, this strict mode has potentially unwanted side effects:

  • Its effect isn't lexical and therefore can affect execution of code that wasn't designed with this mode in mind - there's a pending RFC to change that.

  • It prevents use of the .Count / .Length properties on scalars, which are important for unified treatment of collections and scalars.
    If you're also unhappy with the behavior described there, make your voice heard there.


Aside from the typo, a simpler way to force a string value that is either true or false (in any case variation) to the corresponding Boolean value is to use -eq 'true'; e.g.:
... -RequireSenderAuthenticationEnabled ($_.requiresenderauthenticationenabled -eq 'true')

That said, this is only robust if you can rely on the property values to be limited to string 'true' and 'false' - you wouldn't catch unexpected values that way, such as 'yes'.


As an aside, the New-DistributionGroup using [bool]-typed parameters instead of using [switch]-typed parameters is an unfortunate deviation from PowerShell's conventions.

If -RequireSenderAuthenticationEnabled were properly typed as a [switch]:

Instead of

-RequireSenderAuthenticationEnabled $true

you'd just pass the switch name itself:

-RequireSenderAuthenticationEnabled

and instead of

-RequireSenderAuthenticationEnabled $false

you'd:

  • normally simply omit the switch
  • but if you're building the arguments programmatically, via a Boolean stored in a variable, you'd use -RequireSenderAuthenticationEnabled:$var - note the required : between the switch name and the Boolean value.
mklement0
  • 382,024
  • 64
  • 607
  • 775