Finding “hidden” Lync PowerShell CmdLets

SnifferI don’t think it is any secret that almost any* administration that happens in Lync happens via PowerShell. The obvious use of this is by opening the Lync Server Management Shell and typing in some PowerShell commands. The slightly less obvious version of this is using the graphical Lync Server Control Panel. Something I’ve always wanted the Control Panel to do is to show me the PowerShell commands it was about to run in the same vein as in the Exchange Management Console.

Today I stumbled across a way to do this. It isn’t nearly as easy to see as in Exchange but with a little bit of work you can see the “hidden” cmdlets that the Control Panel is running. In order to see these commands, you will need to use the Lync Server 2013 Logging Tool (aka OCSLogger). If you have already downloaded the Lync 2013 Debugging Tools, you will find the Lync Server 2013 Logging Tool in this path: C:Program FilesMicrosoft Lync Server 2013Debugging ToolsOCSLogger.exe. Start the Tool and find the AdminUI option in the left hand column.


Check the AdminUI Component and be sure that every other component is unchecked. Depending on your environment, having any other components checked could lead to a very large log file and finding the area we are looking for would be pretty difficult. You can keep the rest of the settings at their default values. Here is what my level and Flags sections look like (which I think are the default values):


At this point, if you haven’t yet, open the Lync Control Panel and add something but don’t hit the “commit” option just yet. In this example, I am going to add a new Dial In Access Number. After adding the values (and before hitting commit), start the Lync Server 2013 Logging Tool.


At this point you can hit the Commit button in Lync Server Control Panel. After clicking it, flip back to the Logging Tool and click Stop Logging.


Now that you have captured the command that the Control Panel ran, we need to view it. To do this click the Analyze Log Files button.


This brings up a new window. It provides a few options but none of them are relevant. Simply click the Analyze Button and after a brief pause the Snooper log viewer will open.


Finally we can drill down and see the commands that were run. If you are experienced with Snooper your first inclination is to click the “Messages” tab. However, this capture is not in a format that Messages can handle so we need to stay in the default Trace tab. In the Trace window you should see a few lines of captured entries. There shouldn’t be too many here so feel free to click on each one.


Click the image for a larger view.

Look for a row that has “TF_Component” in the Flag column. There should be two of them. The first one is the PowerShell command that was actually run. The second one is almost the exact same thing except that there is a result code added to the end. Hopefully it simply says “Result:Success”. In the screen shot above, you can see that the actual PowerShell command that was run is the following:

New-CSDialInConferencingAccessNumber -PrimaryUri “” -DisplayNumber “123-4567” -DisplayName “Conference Number” -LineUri “tel:+1234567” -Pool “” -PrimaryLanguage “en-US” -SecondaryLanguages “System.Collections.Generic.List`1[System.Object]” -Regions “System.Collections.Generic.List`1[System.Object]”

That is quite some command! Note that the commands used in the Control Panel won’t necessarily translate to a Lync Management Shell Session. In the command above, the “System.Collections.Generic.List`1[System.Object]” garbage is not something you could use in the Lync Management Shell as that is a reference to a field within the Lync Server Control Panel GUI. So you would still have to translate that to a value that Lync Management Shell could use. In my case, the first would be $Null (or I could simply omit it) and the second would be “United States”.

Now that you know which command was actually run, you could use it as a basis of a PowerShell script. Alternately, if you’ve been banging your head to figure out the right syntax for a PowerShell script and just can’t seem to get a command right, you could “snoop” the command this way to get the proper syntax.

* As best I know, Topology Builder doesn’t use PowerShell.

exchucutil.ps1 and the Verify Switch

In which Lync forces me to dig into the Exchange world again…..

I got an excellent question as a followup to my post breaking down the exchucutil.ps1 script in excruciating detail.

The questions by user “soder” basically asked if the verify switch was still valid in the Exchange 2010/2013 versions of the script. In short – no. In long – mostly no.

Looking at the script, the following is seen on line 10:

param($Forest = $null,[Switch]$Verify)

This means that the script is looking for a command line parameter named -Verify. Running the script with the -Verify parameter runs the script in “verify mode”. (The [Switch] construct basically means that if -verify is present, set the $verify variable to $True, else set it to $false).

However, something strange happens a few lines down – line 21 to be exact:

$Verify = $false;

This sets $Verify to $false NO MATTER WHAT you set on the command line. So effectively, $Verify is disabled.

I don’t have any idea why this is done but there must be a good reason. I don’t want to speculate.

However, if you want to run a verify pass anyway, comment out line 21.  Then run exchucutil.ps1 -verify. I ran it in my lab and I got a list dumping out the permissions and not attempting to actually make changes.



Note that with the -Verify parameter that the script ends before making any changes.

Microsoft effectively removed the verify permissions. (Well, it could be an oversight. It probably is….)

In summation, as of at least Exchange 2013 (and maybe 2010) verify does not officially work anymore.

Lync 2013 PreCall Diagnostics Released

Microsoft recently released the Lync 2013 PreCall Diagnostics tool. This can be found on the Windows Store. It is a Modern App so it requires at least Windows 8.0. I’ve tested it on Windows 8.1 and it work fine. It doesn’t appear to support Windows RT.

The point of this app is to measure the Network MOS, Packet Loss Rate, and Interarrival Jitter of your current network connection. There really isn’t much detailed help on this app. If you do click on the Help icon from the charms menu, you are redirected to the OCS 2007 R2 help page for that legacy PreCall Diagnostic Tool. (You would think they would want this link…).

It’s a pretty simple app to use. Launch the app from the start menu and provide your Lync credentials. The app runs a test for 2 minutes, displaying real-time graphs of the 3 metrics. You can also run it in “Always On” mode which will gather up to 24 hours of metrics. You can also keep the tool running while on a Lync call to get stats from an actual live call. PreCall 1

When you initially log in it displays the various log in steps. Should your log in fail, you can use this high-level diagnostics to see where the error is.

PreCall 4

For example, when I joined my Surface to a specific wireless network in the office, the tool reported that it was unable to connect to a specific Lync server and thus the login failed.

PreCall 3

The best description of how the tool works comes from Microsoft’s website about the tool:

PCD is most useful in situations where the last hop of a network is likely to be the weakest (for example, with laptops on a public WiFi network or home users). PCD creates a small packet stream that traverses this final leg of the network. The tool then analyzes the packet stream to estimate how the jitter and loss along this leg might impact call quality, and then provides a report. You can run PCD continuously on the client, even while calls are being placed. The packet stream does not have a significant effect on bandwidth.

Here is a screenshot of the settings flyout. PreCall 2 You’ll also notice the “blocks” on the left. These will bring up the graphs from previous times you have run the tool so you can compare and contrast historical performance. That’s a nice touch. Again, you can get the tool from the Windows Store.

Grey Text in IM’s

Update 11 April 2014 – There is both a KB – – and a fix for this issue – It took about 5.5 months but at least it is officially fixed now.

Update – 26 February 2014 – It appears that Office 2013 SP1 fixes the font issue.

Update – 24 February 2014 – The Lync Product Group has accepted this issue as a fix in an upcoming Cumulative Update. So hopefully within a few months this issue will be put to rest.

Update – 13 November 2013: Microsoft has filed an internal bug for this. Expect this fixed in a Cumulative Update in early 2014.

Update – 3 December 2013: Apparently Microsoft don’t seem interested in fixing this. If possible, raise this as an issue with your Microsoft TAM. The more complaints MS hears, the more likely they will be to fix something they broke.

I was IM’ing with a Lync contact at the end of last week. The curiosity was that the first word of any given IM was black and the rest of the text was grey (or gray…whatever). I paid it no mind until it happened to me today. Two people I IM’ed asked me what was up with my font? Here is a screen shot of what I am talking about as well as some IM’s trying to figure out what was or wasn’t working:

Grey IM

You can’t tell from that picture but my font color was blue and my horrible font selection was something called “Bradley Hand ITC“. The change in font size carried through as did bold, italic, and underline.

I moved myself from a Lync 2013 pool to a Lync 2010 pool and the only change is that everything was all grey instead of the first letter being black.

At some point, I decided I should reset my font cache. This is done by going to c:windowssystem32 and deleting the file FNTCACHE.DAT. Once that has been deleted, go for a reboot. I didn’t try it without a reboot but PC Tech Support 101 says to always reboot.

After rebooting, everything in my Lync 2013 client was back to normal. People saw my blue font color and the correct font (Calibri, not that horrible Bradley Hand ITC).

This appears to be some kind of bug with the Lync 2013 CU patch and how it gets installed, i.e., it may not be installing everything correctly. Uninstalling the update returns the font situation back to normal. I will update this if I learn what the real fix is. Other than, of course, the Office team keeping their hands off the Lync client because the Lync 2013 client is a mess.

Lync 2013 Spell Check

Earlier today, the Microsoft Lync Twitter account released a tweet with the following image:


So this is great! The Update is available now too. So…uh…where is the update? Apparently it is part of an Office 2013 update. Remember, the Lync client is now being ruined handled by the Office team. So all you have to do is update your Office 2013 to the latest version.

Except, you can’t do this because of this:

For the second time in two months, Microsoft has temporarily pulled a software update after users reported that it inadvertently disabled some Windows features.

Microsoft Wednesday removed its Office Update 2013 (KB2817630), which was released Tuesday as part of the company’s regularly monthly release of patches.

So the only chance of getting Lync Spell Check immediately is to hope that you or your company has downloaded the buggy patch via WSUS and hasn’t removed it yet. Then you might be able to get it.

This is exactly the case with one of my contacts who was able to update and get the patch. His Lync client after the update now shows the following:

Lync Ver

He ran a test and just like in the @msftlync graphic, he got the same results:

Lync Spell Check

So keep hitting updates. Eventually the Office Team will release the patch again.

Update: Here is a link to download the update.

Except since Microsoft pulled the update, the links don’t actually work. At least it’s something you can now monitor to see when it goes live again.

Update 2: After installing this update, the tray icon returns to it’s initial Lync status of showing your state instead of the unchanging Lync icon that was introduced and immediately apologized for by the Office team during the last round of updates.

Update 3: The patch is available here:

Tom Arbuthnot has done an excellent write up:

The ExchUcUtil Script (and Why You May Never Need to Run It Again!)


In 100% of all documentation, it is clearly stated that in order to connect Microsoft Lync with Exchange Unified Messaging (UM) you need to run the ExchUCUtil.ps1 script. This article will detail what this script does and how you can configure your environment so that you will never have to run this script again. Yes it’s possible and it’s pretty straightforward!

There is a brief TechNet article about the ExchUcUtil script that can be found here.

According to this (more in-depth) TechNet article, the ExchUcUtil script only does three things:

  1. Grants Lync Server permission to read Exchange UM Active Directory components, specifically, the SIP URI dial plan.
  2. Creates a UM IP gateway for each Lync Server pool or for each server running Lync Server Standard Edition that hosts users who will be enabled for Enterprise Voice.
  3. Create an Exchange UM hunt group for each UM IP gateway. The hunt group pilot identifier will be the name of the dial plan associated with the corresponding UM IP gateway. The hunt group must specify the UM SIP dial plan used with the UM IP gateway.

As a slight aside, if you look at the two linked TechNet articles you’ll note that the first article says the ExchUcUtil script only does two things while the second article lists three. Even when you find the Microsoft documentation on ExchUcUtil it is inconsistent.

Script Organization

The first step in figuring out how this PowerShell script is put together is to break it down into manageable chunks.

The script has four basic sections. At the top of the script are a bunch of constants. These aren’t anything we should worry about too much other than keeping note of them when breaking down the script.


The second section of the script is a collection of various functions. This is where all of the work happens and these functions will get broken down throughout this article.

Toward the bottom of the script we find the third section. It is a one line command that simply says:


Without this command nothing happens. All it does is call the RunScript function which will be broken down shortly.

The final section of the script is the signed certificate. This is put in so that you can be confident that the script you are running actually came from Microsoft and that nothing within the script has changed.


Breaking Down the Script

As mentioned above, nothing happens until the RunScript command fires. If you pay close attention you’ll notice that this command is the only command in the entire script that is not a function, a comment, or a variable (constant) declaration. As such, this is the command that sends the script on its way.

The first concrete thing the script does is to enumerate the RTC Pools. It does this by launching a separate PowerShell script called get-ucpool.ps1.

At a high level, get-ucpool.ps1 does the following:

  1. Find a Global Catalog Server and connect to it.
  2. Find the RTCUniversalServerAdmins and RTCComponentUniversalServices groups.
  3. Enumerate all UC pools
  4. Verify that all pools are at least version “0x30000” (or 12288 decimal)
  5. Return the list of pools back to ExchUCUtil.

The next step in the script is to get existing permissions. It does this via the GetPermissions function. This function verifies that the RTCUniversalServerAdmins group and the RTCComponentUniversalServices group already have access to Exchange. The first thing it does is to grab a copy of the Exchange configuration.


Next it calls another function (GetObjectPermissions) and runs the get-adpermissions cmdlet against the groupname sent to it from the GetPermissions Function.


Once those permissions are gathered we are back to the RunScript function. The next step is to get a list of all of the UM IP Gateways. It does this by calling the GetUMIPGateways function.

GetUMIPGateways is a simple function that lists all defined UM IP Gateways by running the Get-UMIPGateway cmdlet.



Once this function completes we are returned to the RunScript function. The next step is to gather all defined SIP dial plans. This is a rare instance where a separate function is not called. Instead the Get-UmDialPlan cmdlet is called directly and the results are stored in the $dialplans variable.



Once all of this data is collected the script now turns to setting permissions and creating objects. The first step is to verify that RTCUniversalServerAdmins and RTCComponentUniversalServices groups have proper permissions on Exchange. If it is not correct, the script runs the ConfigurePermissions function.

This function is fairly straightforward. It provides “ListChildren” rights with no inheritance on the Exchange Organization container.



It then provides “ListChildren” and “ReadProperty” rights (with full inheritance) to the UM Dial Plans, AutoAttendant, and Server containers.



It does this by calling the SetObjectPermissions function. This is a small function that basically just runs the Add-Permission cmdlet.



Once the permissions have been applied to AD and Exchange the script then creates the UM IP Gateways by running the ConfigureGateways function. This function takes all of the pools, gateways, and dial plans and creates a new UM IP Gateway for each pool.



Once the UM IP Gateways are created it removes all of your Hunt Groups….


…And creates new ones… ucutil13

Once it has done this work, control returns to the RunScript function which then outputs the results.



While it may feel a little unsettling that the script is removing hunt groups and creating new ones, this script does seem to work pretty flawlessly. I have run it numerous times in several environments and it works perfectly every time. Every Lync admin and Microsoft support representative has it ingrained in his or her head that this script MUST BE RUN in order to hook up Lync and Exchange Unified Messaging.

But what if you have a complicated network that spans continents, that has hundreds of Lync Pools, Lync servers, and Exchange UM servers in various Exchange Organizations? What if you have a network that has firewalls restricting connectivity between offices or countries? What happens then if you run this script?

No script can be designed for every single network that exists and in the case of this script it has to make the assumption that all pools can talk to all gateways. But this is not always the case. So what to do?

Configure your network to never have to run ExchUCUtil ever again!

Microsoft support and Lync Administrators don’t like this option because they have been trained to run ExchUCUtil and their experience has proven that this script works and, when necessary, fixes all kinds of issues. However, if you’ve read this far, you should have realized that the script doesn’t do any voodoo magic. It sets permissions and it creates UM IP Gateways and Hunt Groups. There is no reason you can’t do this yourself. So, let’s go through the steps necessary to do this yourself.

First, let’s check out the permissions created by the script. Remember that it adds Read permissions to certain Exchange objects for the RTCuniversalAdmins group and the RTCComponentUniversalAdmins group.

Here is the output of the first time the ExchUcUtil script was run on the domain. It is edited to only show the security-related output.

[PS] C:Program FilesMicrosoftExchange ServerV15Scripts>.ExchUCUtil.ps1

Using Global Catalog: GC://DC=flinchbot,DC=com

Configuring permissions for flinchbot.comRTCUniversalServerAdmins …

First Organization: The appropriate permissions haven’t been granted for the Office Communications Servers and Administrators to be able to read the UM dial plan and auto attendants container objects in Active Directory. The correct permissions are being added to the container objects.

UM DialPlan Container: The appropriate permissions haven’t been granted for the Office Communications Servers and Administrators to be able to read the UM dial plan and auto attendants container objects in Active Directory. The correct permissions are being added to the container objects.

UM AutoAttendant Container: The appropriate permissions haven’t been granted for the Office Communications Servers and Administrators to be able to read the UM dial plan and auto attendants container objects in Active Directory. The correct permissions are being added to the container objects.

Administrative Groups: The appropriate permissions haven’t been granted for the Office Communications Servers and Administrators to be able to read the UM dial plan and auto attendants container objects in Active Directory. The correct permissions are being added to the container objects.

Configuring permissions for flinchbot.comRTCComponentUniversalServices …

First Organization: The appropriate permissions haven’t been granted for the Office Communications Servers and Administrators to be able to read the UM dial plan and auto attendants container objects in Active Directory. The correct permissions are being added to the container objects.

UM DialPlan Container: The appropriate permissions haven’t been granted for the Office Communications Servers and Administrators to be able to read the UM dial plan and auto attendants container objects in Active Directory. The correct permissions are being added to the container objects.

UM AutoAttendant Container: The appropriate permissions haven’t been granted for the Office Communications Servers and Administrators to be able to read the UM dial plan and auto attendants container objects in Active Directory. The correct permissions are being added to the container objects.

Administrative Groups: The appropriate permissions haven’t been granted for the Office Communications Servers and Administrators to be able to read the UM dial plan and auto attendants container objects in Active Directory. The correct permissions are being added to the container objects.

Permissions for group flinchbot.comRTCUniversalServerAdmins

ObjectName AccessRights Configured

———- ———— ———-

First Organization ListChildren True

UM DialPlan Container ListChildren, ReadProperty True

UM AutoAttendant Container ListChildren, ReadProperty True

Administrative Groups ListChildren, ReadProperty True

Permissions for group flinchbot.comRTCComponentUniversalServices

ObjectName AccessRights Configured

———- ———— ———-

First Organization ListChildren True

UM DialPlan Container ListChildren, ReadProperty True

UM AutoAttendant Container ListChildren, ReadProperty True

Administrative Groups ListChildren, ReadProperty True

The ADSI Edit utility can be used to view the specific settings that were created by this script. Begin by starting the ADSI Edit utility and connecting to the Configuration Naming Context.



Next drill down to the following path:

CN=First Organization,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=flinchbot,DC=com

Note that you may have a different Exchange Organization name. In this example “First Organization” is the name of the Exchange 2013 Organization in the domain.

Right click on your Exchange Organization name and select Properties. From the window that pops up, click on the Security tab. If you scroll down you should see the two Lync groups have been added:



Close this window and return to the main ADSI Edit window. Scroll down until you get to the CN=UM* containers. Earlier in the article it was shown that security is added to the following UM objects: UM Dial Plans and AutoAttendant.

We see two of these objects here.

Right click on CN=UM AutoAttendant Container and select Properties. Next, select the Security Tab and scroll down the list.

You should see two groups listed: RTCComponentUniveralServices and RTCUniversalServerAdmins



You should see the same for the CN=UM DialPlan container.


In either container, you can see specifically which permissions have been assigned to those groups. Earlier in this article it was detailed that the following permissions were set by the script: “ListChildren” and “ReadProperty”. We can see this reflected here.


If you go back over the script, you’ll see that the script verifies if these rights are granted. If they are, it doesn’t change anything. As such, if you have run the script once, haven’t added a new Exchange Organization with UM Servers, and don’t touch these permissions, this part of the script is redundant. If you create a new Exchange Organization, you can manually add the permissions listed in this article or run the ExchUCUtil script to have it done for you. In general, this is the innocuous part of the script.

The real problems in large and/or complex environments is when the script starts removing Hunt Groups and adding UM IP Gateways. If you are in a rigidly defined environment where users are assigned to specific UM Servers and they cannot access other UM Servers (e.g. due to firewalls) then you may not want to run the ExchUcUtil script. ExchUCUtil is oblivious to your network layer and will start adding UM objects that it thinks all users should be able to access. Yet when the Lync client is told to access a gateway it cannot get to, Lync will potentially start failing to forward calls to Exchange UM. To exacerbate this issue, either the Lync client or Exchange UM does not have very robust failover capabilities – at least where the Lync 2010 client is concerned. (On the production environment that is the true source for this article, we all want to stay employed and will not run ExchUcUtil just to see if the 2013 family of Microsoft software is more robust. Sure we could run it, but then we need to reset Exchange UM in about 20 different countries and start submitting our resumee’s to find new employment).

Impact on Exchange

Here is what happens in Exchange when the ExchUcUtil script is run. In the test environment, this article was followed to assure that the minimum requirements for the script are met.

The first step is to create a UM Dial Plan. This was done using PowerShell. In order to make these steps repeatable, PowerShell will be used for all of these steps.

To create a UM dialplan you use the New-UMDialPlan cmdlet. Here is the command used in the lab and below that is the output of running this command.

New-UMDialplan -name “UMDialPlan” -UriType “SipName” -VoipSecurity Secured -NumberOfDigitsInExtension 4 -CountryOrRegionCode 1


Notice that the UMIPGateway field is empty.

Also note that this command creates a corresponding UM Mailbox Policy:


At this point, the ExchUCUtil script can be run. Below is the relevant output from the script relating to the Exchange UM piece:


Running the Get-UMDialPlan command now shows that there are entries in the UM IP Gateway field.



Formatting this for better output of the UM IP Gateways shows the following:



The two UM IP Gateways listed refer to the two Lync pools in this lab. One is a Standard Edition Pool (lycn2013se) and one is an Enterprise Edition pool (lyncpool).

In most cases, this configuration is completely fine and the ExchUcUtil script did its job just fine. However, as mentioned above, there are large and/or complex networks where adding all available pools to a new UM Dial Plan is not at all desirable. So how does one work around this? How can one end up having the same basic result without running the script?

The Exchange lab can be reset by removing the UM IP Gateways created by the ExchUCUtil script. By running the Remove-UMIPGateway command you can remove the gateways automatically created and assigned to the UM Dial Plan.



Running the Get-UMDialPlan verifies that there is still only one dial plan and that there are no assigned UM IP Gateways.



So instead of having the ExchUcUtil creating these automatically, this can be done manually with the following set of commands.

First, assign the UM dial plan to a specific server. That is done via the following:

Set-UMServer -Identity -DialPlans @{add=”UMDialPlan”}

According to TechNet, the –DialPlans parameter does the following:

The DialPlans parameter specifies all the dial plans for which this server will handle UM calls. If no dial plans are defined, the Unified Messaging server won’t handle UM calls.

The next step is to create a new UM IP Gateway. This is done via the following:

New-UMIPGateway -Name Lyncpool_UMIPGateway -Address

This cmdlet is very straightforward. The first parameter is the name of the UM IP Gateway object within Exchange. ExchUCUtil automatically chose the names “lyncpool” and “lync2013se”. In this example, the name “lyncpool_UMIPGateway” was chosen. It’s a bit longer but is a more descriptive name (another advantage of not using ExchUcUtil!).

Next you need to create a UM Hunt Group. A Hunt Group is a simple object that connects a UM IP Gateway with a UM Dial Plan.

New-UMHuntGroup -Name Lyncpool_HuntGroup -UMIPGateway Lyncpool_UMIPGateway -UMDialPlan “UMDialPlan” -PilotIdentifier “UMDialPlan”

This is also a straightforward command. The first parameter (-Name) is the name of the hunt group. The next parameter is the name of the UM IP Gateway we want to link with the UM Dial Plan.

The PilotIdentifier parameter can be confusing when manually configuring a UM dial plan. If you read the TechNet article on New-UmHuntGroup, it has this to say about the PilotIdentifier parameter:

The PilotIdentifier parameter specifies the number string used to uniquely identify the pilot access number for the specified IP gateway. This number must match the subscriber access number configured in the UM dial plan.

So what does this mean for Lync, especially if we do not want (or need) a Subscriber Access number? If you keep searching, you will find this TechNet article.

Create an Exchange UM hunt group for each UM IP gateway. The hunt group pilot identifier will be the name of the dial plan associated with the corresponding UM IP gateway. The hunt group must specify the UM SIP dial plan used with the UM IP gateway.

So for the PilotIdentifier, use the name of your dial plan. In the examples in this article, that would be “UMDialPlan”.

And that’s it. This may seem like more work than just launching ExchUCUtil but it really isn’t. For one, it goes a lot faster (in large environments) since you aren’t waiting for the ExchUCUtil script to enumerate all of your pools and then go about removing hunt groups, creating UM IP Gateways, and adding back the UM Hunt Groups.

If you are in an environment where the Exchange administrators are separate from the Lync administrators, the following is a very concise and understandable set of cmdlets for the Exchange Admins to run:

New-UMDialPlan -name “UMDialPlan” -UriType “SipName” -VoipSecurity Secured -NumberOfDigitsInExtension 4 -CountryOrRegionCode 1

Set-UMServer -Identity -DialPlans @{add=”UMDialPlan”}

New-UMIPGateway -Name Lyncpool_UMIPGateway -Address

New-UMHuntGroup -Name Lyncpool_HuntGroup -UMIPGateway Lyncpool_UMIPGateway -UMDialPlan “UMDialPlan”

This also is easier to document in your change management tracking than the following:

New-UMDialPlan -name “UMDialPlan” -UriType “SipName” -VoipSecurity Secured -NumberOfDigitsInExtension 4 -CountryOrRegionCode 1

Navigate to Exchange Install directory and then the scripts folder.

Run ExchUcUtil.ps1

Magic happens


In the overwhelming majority of networks, you can and should continue to run the ExchUcUtil.ps1 script and go on about life just fine. However, there are scenarios where you may not want to run it, be it due to firewalls blocking access between some Lync Servers and some Exchange Servers or simply because you want to have better control of the naming of your Gateways within Exchange UM.

In order to set up your configuration successfully without running the ExchUcUtil script, be sure that you have your security settings set up correctly. This is probably the easiest part to mess up or to forget to do if you add a new Exchange Organization with the UM role installed (or adding the UM role to an existing Organization). But once you have your security properly configured, the rest of the script simply automates step which you can do manually.



BTW – I do not get all of the credit of figuring this out and making it work in our produciton environment. Quite the contrary. So credit is due to those who chose to remain anonymous.

Get a list of Lync SBA’s via PowerShell

*****Updated 26 September 2016*****
Below is a much better way to get the list of SBA’s versus what I cobbled together below.

$registrars = get-csservice -registrar
$registrars | where {$_.Identity.split(":")[1] -ne $_.Webserver.split(":")[1]} | select Identity, UserServer

It looks at all registrars. If it does not have webservices then it is assumed to be an SBA/SBS.

*****Updated 24 June 2015*****

I can’t find an easy way to get a list of the SBA’s (and the occasional SBS) in our Lync environment. As such, I threw this script together. If someone has a better way to do this, by all means let me know as this is sort of a brute-force method.

$AllSites = get-cssite

Foreach($Site in $Allsites)
If ($Site.ParentSite -ne $Null)
     foreach($Service in $Site.Services)
          if ($Service -notlike "PstnGateway*")
          If ($i -eq 2)
               ForEach ($ServiceType in $Site.Services)
                    if($ServiceType -like "Registrar:*")
                         $PoolName = $ServiceType.TrimStart("Registrar:")
                         write-host $Poolname

Here is a quick breakdown of how this works. First it gathers a copy of the output from the get-cssite cmdlet. It then loops through each site. If the ParentSite attribute is null, then the given site cannot be for an SBA or an SBS so it throws that site away and loops to the next one. If it does have a ParentSite value it then checks to see if there are only 2 registered services. All SBA’s and SBS’s only have the following three services:
Registrar, MediationServer, and PSTNGateway

However, if there are multiple trunks defined, then there could be more than one PstnGateway service – 1 for each trunk. So the PstnGateway services get removed. If there are only 2 services left, then it’s assumed to be an SBA/SBS

If it has gotten this far then it is fairly certain that the given site hosts an SBA. The last step is to get the name of the SBA. This is done by grabbing the Registrar value from the Services attribute of the site and throwing away the “Registrar:” portion (which leaves the pool name which is the name of the SBS/SBA).

Document Lync Server IP’s

I had the need to generate a list of all the IP addresses of our Lync environment. Unlike the screenshot’s below, the production environment I work in has hundreds of Lync servers scattered all around. So off to PowerShell I went and I whipped up this simple script.

$ServersList = Get-CsManagementStoreReplicationStatus
 Foreach ($Server in $ServersList)
 $HostAddress = [System.Net.Dns]::GetHostAddresses($Server.ReplicaFQDN)
 write-host $Server.ReplicaFQDN - $HostAddress.IPAddressToString


The first challenge is getting a list of all Lync servers in the environment. I don’t know of a PowerShell command dedicated to this (Get-CsServers doesn’t exist!).  However, there is a neat little workaround to get this list. The Get-CsManagementStoreReplicationStatus cmdlet lists the replication status of all of the servers in your Lync environment. So this command is used to get the list of servers.

This list is then looped through one at a time and the server name is passed to a .Net command (GetHostAddresses). The result is then written to the screen.

Wrapping all of this into a Transcript allows the output to be easily saved to a text file.

The output of the command is below:


Lync Mobility Randomly (not) Working


This is what you want to see

We got hit up with an issue this morning that Lync Mobilty 2010 was not working for one of our 2010 pools. We were able to validate this and – as a side note – found that not many people are using it as we didn’t get hammered with tickets as we usually do with an outage.

We finally figured out that 2 of our Front End servers were jacked up. Rebooting them fixed our issues.

So how did we figure out which two of our Front End servers were failing? Open the following URL in your web browser, editing the server name for each host you want to test:

If you get a nicely formatted XML document returned, then you have no problem and you can move on to test the next server.

However, if you get a nasty IIS service issue, then reboot the server. We tried an IISreset and it didn’t work for us – but initially we were testing incorrectly so we rebooted a server or two that probably weren’t having a problem. So feel free to try IISreset first before punting the entire server.

Gateway peer in inbound call is not found in topology document


SIP/2.0 488 Not Acceptable Here

I was bringing up a new SIP trunk recently. After some SIP Invite manipulations we got outbound calls working. One would think inbound calls would be pretty straightforward.

Sadly, no.

I kept seeing this message in the Lync logging tool and Googling provided little assistance:

<?xml version=”1.0″ encoding=”us-ascii”?><reportError xmlns=””><error callId=”2085379370307201314329@″ fromUri=”;user=phone” toUri=”;user=phone” fromTag=”1c2085431640″ toTag=”” requestType=”INVITE” contentType=”application/sdp;call-type=audio” responseCode=”488″><diagHeader>10013;reason=”Gateway peer in inbound call is not found in topology document”</diagHeader><progressReports /></error></reportError>

Ummmm. That’s a lie! My gateway most assuredly resides in the Topology. Just for fun, I added the PSTN gateway a second time by IP address in addition to FQDN. This absolutely failed to fix the problem.

Long story short: This message is a little loose in what I think “not found in topology document” means. If I stretch the definition to mean “not found in topology document specifically as you defined it” then that might have been a bigger clue.

The fix was to set the Gateway to TCP (from TLS) to match the configuration within Lync. Once that was fixed, calls came in just fine.


Update: I saw this again. This time, the gateway was defined in DNS but the DNS address didn’t match the IP address of the gateway. So the gateway was sending correctly to Lync, but Lync was rejecting it because it didn’t know about this gateway. Putting the correct entry in via the HOSTS file fixed this in the short term. Long term – update the DNS entry.