HOW TO: Create Lync Server Custom, Scalable Voice Dial Plans – Part 2 (Scripts)

In a previous Unified Communications blog, I outlined a design to facilitate end user dialing habits across multiple offices.  The design called for 4, 7, & 10 digit dialing levels.  In order to scale this solution, I helped my client automate the deployment of new office locations and maintain existing Lync dial plans.  The following scripts will help propagate changes throughout the Lync infrastructure.  This may not work immediately for your environment, but the structure is in place to help you scale your Lync infrastructure and provide a custom user experience at every office.


  1. Define the new Office 7 Digit extension range in _Base-NA-7Digit Dial Plan
  2. Execute the New-OfficeDialPlan.ps1
  3. Customize the new office dialplan’s Operator and 4 Digit extension range
  4. After hours, Execute the Update-OfficeDialPlans.ps1


Step 1

Using the Lync Control Panel, add the newest office to the default 7 digit dial plan to ensure that the new DID range is added to all office dial plans.  This will ensure that the inter-office dial habits are maintained when this new office is online.

Step 2

The New-OfficeDialPlan.ps1 is designed to create a new dial plan for the new branch office using the existing normalization rules within the _Base dial plans.  You will be prompted to answer a few basic questions about the site for description purposes. 


# Run the program from Lync Powershell by typing .\New-OfficeDialPlan.ps1.

Write-Host -ForegroundColor red (“Have you updated the _Base-NA-7Digit Dial Plan with the new office’s DID range?  If not, press Ctrl + C.”)

$SiteID=Read-Host “Enter the new Site ID”

$City=Read-Host “Enter the City”

$State=Read-Host “Enter the State (i.e. TX)”

$Operator=Get-CsVoiceNormalizationRule -Filter _Base-NA-Oper*

$4Digit=Get-CsVoiceNormalizationRule -Filter _Base-NA-4Digit*

$7Digit=Get-CsVoiceNormalizationRule -Filter _Base-NA-7Digit*

$PSTN=Get-CsVoiceNormalizationRule -Filter _Base-NA-PSTN*

Write-Host ‘Creating New Dial Plan’

New-CSDialPlan $SiteID -Description ($SiteID + ” – ” + $City + “, ” + $State) -City $City -State $State -DialinConferencingRegion ‘Global’

$NormRuleToDelete = Get-CSVoiceNormalizationRule $SiteID

Remove-CSVoiceNormalizationRule $NormRuleToDelete.Identity -ErrorAction:SilentlyContinue

Write-Host ‘Creating Normalization Rules…’

ForEach ($Rule in $Operator) {New-CsVoiceNormalizationRule -Parent $SiteID -Name $Rule.Name -Description $Rule.Description -Pattern $Rule.Pattern -Translation $Rule.Translation -IsInternalExtension $Rule.IsInternalExtension | Out-Null}

ForEach ($Rule in $4Digit) {New-CsVoiceNormalizationRule -Parent $SiteID -Name $Rule.Name -Description $Rule.Description -Pattern $Rule.Pattern -Translation $Rule.Translation -IsInternalExtension $Rule.IsInternalExtension | Out-Null}

ForEach ($Rule in $7Digit) {New-CsVoiceNormalizationRule -Parent $SiteID -Name $Rule.Name -Description $Rule.Description -Pattern $Rule.Pattern -Translation $Rule.Translation -IsInternalExtension $Rule.IsInternalExtension | Out-Null}

ForEach ($Rule in $PSTN) {New-CsVoiceNormalizationRule -Parent $SiteID -Name $Rule.Name -Description $Rule.Description -Pattern $Rule.Pattern -Translation $Rule.Translation -IsInternalExtension $Rule.IsInternalExtension | Out-Null}

Write-Host -Foregroundcolor green ‘COMPLETE’

Write-Host -Foregroundcolor green ‘Summary of new Dial Plan:’

Get-CsDialPlan $SiteID

Write-Host -Foregroundcolor yellow (‘Make sure to update the Operator & 4 Digit Rules for this new Dial Plan ‘ + $SiteID)

Step 3

After the new office dial plan has been created, you must customize the Operator and 4 Digit routing.  Likely when dialing 0 within the new office, the call will need to be routed to the reception user or response group.  Additionally, you must define the 4 digit normalization rule to enable intra-site dialing habits.  The 7 Digit, 10/11 Digit, and International normalization rule will have been imported during creation.

Step 4

Now that the new office is fully deployed, we should update all of the other sites’ 7 Digit normalization rules to include the newest office and extension range.  The Update-OfficeDialPlans.ps1 script will first remove all the 7 Digit & PSTN normalizations rules, then import the latest defaults from the corresponding _Base dial plans.  This process may take considerable time due to the nature of deleting/adding dozens of normalization rules to each dial plan, so I recommend running this one after hours.  Remember that dial plans are downloaded to every client on sign-in, so these changes will not be adopted immediately.

# Run the program from Lync Powershell by typing .\Update-OfficeDialPlans.ps1

$SiteDialPlans=Get-CSDialplan | Where-Object {$_.SimpleName -like ‘Site*’ }
$Base7Digit=Get-CsVoiceNormalizationRule -Filter _Base-NA-7Digit*
$BasePSTN=Get-CsVoiceNormalizationRule -Filter _Base-NA-PSTN*

foreach ($D in $SiteDialPlans)

Write-Host -ForegroundColor yellow ($D.Identity + “: Removing Old 7 Digit & PSTN Normalization Rules”)
$Old7Digit = Get-CsVoiceNormalizationRule -Filter ($D.Identity + ‘/7*’ )
foreach ($Rule in $Old7Digit)
    {    Remove-CSVoiceNormalizationRule -Identity $Rule.Identity   }  
$OldPSTN = Get-CsVoiceNormalizationRule -Filter ($D.Identity + ‘/NA-*’)
foreach ($Rule in $OldPSTN)
    {    Remove-CSVoiceNormalizationRule -Identity $Rule.Identity   }

Write-Host -ForegroundColor green ($D.Identity + “: Adding Base Plan 7 Digit & PSTN Normalization Rules”)   
ForEach ($Rule in $Base7Digit) {New-CsVoiceNormalizationRule -Parent $D.Identity -Name $Rule.Name -Description $Rule.Description -Pattern $Rule.Pattern -Translation $Rule.Translation -IsInternalExtension $Rule.IsInternalExtension | Out-Null}
ForEach ($Rule in $BasePSTN) {New-CsVoiceNormalizationRule -Parent $D.Identity -Name $Rule.Name -Description $Rule.Description -Pattern $Rule.Pattern -Translation $Rule.Translation -IsInternalExtension $Rule.IsInternalExtension | Out-Null}



This solution was very rewarding for me, as it allowed me to explore the business problem of enabling new office branches quickly, while providing a standard, but localized, user experience.  My client has been extremely happy with the scripts over the past year.  I hope that this has helped you plan for large rollouts of Lync Voice at your company.  Shoot me a note if you would like to discuss your project in detail.


The script relies on deleting and adding many object on each dial plan.  I am confident that there is a more efficient method of inserting a normalization rule into the middle of the list, but I have been able to locate it. 

If you have any tips, send it over.  I’d love to hear your feedback.


If you are in the Dallas area please join me at the next Unified Communications User Group (UCUG) meeting at the Microsoft campus.  Details are posted on MeetUp.

Exchange Federation Free/Busy drops the SOAP Header

When setting up a new Organization Relationship between Exchange 2013 CU3 and Exchange 2010 SP3 RU0, I found that the Test-OrganizationRelationship cmdlet was failing on the Autodiscover call. For a reminder, here is the format for the cmdlet:

    Test-OrganizationRelationship –UserIdentity –Identity “Name of the OrgRel Object”


The key error revealed itself with the Verbose switch enabled.

VERBOSE: [15:40:01.209 GMT] Test-OrganizationRelationship : The Client will call the Microsoft Exchange Autodiscover service using the following URL:
VERBOSE: [15:40:06.333 GMT] Test-OrganizationRelationship : The Microsoft Exchange Autodiscover service failed to be called at ‘’ because the following error occurred: SoapException.Code =
Exception: System.Web.Services.Protocols.SoapHeaderException: An error occurred when verifying security for the message.


After some research, I discovered a KB article published that looked similar ( Sure enough, I checked the IIS on the targeted Exchange system and found the 500 response to the Autodiscover request from my Exchange server.

The resolution states that the EWS & Autodiscover virtual directories must be configured to allow WSSecurity Authentication. However, my Exchange 2010 server was already defined as True for WSSecurity.

Since everything appeared set correctly, I continued my testing and troubleshooting. I eventually ran out of ideas, so I decided to set the WSSecurity manually and reset IIS (for good measure). The Cmdlets used to set the required authentication:

    Get-WebServicesVirtualDirectory | Set-WebServicesVirtualDirectory -WSSecurityAuthentication $True

    Get-AutodiscoverVirtualDirectory | Set-AutodiscoverVirtualDirectory -WSSecurityAuthentication $True

To my surprise, the free/busy exchange of information began working.


Now, for Exchange 2010, the output of the Test-OrganizationRelationship will be blank. No summary of successful completion is presented, but the Verbose option will state that the steps completed successfully.


From Exchange 2013, you receive more information during the test.



Don’t be afraid to set a parameter even though it appears to be configured already. Exchange does some behind the scenes setup to finalize the configuration.

HOW TO: Create Lync Server Custom, Scalable Voice Dial Plans– Part 1

I love the Lync Server 2013 location-based routing of phone calls, but location-based dialing habits is still not a feature of Lync.  I was able to solve the problem by making the dial plan configuration much smoother and more organized.

Like any phone system, large dial plans can be challenging with a growing number offices that each require special dialing habits.  My recent customer has the requirement to provide 4 digit intra-office, 7 digit inter-office, & 10+ digit external dialing habits as we migrate over 40 offices to Lync Enterprise Voice this year.  I will be writing a multi-part blog to explain how we used a tiered dial plan and powershell scripts to automate the deployment process.  As a dial planning refresher, you may want to check out Ken Lasko’s Lync Enterprise Voice Best Practices and Internal Extension Dialing in Lync.


Lync’s voice configuration requires the administrator to define the list of normalization rules on every office’s dial plan, since there is no hierarchy.  For example, every office needs localized normalization rules for dialing the operator at “0” and 4 digit dialing at each office will be different.  However, all office have the same dialing habits for company 7 digit office extensions, 10 digit local/long distance, & international dialing.  When you add these up, each dial plan will contain over 70 normalization rules.  This can become cumbersome to manage as you deploy each office


To aid in this deployment process, we built and maintain multiple “baseline” dial plans which are copied into each new office’s dial plan.  This allows for an easy deployment process.  Updating previous office dial plans can be scripted to inject the new 7 digit extension rules (later blog). 


Here are representations of each of the base dial plans and example normalization rules.  When a new office dial plan is built, the administrator can simply copy/paste the rules from these base plans into the new one and modify a few rules.




Steps to deploy a new office’s phone number range

  1. Add a new 7 Digit normalization rule to the Base-NA-7Digit dial plan for the new DID block
  2. Create a new Office Dial Plan
  3. Copy the Normalization Rules from Base-NA-Operator
  4. Copy the Normalization Rules from Base-NA-4Digit
  5. Copy the Normalization Rules from Base-NA-7Digit
  6. Copy the Normalization Rules from Base-NA-PSTN
  7. Modify the Operator and 4 Digit rules within the new Office Dial Plan
  8. Update the other office dial plans with the new office’s 7 Digit normalization rule

The resulting office dial plan will contain the normalizations rules for the entire company as well as office specific rules.



This is simply one method to manage growing Lync Voice deployments.  I would love to hear how you deal with the administration of dozens of custom dial plans.

This solution has been working extremely well for my client since last year, and they love using the update script to maintain the consistency.  Stay tuned for the automated process to deploy changes.