• Skip to primary navigation
  • Skip to main content
  • Skip to footer

Stephanos Constantinou Blog

PowerShell Scripting

  • Home
  • Blogs
    • PowerShell Tutorials
    • PowerShell Scripts
    • PowerShell Modules
      • Modules Cmdlets
    • Software Reviews
  • About
  • Contact
You are here: Home / PowerShell Scripts / PowerShell Set Groups Custom Attributes

PowerShell Set Groups Custom Attributes

26/06/2018 by Stephanos Leave a Comment

PowerShell Set Groups Custom Attributes

Scenario:

Powershell Set Groups Custom Attributes

The script that we will see today is an updated version of an older post that was used to set groups custom attributes based on which Organizational Unit is under. The reason of the creation of such script was to ensure that delegation of permissions on Exchange Online will work without any issue. Delegation on Exchange Online has been provided on local It administrators using some filters. Part of that filter is to use CustomAttribute4 of distribution and security groups in order to provide administration access to them. If the value is not correct then they are not able to administer those objects.

Problems of initial version

The previous version of the script, was not so flexible and every time there was a change I have to check the script that I am not missing anything. Let’s see the problem below:

Static Arrays

When there was a change on Organizational Units in Active Directory I had to check all the respective arrays that is correct. There is a possibility to miss an Organizational Unit. If you miss one then the custom attribute will not be set and local IT will not be able to administer the groups below that Organizational Unit.

Old code:

$CYGroups = @("domain.com/Offices/Cyprus/Groups/DistributionGroups",`
              "domain.com/Offices/Cyprus/Groups/SecurityGroups")
$CNGroups = @("domain.com/Offices/China/Groups/DistributionGroups",`
              "domain.com/Offices/China/Groups/SecurityGroups")
$DEGroups = @("domain.com/Offices/Germany/Groups/DistributionGroups",`
              "domain.com/Offices/Germany/Groups/SecurityGroups")
$GRGroups = @("domain.com/Offices/Greece/Groups/DistributionGroups",`
              "domain.com/Offices/Greece/Groups/SecurityGroups")
$INGroups = @("domain.com/Offices/India/Groups/DistributionGroups",`
              "domain.com/Offices/India/Groups/SecurityGroups")
$UKGroups = @("domain.com/Offices/UnitedKingdom/Groups/DistributionGroups",`
              "domain.com/Offices/UnitedKingdom/Groups/SecurityGroups")

[adinserter name=”In Article”]

Multiple ElseIf

In the previous version, I was using multiple elseif in order to check the current value of the custom attribute and change it accordingly. This resulted in to have a lot of code, that a big part of it was duplicate. In this version I have replaced it with a switch statement. The code is less and clearer to read.

Old Code:

if (($CYGroups -contains $Group.OrganizationalUnit) -and ($Group.CustomAttribute4 -ne "Cyprus")){
      Set-DistributionGroup -Identity $Group.PrimarySmtpAddress -CustomAttribute4 "Cyprus" -ForceUpgrade
      $EmailTemp = @"
<tr>
   <td class="colorm">$Group</td>
   <td>Cyprus</td>
</tr>
"@
      $EmailResult = $EmailResult + "`r`n" + $EmailTemp
   }
   elseif (($CNGroups -contains $Group.OrganizationalUnit) -and ($Group.CustomAttribute4 -ne "China")){
      Set-DistributionGroup -Identity $Group.PrimarySmtpAddress -CustomAttribute4 "China" -ForceUpgrade
      $EmailTemp = @"
<tr>
   <td class="colorm">$Group</td>
   <td>China</td>
</tr>
"@
      $EmailResult = $EmailResult + "`r`n" + $EmailTemp
   }
   elseif (($DEGroups -contains $Group.OrganizationalUnit) -and ($Group.CustomAttribute4 -ne "Germany")){
      Set-DistributionGroup -Identity $Group.PrimarySmtpAddress -CustomAttribute4 "Germany" -ForceUpgrade
      $EmailTemp = @"
<tr>
   <td class="colorm">$Group</td>
   <td>Germany</td>
</tr>
"@
      $EmailResult = $EmailResult + "`r`n" + $EmailTemp
   }
   elseif (($GRGroups -contains $Group.OrganizationalUnit) -and ($Group.CustomAttribute4 -ne "Greece")){
      Set-DistributionGroup -Identity $Group.PrimarySmtpAddress -CustomAttribute4 "Greece" -ForceUpgrade
      $EmailTemp = @"
<tr>
   <td class="colorm">$Group</td>
   <td>Greece</td>
</tr>
"@
      $EmailResult = $EmailResult + "`r`n" + $EmailTemp
   }
   elseif (($INGroups -contains $Group.OrganizationalUnit) -and ($Group.CustomAttribute4 -ne "India")){
      Set-DistributionGroup -Identity $Group.PrimarySmtpAddress -CustomAttribute4 "India" -ForceUpgrade
      $EmailTemp = @"
<tr>
   <td class="colorm">$Group</td>
   <td>India</td>
</tr>
"@
      $EmailResult = $EmailResult + "`r`n" + $EmailTemp
   }
   elseif (($UKGroups -contains $Group.OrganizationalUnit) -and ($Group.CustomAttribute4 -ne "United Kingdom")){
      Set-DistributionGroup -Identity $Group.PrimarySmtpAddress -CustomAttribute4 "United Kingdom" -ForceUpgrade
      $EmailTemp = @"
<tr>
   <td class="colorm">$Group</td>
   <td>United Kingdom</td>
</tr>
"@
      $EmailResult = $EmailResult + "`r`n" + $EmailTemp
   }

[adinserter name=”In Article”]

Backtick

Previously there was use of backtick to present the code in a more readable way. Now, bakcticking has been removed and I have used the splatting and normal command line continuation where is applicable.

Old Code:

$CYGroups = @("domain.com/Offices/Cyprus/Groups/DistributionGroups",`
              "domain.com/Offices/Cyprus/Groups/SecurityGroups")
              
send-mailmessage `
      -To $To `
      -Subject "Distribution Groups CustomAttribute4 Report $(Get-Date -format dd/MM/yyyy)" `
      -Body $Email `
      -BodyAsHtml `
      -Priority high `
      -UseSsl `
      -Port 587 `
      -SmtpServer 'smtp.office365.com' `
      -From $From `
      -Credential $EmailCredentials

In order to make overcome the above issue that I had, I have made changes on my script, so the arrays will be dynamic, and if there is any addition in Organizational Units, I will not need to edit my script. It runs faster than before, it is smaller and easier to read.

How it works

The script is setup to work on a hybrid environment. In Hybrid environment all federated groups should be administered from Exchange On-Prem. First the script will connect to Exchange On-Prem so we will have the related cmdlets available. Later a few variables are defined in order to be used later to send the email report at the end of the script. After that it will retrieve all Organizational Units from Active Directory based on the filter that we define. In the script below the filter will keep only the Organizational Units that include Group and Distribution or Security in their Canonical Name. So we have two combinations, the first one is Group and Distribution and the second one is Group and Security. All groups are saved in a variable and then we filter that variable in order to create one array for each location. One more array is created later containing all groups in our system. Then the script will process that array

[adinserter name=”In Article”]

You can download the script here or copy it from below. (Note that code within the script might not be copied correctly due to syntax highlighting.)

Hope you like it.

You feedback is appreciated.

If you have any questions or anything else please let me know in the comments below.

Related Links:

  • PowerShell Scripts
  • PowerShell Tutorials
  • Exchange custom attributes on groups automatically with PowerShell
  • PowerShell Comparison Operators
  • PowerShell Arithmetic Operators
  • New-PSSession – Microsoft Docs
  • Import-PSSession – Microsoft Docs
  • Get-Content – Microsoft Docs
  • ConvertTo-SecureString – Microsoft Docs
  • New-Object – Microsoft Docs
  • Get-ADOrganizationalUnit – Microsoft Docs
  • Where-Object – Microsoft Docs
  • Get-DistributionGroup – Microsoft Docs
  • Set-DistributionGroup – Microsoft Docs
  • Send-MailMessage – Microsoft Docs
  • about_Foreach | Microsoft Docs
  • about_If | Microsoft Docs
  • about_Switch | Microsoft Docs

[adinserter name=”In Article”]

Solution / Script:

<#
.SYNOPSIS
  Name: Set-GroupCustomAttribute.ps1
  The purpose of this script is to set CustomAttribute4 of groups into a specific one
  based on their Organizational Unit in Active Directory.
  
.DESCRIPTION
  This is a script that collects all groups in Active Direcotry and sets CustomAttribute4
  of the group to the desired one based on Organizational Unit and the responsible IT.
  Report is sent with the changes applied if there are any. An error email report will also
  be sent if there are any errors duing run.
.RELATED LINKS
  
Home
.NOTES Version: 1.1 Update: - Converted static array of groups to dynamic - Converted static arrays of OUs to dynamic - Code improvements Release Date: 30-09-2016 Author: Stephanos Constantinou .EXAMPLE Run the script Set-GroupCustomAttribute.ps1 #> $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://exchange-server.domain.com/PowerShell/ -Authentication Kerberos Import-PSSession $Session $File = "C:\Scripts\Password.txt" $Key = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32) $EmailUser = "Script-User@domain.com" $Password = Get-Content $File | ConvertTo-SecureString -Key $Key $EmailCredentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $EmailUser,$Password $To = 'User1@domain.com' $From = 'Script-User@domain.com' $EmailResult = "" $AllGroupsOUs = (Get-ADOrganizationalUnit -Properties * -Filter * | Where-Object {($_.CanonicalName -like "*Groups*") -and (($_.CanonicalName -like "*DistributionGroups") -or ($_.CanonicalName -like "*SecurityGroups"))}).CanonicalName $CyprusGroupsOUs = $AllGroupsOUs | Where-Object {$_ -like "*Cyprus*"} $GreeceGroupsOUs = $AllGroupsOUs | Where-Object {$_ -like "*Greece*"} $GermanyGroupsOUs = $AllGroupsOUs | Where-Object {$_ -like "*Germany*"} $ChinaGroupsOUs = $AllGroupsOUs | Where-Object {$_ -like "*China*"} $UnitedKingdomGroupsOUs = $AllGroupsOUs | Where-Object {$_ -like "*UnitedKingdom*"} $IndiaGroupsOUs = $AllGroupsOUs | Where-Object {$_ -like "*India*"} $DCGroupsOUs = $AllGroupsOUs | Where-Object {$_ -like "*Datacenter*"} $AllGroups = Get-DistributionGroup -OrganizationalUnit "domain.com/Offices" -ResultSize Unlimited $EmailResult = "" foreach ($Group in $AllGroups){ if ($Group.MemberJoinRestriction -eq "Open") {Set-DistributionGroup -Identity $Group.PrimarySmtpAddress -MemberJoinRestriction "Closed" -ForceUpgrade} if ($Group.MemberDepartRestriction -eq "Open") {Set-DistributionGroup -Identity $Group.PrimarySmtpAddress -MemberDepartRestriction "Closed" -ForceUpgrade} Switch -Regex ($Group){ {$CYGroupsOUs -contains $Group.OrganizationalUnit}{ $Attribute4Value = "Cyprus";Break} {$ChinaGroupsOUs -contains $Group.OrganizationalUnit}{ $Attribute4Value = "China";Break} {$GermanyGroupsOUs -contains $Group.OrganizationalUnit}{ $Attribute4Value = "Germany";Break} {$GreeceGroupsOUs -contains $Group.OrganizationalUnit}{ $Attribute4Value = "Greece";Break} {$IndiaGroupsOUs -contains $Group.OrganizationalUnit}{ $Attribute4Value = "India";Break} {$UnitedKingdomGroupsOUs -contains $Group.OrganizationalUnit}{ $Attribute4Value = "UnitedKingdom";Break} {$DCGroupsOUs -contains $Group.OrganizationalUnit}{ $Attribute4Value = "Frankfurt";Break} } if ($Group.CustomAttribute4 -ne $Attribute4Value){ $GroupPrimarySmtpAddress = $Group.PrimarySmtpAddress $GroupParams = @{ Identity = $GroupPrimarySmtpAddress CustomAttribute4 = $Attribute4Value ForceUpgrade = $true} Set-DistributionGroup @GroupParams $EmailTemp = @" <tr> <td class="colorm">$Group</td> <td>$Attribute4Value</td> </tr> "@ $EmailResult = $EmailResult + "`r`n" + $EmailTemp } } $EmailUp = @" <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%3E%0D%0A%0D%0Abody%20%7B%20font-family%3ASegoe%2C%20%22Segoe%20UI%22%2C%20%22DejaVu%20Sans%22%2C%20%22Trebuchet%20MS%22%2C%20Verdana%2C%20sans-serif%20!important%3B%20color%3A%23434242%3B%7D%0D%0ATABLE%20%7B%20font-family%3ASegoe%2C%20%22Segoe%20UI%22%2C%20%22DejaVu%20Sans%22%2C%20%22Trebuchet%20MS%22%2C%20Verdana%2C%20sans-serif%20!important%3B%20border-width%3A%201px%3Bborder-style%3A%20solid%3Bborder-color%3A%20black%3Bborder-collapse%3A%20collapse%3B%7D%0D%0ATR%20%7Bborder-width%3A%201px%3Bpadding%3A%2010px%3Bborder-style%3A%20solid%3Bborder-color%3A%20white%3B%20%7D%0D%0ATD%20%7Bfont-family%3ASegoe%2C%20%22Segoe%20UI%22%2C%20%22DejaVu%20Sans%22%2C%20%22Trebuchet%20MS%22%2C%20Verdana%2C%20sans-serif%20!important%3B%20border-width%3A%201px%3Bpadding%3A%2010px%3Bborder-style%3A%20solid%3Bborder-color%3A%20white%3B%20background-color%3A%23C3DDDB%3B%7D%0D%0A.colorm%20%7Bbackground-color%3A%2358A09E%3B%20color%3Awhite%3B%7D%0D%0A.colort%7Bbackground-color%3A%2358A09E%3B%20padding%3A20px%3B%20color%3Awhite%3B%20font-weight%3Abold%3B%7D%0D%0A.colorn%7Bbackground-color%3Atransparent%3B%7D%0D%0A%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<style>" title="<style>" /> <body> <h3>Script has been completed successfully</h3> <h4>CustomAttribute4 has been set for the below groups</h4> <table> <tr> <td class="colort">Group Name</td> <td class="colort">Custom Attribute4 Value</td> </tr> "@ $EmailDown = @" </table> </body> "@ $Email = $EmailUp + $EmailResult + $EmailDown if ($EmailResult -ne ""){ $EmailParams = @{ To = $To Subject = "Distribution Groups CustomAttribute4 Report $(Get-Date -format dd/MM/yyyy)" Body = $Email BodyAsHtml = $True Priority = "High" UseSsl = $True Port = "587" SmtpServer = "smtp.office365.com" Credential = $EmailCredentials From = $From} send-mailmessage @EmailParams } if ($error -ne $null){ foreach ($value in $error){ $ErrorEmailTemp = @" <tr> <td class="colorm">$value</td> </tr> "@ $ErrorEmailResult = $ErrorEmailResult + "`r`n" + $ErrorEmailTemp } $ErrorEmailUp = @" <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%3E%0D%0Abody%20%7Bfont-family%3ASegoe%2C%20%22Segoe%20UI%22%2C%20%22DejaVu%20Sans%22%2C%20%22Trebuchet%20MS%22%2C%20Verdana%2C%20sans-serif%20!important%3B%20color%3A%23434242%3B%7D%0D%0ATABLE%20%7Bfont-family%3ASegoe%2C%20%22Segoe%20UI%22%2C%20%22DejaVu%20Sans%22%2C%20%22Trebuchet%20MS%22%2C%20Verdana%2C%20sans-serif%20!important%3B%20border-width%3A%201px%3Bborder-style%3A%20solid%3Bborder-color%3A%20black%3Bborder-collapse%3A%20collapse%3B%7D%0D%0ATR%20%7Bborder-width%3A%201px%3Bpadding%3A%2010px%3Bborder-style%3A%20solid%3Bborder-color%3A%20white%3B%20%7D%0D%0ATD%20%7Bfont-family%3ASegoe%2C%20%22Segoe%20UI%22%2C%20%22DejaVu%20Sans%22%2C%20%22Trebuchet%20MS%22%2C%20Verdana%2C%20sans-serif%20!important%3B%20border-width%3A%201px%3Bpadding%3A%2010px%3Bborder-style%3A%20solid%3Bborder-color%3A%20white%3B%20background-color%3A%23C3DDDB%3B%7D%0D%0A.colorm%20%7Bbackground-color%3A%2358A09E%3B%20color%3Awhite%3B%7D%0D%0Ah3%20%7Bcolor%3A%23BD3337%20!important%3B%7D%0D%0A%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<style>" title="<style>" /> <body> <h3 style="color:#BD3337 !important;"> WARNING!!!</h3> <p>There were errors while setting up CustomAttribute4 on Groups</p> <p>Please check the errors and act accordingly</p> <table> "@ $ErrorEmailDown = @" </table> </body> "@ $ErrorEmail = $ErrorEmailUp + $ErrorEmailResult + $ErrorEmailDown $ErrorEmailParams = @{ To = $To Subject = "Distribution Groups CustomAttribute4 Report $(Get-Date -format dd/MM/yyyy) - WARNING" Body = $ErrorEmail BodyAsHtml = $True Priority = "High" UseSsl = $True Port = "587" SmtpServer = "smtp.office365.com" Credential = $EmailCredentials From = $From} send-mailmessage @ErrorEmailParams }

[adinserter name=”Matched-Content”]

Summary
PowerShell Set Groups Custom Attributes
Article Name
PowerShell Set Groups Custom Attributes
Description
PowerShell Set Groups Custom Attributes. Here you can find a script to set custom attributes on groups automatically with PowerShell.
Author
Stephanos
Publisher Name
Stephanos Constantinou Blog
Publisher Logo
Stephanos Constantinou Blog

Filed Under: PowerShell Scripts Tagged With: Active Directory, Arithmetic Operators, Comparison Operators, ConvertTo-SecureString, Get-ADOrganizationalUnit, Get-Content, Get-DistributionGroup, Import-PSSession, New-Object, New-PSSession, PowerShell ForEach, PowerShell If, PowerShell Operators, PowerShell Switch, Send-MailMessage, Set-DistributionGroup, Where-Object

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Footer

Recent Posts

  • ICS Cube Product Review 26/04/2019
  • PowerShell Module SysInfo v1.2.0 15/03/2019
  • PowerShell Module SysInfo v1.1.2 13/11/2018
  • PowerShell Module SysInfo 24/10/2018
  • Get-VoltageProbe 24/10/2018
  • Get-VideoController 24/10/2018
  • Get-USBController 24/10/2018
  • Get-TrackPoint 24/10/2018
  • Get-TrackBall 24/10/2018
  • Get-TouchScreen 24/10/2018
Planet PowerShell

Categories

  • Modules Cmdlets (57)
  • PowerShell Modules (5)
  • PowerShell Scripts (38)
  • PowerShell Tutorials (35)
  • Software Reviews (2)

Archives

  • April 2019 (1)
  • March 2019 (1)
  • November 2018 (1)
  • October 2018 (56)
  • September 2018 (13)
  • August 2018 (9)
  • July 2018 (6)
  • June 2018 (8)
  • May 2018 (7)
  • April 2018 (9)
  • March 2018 (4)
  • February 2018 (6)
  • January 2018 (12)
  • December 2017 (4)
Top 10 PowerShell 2018

Blogroll

  • Planet PowerShell
  • Reddit – PowerShell
  • PowerShell Magazine
  • PowerShell.org
  • PowerShell Team Blog
  • Hey, Scripting Guy! Blog
  • Mike F Robbins
  • PowerShell Explained with Kevin Marquette
  • Mike Kanakos – Network Admin
  • The Lonely Administrator
  • AskME4Tech
PowerShell Blogs Sysadmin Blogs Banners for Top 20 Programming Blogs

© 2023 · Stephanos Constantinou Blog

  • Home
  • Blogs
  • About
  • Contact