Recently I was asked to rename some distribution groups in Exchange. Not so tough of a problem, but painstaking to do one at a time and there were a few of these to do. So I did what any good admin should do, I wrote a script to take care of this.
The issues
To properly rename a distribution group, you need to not only change the name of the group, but also the Alias, DisplayName and entries in the EmailAddresses field. The first two are easy but if you’re like me, you need to add a handful of emailaddresses to these fields. In our environment, we tend to add records when a name is changed rather than swap the old for the new. This way, if someone uses the old address, it still goes to where they want it too. Probably a better answer would be to create a mailbox with the old address and setup an auto reply that says “Hey, use the new address for this list.” That’ll be for another day.
Anyways, here is the script…
I should note, that I’m keeping this function (along with some other Exchange functions on github. you can get the most recent version of this script here: https://github.com/glaisne/PowerShellExchangeFunctions/archive/master.zip
function Rename-DistributionGroup
{
<#
.SYNOPSIS
Renames distribution groups
.DESCRIPTION
Changes the old name of the distribution group
to the new name. Specifically, the fields that
are changed are 'Name', 'Alias', 'DisplayName'.
Also, for each smtp domain the added new alias
address will be added. For example, if the old
distribution list had an EmailAddresses field
containing smtp:OldName@contoso.com and
smtp:OldName@microsoft.com, this cmdlet would
add 'smtp:NewName@contoso.com and
'smtp:NewName@Microsoft.com.
.EXAMPLE
Rename-DistributionGroup -OldName "OldDistributionGroup" -NewName "NewDistribtuionGroup"
This would rename the distribution group named "OldDistributionGroup" to "NewDistributionGroup"
.PARAMETER OldName
The old (or current) name of the distribution group
.PARAMETER NewName
The new name of the distribution group. This is the name
this script will change the distribution group to.
.Parameter Confirm
Use this to force or remove confirmation.
#>
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(Mandatory=$true)]
[string] $OldName,
[Parameter(Mandatory=$true)]
[string] $NewName,
[Boolean] $Confirm = $True
)
write-verbose "Fields that contain ""$OldName"""
try
{
Get-DistributionGroup $OldName -ErrorAction "Stop" |fl * | out-string -stream | select-string $OldName |
Where {$_ -ne "" } | ForEach { write-verbose $_ }
}
catch [System.Management.Automation.RuntimeException]
{
Write-Verbose "There was an error accessing Distribution Group $OldName"
write-host ("Exception: " + $Error[0].Exception.GetType().FullName)
write-host $Error[0].Exception.Message
return
}
catch
{
Write-Verbose "There was an error accessing Distribution Group $OldName"
throw $_
}
Write-Verbose "Getting the Distribution Group $OldName"
$group = Get-DistributionGroup $OldName
if ( $PSCmdlet.ShouldProcess($OldName, "Setting Name, Alias and DisplayName to $NewName") )
{
if ( -Not $Confirm -or $($PSCmdlet.ShouldContinue("Are you sure you want to make this change?","Setting Name, Alias and DisplayName to $NewName on target $OldName" )) )
{
Set-DistributionGroup $OldName -alias $NewName -DisplayName $NewName -ForceUpgrade
}
}
Write-Verbose "EmailAddresses listed on the original group:"
$group.EmailAddresses |ft -auto | out-string -stream | Where {$_ -ne "" } | ForEach { write-verbose $_ }
foreach ($EmailAddress in $($group.EmailAddresses))
{
if ($EmailAddress -notmatch "^smtp:.*@.*$")
{
Write-Verbose "Skipping processing of EmailAddress $EmailAddress"
Continue
}
$domain = $EmailAddress.split('@')[1]
Write-Verbose "Current Emailaddress ($EmailAddress) domain = $Domain"
Write-Verbose "Adding new smtp address (smtp:$NewName@$Domain) to the EmailAddresses field"
$group.EmailAddresses += "smtp:$NewName@$Domain"
}
Get-DistributionGroup $OldName -ErrorAction "Stop" |fl * | out-string -stream | select-string $OldName |
Where {$_ -ne "" } | ForEach { write-verbose $_ }
if ( $PSCmdlet.ShouldProcess($OldName, "Adding new alias to the old address' smtp addresses.") )
{
if ( -Not $Confirm -or $($PSCmdlet.ShouldContinue("Are you sure you want to make this change?","Adding $NewName addresses on target $OldName" )) )
{
if ($($group.EmailAddressPolicyEnabled))
{
Write-Verbose "Turning off the Email Address Policy for this distribution group."
Set-DistributionGroup $NewName -EmailAddressPolicyEnabled:$false
}
Write-Verbose "Setting the distribution groups new EmailAddresses setting."
Set-DistributionGroup $NewName -EmailAddresses $($group.EmailAddresses)
if ($($group.EmailAddressPolicyEnabled))
{
Write-Verbose "Turning Back on the Email Address Policy for this distribution group."
Set-DistributionGroup $NewName -EmailAddressPolicyEnabled:$True
}
}
}
Write-Verbose "New EmailAddresses listed on the original group:"
(get-distributiongroup $NewName).EmailAddresses | out-string -stream | Where {$_ -ne "" } | ForEach { write-verbose $_ }
}
Some things worth noting
First of all, I’m working trying to make every bit of code I write more of a tool for others rather than something I use in my environment only. As a result, I’m utilizing ShouldContinue and ShouldProcess more. In this script I use them twice. First when I change the Name, Alias and DisplayName fields
if ( $PSCmdlet.ShouldProcess($OldName, "Setting Name, Alias and DisplayName to $NewName") )
{
if ( -Not $Confirm -or $($PSCmdlet.ShouldContinue("Are you sure you want to make this change?","Setting Name, Alias and DisplayName to $NewName on target $OldName" )) )
{
Set-DistributionGroup $OldName -alias $NewName -DisplayName $NewName -ForceUpgrade
}
}
The second time I use ShouldProcess and ShouldContinue is when I set the EmailAddresses field.
if ( $PSCmdlet.ShouldProcess($OldName, "Adding new alias to the old address' smtp addresses.") )
{
if ( -Not $Confirm -or $($PSCmdlet.ShouldContinue("Are you sure you want to make this change?","Adding $NewName addresses on target $OldName" )) )
{
if ($($group.EmailAddressPolicyEnabled))
{
Write-Verbose "Turning off the Email Address Policy for this distribution group."
Set-DistributionGroup $NewName -EmailAddressPolicyEnabled:$false
}
Write-Verbose "Setting the distribution groups new EmailAddresses setting."
Set-DistributionGroup $NewName -EmailAddresses $($group.EmailAddresses)
if ($($group.EmailAddressPolicyEnabled))
{
Write-Verbose "Turning Back on the Email Address Policy for this distribution group."
Set-DistributionGroup $NewName -EmailAddressPolicyEnabled:$True
}
}
}
Also, you’ll notice there isn’t much in the way of actual comments. This is a bit of a departure for me as I love my comments. But, rather than use comments, I’ve decided to use Write-Verbose so that everyone can share in “What should be happening.”
Let me know if you have any questions, or if you think there is a better way.
Thanks,
Gene
Hi Gene,
stupid question, as I am not very familiar with PS:
How do you run that script / call the function from PS?
I tried:
. .\rename_distribution_groups.ps1
Rename-DistributionGroup -OldName “MyOldGroupName” -NewName “MyNewGroupName”
I just receive an error “… a parameter with the name “confirm” was defined multiple times…”
If I add that param, same result:
Rename-DistributionGroup -OldName “MyOldGroupName” -NewName “MyNewGroupName” -confirm
Could you pls advise?
Thx in advance
BR
Dan
Hi Dan,
Looks like you are doing it correctly. try -confirm:$false (if you want it to just run) or -Confirm:$True (if you want it to check with you first).
Gene,
I’ve tried adding the -confirm parameter the same way you describe, but I still get the same exception: “…A parameter with the name “confirm” was defined muliple times…”
Me too, I get the same error!
Found solution 🙂
Replace $Confirm with $MyConfirm everywhere and run 😉
PS: Probably because of the reserved word in PS
Just to confirm (pun intended?), I am getting the same error. No matter what I do (even trying get-help rename-distributiongroup), I get the “A parameter with the name ‘Confirm’ was defined multiple times for the command’.
This was probably written in the Powershell V2 era. Confirm is now provided by default and could be removed?
param(
[Parameter(Mandatory=$true)]
[string] $OldName,
[Parameter(Mandatory=$true)]
[string] $NewName
)