PortQueryUI Config.xml File for Lync

•May 10, 2013 • 8 Comments

At work we often use the Port Querycommand to test connectivity to services running on servers. We have a bunch of firewalls scattered all over the place and most of the time issues with Lync are due to firewall updates not having been made. The advantage to PortQry is that it can probe for UDP ports as opposed to just TCP ports that the built-in Windows Telnet client can test.

I don’t have time to memorize the command line switches for every command I run. Fortunately, there is also a GUI version of PortQry called PortQueryUI. (Note that Microsoft documentation refers to this as PortQryUI but the name of the executable is PortQueryUI. For readability purposes, I will use the latter.) Aside from not having to memorize any command line parameters, PortQueryUI let’s you easily run standard tests by selecting them from a drop down list.

PortQueryUI 1

The entries in the list are defined by an XML file named config.xml. If you open this file you will see the service lists followed by the relevant ports to query. For example, this is the entry for SQL Service:

<Service Name=”SQL Service”>

<Port Name=”ms-sql-s service” Protocol=”UDP” Value=”1434″/>

<Port Name=”ms-sql-s service” Protocol=”TCP” Value=”1433″/>

</Service>

It’s easy enough to figure out how to add your own entries. Simply create a new Service Name entry and under that define the ports you want to query. So I went ahead and created a bunch of these Service Names for all manner of Lync communication – 22 in total. I based my work off the very useful Windows Phone app Lync Protocol&Ports.

Click here to download the config.xml and then just copy it over the config.xml that comes with PortQueryUI.

Most likely I missed some ports and some options. Feel free to leave a comment and I’ll update the file with the corrections.

Working with Powershell Modules and Remote Sessions

•April 19, 2013 • Leave a Comment

load_unload_configurationsI had a request yesterday to see which users in an Active Directory group had a Lync conferencing policy applied. Easy enough request but the hitch was that the group was in a different domain than where the Lync servers are hosted. What I learned during this exercise was how to load and unload PowerShell modules automatically and how to establish a remote PowerShell session.

On my workstation’s PowerShell configuration, the Lync modules automatically load. However, when I set up the remote PowerShell session to a Lync server, I got an error back basically saying that there was a conflict between local commands and remote commands. For example, if I type Get-CSUser, will that run against the local instance of Get-CSUser or the remote instance? I didn’t want to figure out the details of the AllowClobber parameter. So the first thing I needed to do is determine if the local Lync module is loaded and then unload it. This is done with the following code:

if(Get-Module -name “Lync”)

{
Remove-Module “Lync”
}

I simply run the Get-Module cmdlet and pass it the name of the module. If the module can be “gotten” then it evaluates to true. If it is true, I then remove that module. If you don’t know the name of the modules you have loaded, you can run  Get-Module -ListAvailable.

The next thing I needed to do was to make sure the ActiveDirectory module was loaded as I was going to use the Get-ADGroupMembers <Group DN> -recursive cmdlet to enumerate all of the users in the AD group. To install the ActiveDirectory module on a Windows PC, follow the steps here. Very similar to above, the simple and straightforward thing to do is to see if the module is NOT loaded. If it is not loaded run the Import-Module command to load it.

if(-not(Get-Module -name ActiveDirectory))
{
Import-Module ActiveDirectory
}

There is a more complete way to import this module which I didn’t use in my script but I feel I should point out. My if statement above assumes that the ActiveDirectory module is actually installed and can be imported. Ideally you would check to see if the module is installed before loading the module.

$name=”ActiveDirectory”
if(-not(Get-Module -name $name))
{
if(Get-Module -ListAvailable | Where-Object { $_.name -eq $name })
{
#module available so import it
Import-Module -Name $name
}
else
{
#module not available
$false
}
} # end if not module
else
{
#Module already loaded
$true
}

Setting up the remote PowerShell session isn’t too complicated. I went with a basic check on the first pass and simply verified if any remote session already exists. If any remote session exists I assume it is for Lync.

$RemoteUsername = “na\flinchbot”
$RemoteConnectionURI =  “https://lyncfe01.na.flinchbot.com/OcsPowershell”

if (-not(Get-PsSession))
{
$cred = Get-Credential $RemoteUsername
$session = New-PSSession -ConnectionURI $RemoteConnectionURI -Credential $cred
Import-PsSession $session
}

Ideally you would go more advanced and would run a check to make sure the remote PowerShell Session specifically for Lync doesn’t already exist and that it is in a usable (i.e. “opened”) state. Check this bad boy out:

$RemoteUsername = “na\flinchbot”
$RemoteConnectionURI =  “https://lyncfe01.na.flinchbot.com/OcsPowershell”
$PSSessionState = Get-PsSession

If (($PSSessionState.Runspace.ConnectionInfo.ConnectionUri.AbsolutePath -ne “/OcsPowershell”) -and ($PSSessionState.Runspace.RunspaceStateInfo -ne “opened”))
{
$cred = Get-Credential $RemoteUsername
$session = New-PSSession -ConnectionURI $RemoteConnectionURI -Credential $cred
Import-PsSession $session
}

By grabbing the PSSession information and putting it into a variable, I can then check that variable for certain values. I can check to make sure that I am actually connected to a Lync remote PowerShell session by looking for the AbsoluteURI of “OcsPowershell”. If that does NOT exist AND if the session is NOT in an opened stated, I then create the session.

Well there you have it. How to check if modules are loaded and available and how to make sure a session already exists and how to create one.

Lync Holiday Sets for Canada + British Columbia

•March 28, 2013 • 1 Comment

The below powershell code has all of the major holidays for Canada and British Columbia through 2015. If your business isn’t in BC, then simply delete the $k variable in the New-CsRgsHolidaySet command. Replace <poolname> below with either the name of your pool or the name of your standard edition server.

$a = New-CsRgsHoliday -Name “New Year’s Day” -StartDate “1/1/2012″ -EndDate “1/2/2012″
$b = New-CsRgsHoliday -Name “Good Friday” -StartDate “4/6/2012″ -EndDate “4/22/2012″
$c = New-CsRgsHoliday -Name “Easter Monday” -StartDate “4/9/2012″ -EndDate “4/9/2012″
$d = New-CsRgsHoliday -Name “Victoria Day” -StartDate “5/21/2012″ -EndDate “5/21/2012″
$e = New-CsRgsHoliday -Name “Canada Day” -StartDate “7/1/2012″ -EndDate “7/1/2012″
$f = New-CsRgsHoliday -Name “Labour Day” -StartDate “9/3/2012″ -EndDate “9/3/2012″
$g = New-CsRgsHoliday -Name “Thanksgiving Day” -StartDate “10/8/2012″ -EndDate “10/8/2012″
$h = New-CsRgsHoliday -Name “Remembrance Day” -StartDate “11/11/2012″ -EndDate “11/12/2012″
$i = New-CsRgsHoliday -Name “Christmas Day” -StartDate “12/25/2012″ -EndDate “12/25/2012″
$j = New-CsRgsHoliday -Name “Boxing Day” -StartDate “12/26/2012″ -EndDate “12/26/2012″
$k = New-CsRgsHoliday -Name “British Columbia Day” -StartDate “8/6/2012″ -EndDate “8/6/2012″
New-CsRgsHolidaySet -Parent “service:ApplicationServer:<poolname>” -name “2012 CA Holidays” – holidaylist ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k)

$a = New-CsRgsHoliday -Name “New Year’s Day” -StartDate “1/1/2013″ -EndDate “1/1/2013″
$b = New-CsRgsHoliday -Name “Good Friday” -StartDate “3/29/2013″ -EndDate “3/29/2013″
$c = New-CsRgsHoliday -Name “Easter Monday” -StartDate “4/1/2013″ -EndDate “4/1/2013″
$d = New-CsRgsHoliday -Name “Victoria Day” -StartDate “5/20/2013″ -EndDate “5/20/2013″
$e = New-CsRgsHoliday -Name “Canada Day” -StartDate “7/1/2013″ -EndDate “7/1/2013″
$f = New-CsRgsHoliday -Name “Labour Day” -StartDate “9/2/2013″ -EndDate “9/2/2013″
$g = New-CsRgsHoliday -Name “Thanksgiving Day” -StartDate “10/14/2013″ -EndDate “10/14/2013″
$h = New-CsRgsHoliday -Name “Remembrance Day” -StartDate “11/11/2013″ -EndDate “11/11/2013″
$i = New-CsRgsHoliday -Name “Christmas Day” -StartDate “12/25/2013″ -EndDate “12/25/2013″
$j = New-CsRgsHoliday -Name “Boxing Day” -StartDate “12/26/2013″ -EndDate “12/26/2013″
$k = New-CsRgsHoliday -Name “British Columbia Day” -StartDate “8/5/2013″ -EndDate “8/5/2013″
New-CsRgsHolidaySet -Parent “service:ApplicationServer:<poolname>” -name “2013 CA Holidays” – holidaylist ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k)

$a = New-CsRgsHoliday -Name “New Year’s Day” -StartDate “1/1/2014″ -EndDate “1/1/2014″
$b = New-CsRgsHoliday -Name “Good Friday” -StartDate “4/18/2014″ -EndDate “4/18/2014″
$c = New-CsRgsHoliday -Name “Easter Monday” -StartDate “4/21/2014″ -EndDate “4/21/2014″
$d = New-CsRgsHoliday -Name “Victoria Day” -StartDate “5/19/2014″ -EndDate “5/19/2014″
$e = New-CsRgsHoliday -Name “Canada Day” -StartDate “7/1/2014″ -EndDate “7/1/2014″
$f = New-CsRgsHoliday -Name “Labour Day” -StartDate “9/1/2014″ -EndDate “9/1/2014″
$g = New-CsRgsHoliday -Name “Thanksgiving Day” -StartDate “10/13/2014″ -EndDate “10/13/2014″
$h = New-CsRgsHoliday -Name “Remembrance Day” -StartDate “11/11/2014″ -EndDate “11/11/2014″
$i = New-CsRgsHoliday -Name “Christmas Day” -StartDate “12/25/2014″ -EndDate “12/25/2014″
$j = New-CsRgsHoliday -Name “Boxing Day” -StartDate “12/26/2014″ -EndDate “12/26/2014″
$k = New-CsRgsHoliday -Name “British Columbia Day” -StartDate “8/4/2014″ -EndDate “8/4/2014″
New-CsRgsHolidaySet -Parent “service:ApplicationServer:<poolname>” -name “2014 CA Holidays” – holidaylist ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k)

$a = New-CsRgsHoliday -Name “New Year’s Day” -StartDate “1/1/2015″ -EndDate “1/1/2015″
$b = New-CsRgsHoliday -Name “Good Friday” -StartDate “4/3/2015″ -EndDate “4/3/2015″
$c = New-CsRgsHoliday -Name “Easter Monday” -StartDate “4/6/2015″ -EndDate “4/6/2015″
$d = New-CsRgsHoliday -Name “Victoria Day” -StartDate “5/18/2015″ -EndDate “5/18/2015″
$e = New-CsRgsHoliday -Name “Canada Day” -StartDate “7/1/2015″ -EndDate “7/1/2015″
$f = New-CsRgsHoliday -Name “Labour Day” -StartDate “9/7/2015″ -EndDate “9/7/2015″
$g = New-CsRgsHoliday -Name “Thanksgiving Day” -StartDate “10/12/2015″ -EndDate “10/12/2015″
$h = New-CsRgsHoliday -Name “Remembrance Day” -StartDate “11/11/2015″ -EndDate “11/11/2015″
$i = New-CsRgsHoliday -Name “Christmas Day” -StartDate “12/25/2015″ -EndDate “12/25/2015″
$j = New-CsRgsHoliday -Name “Boxing Day” -StartDate “12/26/2015″ -EndDate “12/28/2015″
$k = New-CsRgsHoliday -Name “British Columbia Day” -StartDate “8/3/2015″ -EndDate “8/3/2015″
New-CsRgsHolidaySet -Parent “service:ApplicationServer:<poolname>” -name “2015 CA Holidays” – holidaylist ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k)

To apply these holiday sets to an existing Response Group Service, run the following for each year:

$HolidayHours = Get-CsRgsHolidaySet “service:ApplicationServer:<poolname>” -Name “<Name of Holiday Set>”

$y = Get-CsRgsWorkflow <poolname> -Name “<Name of Response Group>”

$y.HolidaySetIDList.Add($HolidayHours.Identity)

Set-CsRgsWorkflow -Instance $y

Lync Holiday Sets for the USA

•March 28, 2013 • 1 Comment

The below powershell code has all of the major and minor holidays for the United States through 2015. If your business isn’t closed on the minor holidays, then simply delete those variables in the New-CsRgsHolidaySet command. Replace <poolname> below with either the name of your pool or the name of your standard edition server.

$a = New-CsRgsHoliday -Name "New Year's Day" -StartDate "1/1/2011" -EndDate "1/2/2011"
$b = New-CsRgsHoliday -Name "Martin Luther King Jr. Day" -StartDate "1/17/2011" -EndDate "1/17/2011"
$c = New-CsRgsHoliday -Name "President's Day" -StartDate "2/21/2011" -EndDate "2/21/2011"
$d = New-CsRgsHoliday -Name "Memorial Day" -StartDate "5/30/2011" -EndDate "5/30/2011"
$e = New-CsRgsHoliday -Name "Independence Day" -StartDate "7/4/2011" -EndDate "7/4/2011"
$f = New-CsRgsHoliday -Name "Labor Day" -StartDate "9/5/2011" -EndDate "9/5/2011"
$g = New-CsRgsHoliday -Name "Columbus Day" -StartDate "10/10/2011" -EndDate "10/10/2011"
$h = New-CsRgsHoliday -Name "Veterans Day" -StartDate "11/11/2011" -EndDate "11/11/2011"
$i = New-CsRgsHoliday -Name "Thanksgiving Day" -StartDate "11/24/2011" -EndDate "11/24/2011"
$j = New-CsRgsHoliday -Name "Christmas Day" -StartDate "12/26/2011" -EndDate "12/26/2011"
New-CsRgsHolidaySet -Parent "service:ApplicationServer:<poolname>" -name "2011 US Holidays" - holidaylist ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j)

$a = New-CsRgsHoliday -Name “New Year’s Day” -StartDate “1/1/2013″ -EndDate “1/2/2013″
$b = New-CsRgsHoliday -Name “Martin Luther King Jr. Day” -StartDate “1/21/2013″ -EndDate “1/21/2013″
$c = New-CsRgsHoliday -Name “President’s Day” -StartDate “2/18/2013″ -EndDate “2/18/2013″
$d = New-CsRgsHoliday -Name “Memorial Day” -StartDate “5/27/2013″ -EndDate “5/27/2013″
$e = New-CsRgsHoliday -Name “Independence Day” -StartDate “7/4/2013″ -EndDate “7/4/2013″
$f = New-CsRgsHoliday -Name “Labor Day” -StartDate “9/2/2013″ -EndDate “9/2/2013″
$g = New-CsRgsHoliday -Name “Columbus Day” -StartDate “10/14/2013″ -EndDate “10/14/2013″
$h = New-CsRgsHoliday -Name “Veterans Day” -StartDate “11/11/2013″ -EndDate “11/11/2013″
$i = New-CsRgsHoliday -Name “Thanksgiving Day” -StartDate “11/28/2013″ -EndDate “11/28/2013″
$j = New-CsRgsHoliday -Name “Christmas Day” -StartDate “12/25/2013″ -EndDate “12/25/2013″
New-CsRgsHolidaySet -Parent “service:ApplicationServer:<poolname>” -name “2013 US Holidays” -holidaylist ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j)

$a = New-CsRgsHoliday -Name “New Year’s Day” -StartDate “1/1/2014″ -EndDate “1/2/2014″
$b = New-CsRgsHoliday -Name “Martin Luther King Jr. Day” -StartDate “1/20/2014″ -EndDate “1/20/2014″
$c = New-CsRgsHoliday -Name “President’s Day” -StartDate “2/17/2014″ -EndDate “2/17/2014″
$d = New-CsRgsHoliday -Name “Memorial Day” -StartDate “5/26/2014″ -EndDate “5/26/2014″
$e = New-CsRgsHoliday -Name “Independence Day” -StartDate “7/4/2014″ -EndDate “7/4/2014″
$f = New-CsRgsHoliday -Name “Labor Day” -StartDate “9/1/2014″ -EndDate “9/1/2014″
$g = New-CsRgsHoliday -Name “Columbus Day” -StartDate “10/13/2014″ -EndDate “10/13/2014″
$h = New-CsRgsHoliday -Name “Veterans Day” -StartDate “11/11/2014″ -EndDate “11/11/2014″
$i = New-CsRgsHoliday -Name “Thanksgiving Day” -StartDate “11/27/2014″ -EndDate “11/27/2014″
$j = New-CsRgsHoliday -Name “Christmas Day” -StartDate “12/25/2014″ -EndDate “12/25/2014″
New-CsRgsHolidaySet -Parent “service:ApplicationServer:<poolname>” -name “2014 US Holidays” -holidaylist ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j)

$a = New-CsRgsHoliday -Name “New Year’s Day” -StartDate “1/1/2015″ -EndDate “1/2/2015″
$b = New-CsRgsHoliday -Name “Martin Luther King Jr. Day” -StartDate “1/19/2015″ -EndDate “1/19/2015″
$c = New-CsRgsHoliday -Name “President’s Day” -StartDate “2/16/2015″ -EndDate “2/16/2015″
$d = New-CsRgsHoliday -Name “Memorial Day” -StartDate “5/25/2015″ -EndDate “5/25/2015″
$e = New-CsRgsHoliday -Name “Independence Day” -StartDate “7/4/2015″ -EndDate “7/4/2015″
$f = New-CsRgsHoliday -Name “Labor Day” -StartDate “9/7/2015″ -EndDate “9/7/2015″
$g = New-CsRgsHoliday -Name “Columbus Day” -StartDate “10/12/2015″ -EndDate “10/12/2015″
$h = New-CsRgsHoliday -Name “Veterans Day” -StartDate “11/11/2015″ -EndDate “11/11/2015″
$i = New-CsRgsHoliday -Name “Thanksgiving Day” -StartDate “11/26/2015″ -EndDate “11/26/2015″
$j = New-CsRgsHoliday -Name “Christmas Day” -StartDate “12/25/2015″ -EndDate “12/25/2015″

New-CsRgsHolidaySet -Parent “service:ApplicationServer:<poolname>” -name “2015 US Holidays” -holidaylist ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j)

To apply these holiday sets to an existing Response Group Service, run the following for each year:

$HolidayHours = Get-CsRgsHolidaySet “service:ApplicationServer:<poolname>” -Name “<Name of Holiday Set>”

$y = Get-CsRgsWorkflow <poolname> -Name “<Name of Response Group>”

$y.HolidaySetIDList.Add($HolidayHours.Identity)

Set-CsRgsWorkflow -Instance $y

Blocking Premium Toll in Lync Dial Plans

•March 28, 2013 • Leave a Comment
...at least a little bit...

…at least a little bit…

I am building a dial plan where the need is to drop calls to premium toll numbers, such as 900/976 in the US. There is an elegant solution to this which is a much better user-friendly solution.

Due to our infrastructure, I can’t really implement that fix. Ideally, I need to block the call before it ever gets routed anywhere. I need it blocked at the dial plan. Fortunately, I found a way to do this within Regular Expressions. As this was a new RegEx trick to me, I thought I’d share it.

The challenge here is not to be able to simply block 900 numbers, but to allow all calls unless they are 900 numbers. To accomplish this, I discovered the Regular Expression construct of negative lookahead assertion.  The construct is simple and looks like so:

(?!subexpression )

To use that with Lync and blocking premium numbers in the US, you could go with something like this:

^(?!(900|976))(\d+)$

+$1$2

If the user dials 9001234567 the negative lookahead assertion fires. When testing this while in the “Edit Normalization Rule” screen of Lync Control Panel, you should see the heartwarming “No match exists for the regular expression that you built.” message. Yet when you dial anything else, then you will have a successful match.

To build on this, assume you are in South Korea and assume that you have to dial 111 to route your call to a 3rd party long distance provider. Further, assume users could dial either an 8 or a 9 before dialing as that was their habit on the PBX from which they are being migrated. In South Korea, the premium toll numbers are 001, 002, and 00700. The following is what I put together and appears to work fine so far in our testing:

^8?9?(111)(?!(001|002|0070))(\d+)$

+$1$2$3

So if the user dials 8111001xxxxxx or 9111002xxxx or 1110070xxxxx or many other permutations, the call gets dropped by the dial plan as there is no match. However, if the user dials 8111356xxxxx or 9111202xxxxxx or 1110060xxxx or many other such permutations, Lync will find a RegEx match and forward the call on to ultimately be routed to its endpoint destination.

The site ## was not found in the topology

•March 21, 2013 • Leave a Comment

We ran into a problem the past 36 hours when publishing our Lync topology. When publishing either via Topology Builder or via the Enable-CsTopology PowerShell cmdlet, the warnings seen in the screen shots below would occasionally pop up - The site ## was not found in the topoology.

cs-enable1

Ignore the red errors. They are irrelevant to this issue.

Ignore the red errors. They are irrelevant to this issue.

We knew that Site 19 was a site that we had removed from the topology the previous week. We just couldn’t figure out why this particular site removal messed up the publishing.

We have another issue in that our topology publish is not finishing. Since the topology publish isn’t completing, there is no html file for us to review to troubleshoot this error. However, we found an XML file that did contain a log for us to review. This XML file is in the temp directory of the user running the publish.

We opened that XML file and searched for Site 19 and found the following:

xml log2

Note the Kerberos error? This was our clue that perhaps this site was configured with a Kerberos account. So we ran Get-CsKerberosAccountAssignment and sure enough, Site 19 was in the list.

remove kerberos1

Since we knew that site was gone, we went ahead and ran Remove-csKerberosAccountAssignment -identity “site:19″ to remove the Kerberos account assignment for Site 19.

We then ran Enable-CsTopology and it ran with nary a hint of Site 19.



** Just for credit, 2 coworkers did all of this legwork. I just wrote this up for them.**

Lync CU Updates Without Descriptions

•March 18, 2013 • Leave a Comment

whatIn this last batch of Lync Cumulative Updates, two of them (1, 2) have no description of what is fixed, what is added, or any information about them whatsoever.

So I asked my Microsoft contact what exactly these updates are supposed to do?

From the product group I found out that there were some code updates done which improves the performance and some updates that not visible outside. I would recommend installing them in your environment.

So there you go. It would be nice if Microsoft threw in a line basically saying the above.

 

 
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: