Create O365 group and copy members from another group..

Hi,
For a day I have been trying to learn enough Powershell stuff to create myself a script that I badly need :-)

It loops through my O365 security groups, and selects a few of those that it should copy to mail-enabled distribution groups.
I have succeeded in almost everything except synching the members from the source group to the target group.  Do I have to erase all the members in the target group and fill it again with the current members of the source group?   Please see the two comment lines, first after the create group line, and the second where members should be updated according to the source group.   $GroupMembers contains the members of the current source group.  Thanks a lot for help on this.

Also, I'm confused that the email domain of the new email-enabled distribution groups are not my default domain.  We have two O365 domains,  mydomain.onmicrosoft.com and mydomain.com. The latter is set as default in O365.  Despite this my created email-enabled distribution groups get <alias>@mydomain.onmicrosoft.com as email address.  How do I force them to have mydomain.com as email domain?

Here is a section of my code:
      $GroupMembers = Get-MsolGroupMember -GroupObjectId $GroupObjectID
      Write-Host $Description $DispName $CommonName $EmailAddress
      if ($DoCreate -eq $TRUE) {
        $DistGroup = Get-DistributionGroup -Identity $CommonName
        if ($DistGroup -eq $NULL) {
          Write-Host "Now creating mail-enabled security group"
          New-DistributionGroup -Name $CommonName -DisplayName $DispName -Alias $AliasName -Notes $Description -Type "Security"
          # How do I correctly add $GroupMembers here?
        }
        else
        {
         Write-Host "Mail-enabled security group $CommonName already exists!  Now updating members!"
         # How do I correctly update $DistGroup with the current $GroupMembers here?
        }
      }
datatorAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Vasil Michev (MVP)Commented:
Assuming $GroupMembers contains the list of users you want to add, you can do something like:

$GroupMembers | foreach { Add-DistributionGroupMember empty -Member $_.EmailAddress }

Open in new window


This will basically cycle over each member listed in $GroupMembers and pass the value of its EmailAddress parameter to the Add-DistributionGroupMember cmdlet.

As for the group address, use this:

New-DistributionGroup -Name $CommonName -DisplayName $DispName -Alias $AliasName -Notes $Description -Type "Security" -PrimarySmtpAddress group@domain.com

Open in new window

datatorAuthor Commented:
Hi Vasil,

Thanks a lot for the tips.  However I have a question about the Member adding line above.  You use the parameter 'empty' there.  What does that mean?   I thought I have to specify the name of the target group like this:

$GroupMembers | foreach { Add-DistributionGroupMember -Identity $CommonName -Member $_.EmailAddress }

Did you mean that I should fill in the appropriate target group identity where you put 'empty'?

Does the line above just add members from the source group to the target group, OR if members are changed or removed in the source group, does it update the target group members accordingly?  If not, I would need to know how to update the target group members too...

Thanks for some light on this :-)

best regards

Tor
Vasil Michev (MVP)Commented:
Oh, well "empty" is the name of my test group. Creative, I know :) Just replace it with the group name, or $CommonName.

The Add- cmdlet will add any member currently listed in the source group to the target one. It's a one-time action, if membership of the source group changes in the future you will have to update the target one as well. If this is what you are after, maybe you should consider adding the entire source group as a member of the target one (i.e. nested group)?
Angular Fundamentals

Learn the fundamentals of Angular 2, a JavaScript framework for developing dynamic single page applications.

datatorAuthor Commented:
Hi again,
In the case where the target group doesn't exist, I want to add all the source group members - which it does now.
In the case where the target group exist, I just need to update the members of the target group so it equals those of the source group.  
It seems to be a good solution to just add the source group as the target group's sole member.  That can be done when creating ithe target group and we don't need to deal more with the memberships.
HOWEVER the source group is a plain security group and the target group is a mail-eanbled security group.   Can a security group be a member of a mail-eanbled security group? If yes, how will the code look like?

My source group loop starts like this:

Get-MsolGroup -all -GroupType Security| %{
  $DispName = $_.DisplayName
  $Description = $_.Description
  $CourceGroupObjectID = $_.ObjectID

Can I do this when adding the new target group:

New-DistributionGroup -Name $CommonName -DisplayName $DispName -Alias $AliasName -Notes $Description -Type "Security" -PrimarySmtpAddress $EmailAddress
Add-DistributionGroupMember -Identity $CommonName -Member $CourceGroupObjectID

I need a confirmation before I try this so I don't mess things up...

regards

Tor
Vasil Michev (MVP)Commented:
Hm, well it seems I was wrong on that part. While you can certainly add a security group as a member of DG, Exchange doesnt seem to expand the membership correctly (that is, it will only expand it for mail-enabled groups). Here's a reference: http://serverfault.com/questions/278910/can-i-nest-security-groups-not-mail-enabled-inside-a-distribution-list-to-hav

So unfortunately there is no way to keep the two groups in sync. If you want to match the membership at least on the initial script run, I guess what you can do is to remove all members of the target DG and populate it with the members of the source one.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
datatorAuthor Commented:
Ok, thanks for the update.  I will do that.
datatorAuthor Commented:
Hi again,
Unfortunately I ran into problems in testing if the distribution group existed or not.  
$GroupMembers holds the source group members

1st issue:
$DistGroup should be the target distribution group object (assigned if it exists, to avoid exception I use -ea 0)
I thought that if it doesn't exist then $DistGroup will be NULL, but it does not seem to work.
How should I correctly test if the target distribution group $DistGroup exists?

2nd issue:
If the target distribution group exists, its members should be retrieved in $DistGroupMembers.
How do I correctly use this member array in the following Remove-DistributionGroupMember call?  
I need to remove all members from the group before adding those from the source group.

Excerpt from the actual code section:

    $GroupMembers = Get-MsolGroupMember -GroupObjectId $GroupObjectID
    Write-Host $Description $DispName $CommonName $EmailAddress
    $DistGroup = Get-DistributionGroup -Identity $CommonName -ea 0
    if ($DistGroup -eq $NULL) {
      Write-Host "DistributionGroup $CommonName does not exist, creating it now...."
      if ($DoCreate -eq $TRUE) {
        New-DistributionGroup -Name $CommonName -DisplayName $DispName -Alias $AliasName -Notes $Description -Type "Security" -PrimarySmtpAddress $EmailAddress
        $GroupMembers | foreach { Add-DistributionGroupMember -Identity $CommonName -Member $_.EmailAddress }
      }
    }
    else
    {
      Write-Host "DistributionGroup $CommonName already exists!  Updating members only!"
      if ($DoCreate -eq $TRUE) {
        $DistGroupMembers = Get-MsolGroupMember -GroupObjectId $DistGroup.$_ObjectID
        Remove-DistributionGroupMember -Identity $CommonName -Member $DistGroupMembers
        #GroupMembers | foreach { Add-DistributionGroupMember -Identity $CommonName -Member $_.EmailAddress }
      }
    }

Thanks for any help on this

best regards
Tor
Vasil Michev (MVP)Commented:
1) $null should handle it properly, unless $CommonName doesnt exist - then $DistGroup will return a list of all groups. Check the value after the if statement I guess, it should give you a pointer on what's going on. Instead of comparing to $null, you can try something like

if ($DistGroup) {do stuff}

or check against the number of elements (i.e. zero should correspond to the case where no matching DG was foung):

if ($DistGroup.count -gt 0) {do stuff}

2) Use Get-DistributionGroupMember instead

$DistGroupMembers = Get-DistributionGroupMember -Identity $DistGroup 
$DistGroupMembers | % { Remove-DistributionGroupMember -Identity $DistGroup -Member $_.PrimarySmtpAddress -WhatIf } #remove the -whatif once you verify it works as expected
$GroupMembers | foreach { Add-DistributionGroupMember -Identity $DistGroup -Member $_.EmailAddress }

Open in new window

datatorAuthor Commented:
Unfortunately the:

$DistGroupMembers = Get-DistributionGroupMember -Identity $DistGroup
$DistGroupMembers | % { Remove-DistributionGroupMember -Identity $DistGroup -Member $_.PrimarySmtpAddress -WhatIf } #remove the -whatif once you verify it works as expected
$GroupMembers | foreach { Add-DistributionGroupMember -Identity $DistGroup -Member $_.EmailAddress }

.. code throws this exception:                                          

Cannot process argument transformation on parameter 'Identity'. Cannot convert
value "EMailGroup Servicepersonalet2" to type "Microsoft.Exchange.Configuration
.Tasks.DistributionGroupIdParameter". Error: "Cannot convert hashtable to an ob
ject of the following type: Microsoft.Exchange.Configuration.Tasks.Distribution
GroupIdParameter. Hashtable-to-Object conversion is not supported in restricted
 language mode or a Data section."
    + CategoryInfo          : InvalidData: (:) [Add-DistributionGroupMember],
   ParameterBindin...mationException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,Add-Distrib
   utionGroupMember
    + PSComputerName        : outlook.office365.com

It's late here so I have to throw in the towel now, will try further tomorrow.

best regards

Tor
Vasil Michev (MVP)Commented:
Try replacing $DistGroup with $DistGroup.Identity or $DistGroup.PrimarySmtpAddress
datatorAuthor Commented:
Like this?  (Note that I renamed some variables for better clarity)

    $TargetGroup = Get-DistributionGroup -Identity $TargetCommonName -ea 0
    if ($TargetGroup) { # TargetGroup exists already, now delete and re-add all members
      Write-Host "DistributionGroup $TargetCommonName already exists!  Now deleting and re-adding members..."
      if ($DoCreate -eq $TRUE) {
        $TargetGroupMembers = Get-DistributionGroupMember -Identity $TargetGroup 
        $TargetGroupMembers | % { Remove-DistributionGroupMember -Identity $TargetGroup.PrimarySmtpAddress  -Member $_.EmailAddress }
        $SourceGroupMembers | foreach { Add-DistributionGroupMember -Identity $TargetGroup.PrimarySmtpAddress  -Member $_.EmailAddress } 
      }
    }
    else # Target group does not exist, create it and populate it with source group members 
    {
      Write-Host "DistributionGroup $TargetCommonName does not exist, now creating and populating it...."
      if ($DoCreate -eq $TRUE) {
        New-DistributionGroup -Name $TargetCommonName -DisplayName $TargetDispName -Alias $TargetAliasName -Notes $SourceDescr -Type "Security" -PrimarySmtpAddress $SourceEmail 
        $SourceGroupMembers | foreach { Add-DistributionGroupMember -Identity $TargetCommonName -Member $_.EmailAddress }
      }
    } 
  }

Open in new window


Here is the error message that comes when the target group exists:

PS C:\Users\dev\Desktop> E:\ListGroups.ps1
PS C:\Users\dev\Desktop> E:\ListGroups.ps1
DistributionGroup Servicepersonalet already exists!  Now deleting and re-adding
members...
Cannot process argument transformation on parameter 'Identity'. Cannot convert
value "ServicepersonalPers" to type "Microsoft.Exchange.Configuration.Tasks.Dis
tributionGroupMemberIdParameter". Error: "Cannot convert hashtable to an object
 of the following type: Microsoft.Exchange.Configuration.Tasks.DistributionGrou
pMemberIdParameter. Hashtable-to-Object conversion is not supported in restrict
ed language mode or a Data section."
    + CategoryInfo          : InvalidData: (:) [Get-DistributionGroupMember],
   ParameterBindin...mationException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,Get-Distrib
   utionGroupMember
    + PSComputerName        : outlook.office365.com

The recipient "agngul02@framnes.vgs.no" is already a member of the group "Servi
cepersonalet".
    + CategoryInfo          : NotSpecified: (agngul02@framnes.vgs.no:Recipient
   WithAdUserGroupIdParameter`1) [Add-DistributionGroupMember], MemberAlready
  ExistsException
    + FullyQualifiedErrorId : [Server=AM2PR03MB0740,RequestId=e2c2d6a4-0241-4d
   7b-b7b2-577b75d9ec7a,TimeStamp=14.11.2015 15:45:00] [FailureCategory=Cmdle
  t-MemberAlreadyExistsException] 5F3FDCDF,Microsoft.Exchange.Management.Rec
 ipientTasks.AddDistributionGroupMember
    + PSComputerName        : outlook.office365.com

Open in new window

Vasil Michev (MVP)Commented:
Well no, you are again providing the entire object. Try:

$TargetGroupMembers = Get-DistributionGroupMember -Identity $TargetGroup.PrimarySmtpAddress

Open in new window

datatorAuthor Commented:
Sorry Vasil, I was unsure on which of the lines to apply the field.  

Now the code works, thanks a lot for all your help.  I feel I have learnt a lot on these three days!

regards Tor
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Office 365

From novice to tech pro — start learning today.