Monthly Archives: August 2014

Updated Tool: Lync Common Area Phone Management (GUI)

If you haven’t seen it or played with it, there’s a free tool available to you that I’ve developed that will help manage Lync Common Area Phones with a GUI interface.  There is nothing to install, it’s a pure PowerShell script you can run.  Read more about that here if you haven’t seen it: http://www.lyncfix.com/?p=715

What’s new is that it’s been updated again due to a request by a user.

Marcel writes:

“Hi Anthony, thank you for this great tool. It is very helpful doing maintenance on the common area phones.
I have a few questions/suggestions:
– You cannot select multiple cap’s to make changes. For example: I want to assign a new Pin Policy on 100 phones. I have to do it one by one now. Can you make it possible to select multiple phones?
– The company I work for has one the largest and complex installations. When I start this tool I see all (3300+ phones on 100+ pools). Is it possible that you add a feature to select the correct pool?”

Introducing Version 1.2!  These capabilities have now been added.  As you can see in the screenshot below, there is a Filter dropdown that allows you to filter by pool, or all pools.  The ability to select multiple phones and set the pin, make changes, or remove them is now available as well.  If you wanted to grab a selection of phones from pool1 and move them to pool2 with a new voice policy and dial plan, just select the phones on the left, change the relevant dropdowns, and click the “Save Changes” button.  Fields that do not have values selected will not change when the “Save Changes” button is pressed.   This way, you can modify only one or a few settings at a time.

multiselect

If you have any thoughts, comments, bug reports, or feature requests, the Q/A section in the TechNet gallery is the best place, but I’m also watching here as well.

As with any free tool you find on the Internet, use at your own risk!

To download the program, please find it here in the TechNet Gallery: http://gallery.technet.microsoft.com/lync/Lync-2013-Common-Area-57bc4ff1

If you like it, please give it 5 stars over at the TechNet Gallery.  If not, please drop me a line before you rate it and give me a chance at fixing whatever bug you may have found.   I might also be able to add a feature you’d like to see!

Thanks again and let me know what you think!

How Many Users Can a Lync Pool Hold?

How many users can a Lync pool hold?  This question has come up a few times on the TechNet forums recently and I wanted to talk about it a little.

It’s referenced time and time again that the supported limit to a Lync Server Front End Pool is 80,000 users.

For Lync 2013: “The maximum number of users per pool is 80,000, with twelve Front End Servers. “: http://technet.microsoft.com/en-us/library/gg425939.aspx

For Lync 2010: “The maximum number of users per pool is 80,000, with eight Front End Servers.  “: http://technet.microsoft.com/en-us/library/gg425939(v=ocs.14).aspx

If your pool is a part of a pool pairing team, the number would be reduced as you wouldn’t want to invoke failover and end up with 160,000 users in a pool.  The why of this can be found by reviewing the capacity planning guides.  It’s effectively based upon tested and expected modality usages when run on recommended hardware: http://technet.microsoft.com/en-us/library/gg615015.aspx

The question that comes up on TechNet isn’t just “What’s supported”, it’s “What’s possible”?  Is this a hard limit?  People have been asking if Lync is used for just pure IM and presence, could you get away with more?  The technical answer is yes.  The limit is a supported limit only as you can see from the following lab screenshot where I’m querying the total number of users in a single pool.

lync2013

Hopefully you didn’t stop reading there and run off to build your enormous pool.  My strong suggestion is, despite what is possible, if you’re running Lync for this amount of users you should absolutely want to stay within supported parameters.  The last thing you’ll ever want to hear when tens of thousands of users are down and you’re scrambling is that you’re not running a supported configuration.  On the flip side, if you find yourself at 79,999 users, you’re not going to crash Lync by hiring and enabling two more employees, so take your time and build your new pool properly.

 

New Tool: Lync Common Area Phone Management (GUI)

 

Update (August 15, 2014): We’re just a few days in and there’s already a revision 🙂  Based on conversations I’ve had, there’s a desire for a 2010 version as well.  There are also environments that are mixed 2010/2013.  I have modified this tool to work equally well with both.  The commands behind the GUI are similar, however the 2010 commands do not have the ability to set PersistentChat, Mobility, or VoiceRoutingPolicy (hybrid O365 voice environments).  I can’t imagine these are policies that would ever be needed, however if you find a need, I can re-enable it for you.

Update (August 19, 2014): Version 1.2 released with the ability to modify multiple phones at once and filter by pool: http://www.lyncfix.com/?p=757

I created this tool to allow you to add, modify, and remove Lync common area phones with an easy to use graphical front end.  This functionality is not available within the Lync Control Panel and even modifications via the Lync Management Shell can be difficult to those who don’t have to modify them often.

I hope you find this tool straightforward to use.  From a Lync server, you can simply right click it and run it.  However,  due to the modules it loads, it may start faster if you start it from a Lync Management Shell.  The opening screen looks like what you see below.  The glaring red warning is just a note to let you know that sometimes replication can take a bit of time and you may need to hit the refresh buttons a few times before you see updated data.  Within a six server Enterprise pool I was watching it take upwards of 8 seconds.

You should see a listing of all of your common area phones in front of you.  From here, just select them in the left box and change any settings you’d like.  As you change the settings, the colors of the fields should turn green letting you know that a change is pending.  Once you’re ready, click the Save Changes button.  If you change the DisplayName attribute, you’ll receive a warning letting you know to refresh your phone list.  This is because this we use this name to  display and reference the phones in the GUI and behind the scenes.

2010Edition

Clicking the Refresh Phone List button refreshes the list of Common Area Phones and redisplays them.  Clicking the Refresh Phone box only refreshes the information shown in the right side of the screen.

Clicking the Set Pin button resets the pin for the selected phone.  If you enter a pin and receive a failure, the tool is intelligent enough to let you know the error.  In the below screenshots, we highlight a phone, click the Set Pin button, enter a pin and click OK.  The pin we’ve entered is too short however and we receive an error.  Had we entered a pin with the required number of digits, we would have been returned back to the tool without additional prompts.

2010setpin

2010pinerror

To remove a phone, simply highlight the phone of your choice and click the Remove Phone button.  You will be prompted for a confirmation before you delete.

2010remove

To add a new phone, click the Create Phone button.  A new dialog will pop up which will allow you to supply information about the phone.  The OU, Pool, LineURI and DisplayName are required fields, and if you miss one of these you will be notified before you click Create.  The others can be left as is.  Typing an OU in can be cumbersome, so I’ve also added a Browse button that will load all of your OUs as well as the users container.  Drill in and select the OU you want the Common Phone to be created in and click the Select button.  Once you’re ready, click the Create button.  You may need to wait a moment and click the Refresh Phone List button before the data is available to the GUI.

2010create

My own future thoughts for improvement include a multi-select mode where you could select multiple phones and modify them as a group.  Let me know if you’d like to see this implemented.

If you have any thoughts, comments, bug reports, or feature requests, the Q/A section in the TechNet gallery is the best place, but I’m also watching here as well.

As with any free tool you find on the Internet, use at your own risk!

To download the program, please find it here in the TechNet Gallery: http://gallery.technet.microsoft.com/lync/Lync-2013-Common-Area-57bc4ff1

If you like it, please give it 5 stars over at the TechNet Gallery.  If not, please drop me a line before you rate it and give me a chance at fixing whatever bug you may have found.   I might also be able to add a feature you’d like to see!

Thanks again and let me know what you think!

FIXED: Lync Mobile Numbers Not Showing In Mobility

There’s a long standing issue where users using the Lync mobile client can not see cellular phone numbers of coworkers unless their privacy relationship was manually set higher than the default on a user by user basis.  The common workaround was to add the mobile numbers to contacts in the affected user’s Outlook.  This of course wasn’t feasible if there were thousands of users.

Well, it looks like this one has finally be fixed.  The fix was just released today with the August 2014 cumulative updates!  I’ve been waiting for this one long enough that I felt it deserved it’s own post.

Find the details here: http://support.microsoft.com/kb/2967628/en-us

And download the CU here: http://www.microsoft.com/en-us/download/details.aspx?id=36820&751be11f-ede8-5a0c-058c-2ee190a24fa6

TL;DR Just Tell Me How to Edit Lync IVR from PowerShell

The previous article was a bit of a walkthrough on creating and modifying a Lync Interactive Response Group from the Lync Management Shell.  However, the meat of that and the reason it was written was really focused around how to modify an existing group.  The method to accomplish this isn’t clear at all if you’re just starting out and reading through TechNet.  As promised, here’s the short version for those who already know their way around.

To modify a workflow, we first need to pull it into a variable like so:

$workflow = Get-CsRgsWorkflow -Name “Our IVR”

To review settings, we can drill down into the object a bit at a time.  For example, we can see what the DefaultAction of the workflow is by typing $workflow.DefaultAction.  We see that the action is TransferToQuestion and there’s a Question attribute.  So now we can drill into the question attribute by typing $workflow.DefaultAction.Question.  We can also see there’s an AnswerList attribute, which is an array of answers.  We can access that array directly by specifying $workflow.DefaultAction.Question.AnswerList.

navigate1

You’ll notice that the AnswerList is a variable, and we can access it as such.  To get at a specific answer we can use $workflow.DefaultAction.Question.AnswerList[2] the same way we’d access any array in PowerShell.

navigate2

We can add responses by $workflow.DefaultAction.Question.AnswerList.Add($YourNewAction).  This allows us to drill down deeper into the new answer the same way.  In the example below, you can see me getting at an answerlist that is an option from a previous answer.

add1

To remove an answer, you’d use AnswerList.Remove() and specify which answer in the array you’d like to remove as seen here: $workflow.DefaultAction.Question.AnswerList.Remove($workflow.DefaultAction.Question.AnswerList[1]).

So far, we’ve only modified our $workflow variable, to write our changes back, we only need to type: Set-CsRgsWorkflow $workflow and we’re done!

Thanks for reading!

Lync Interactive Response Group Creation and Modification Via PowerShell

Introduction and Overview

Microsoft Lync provides the ability for callers to interact via questions and answers within a response group before being delivered to the appropriate queue.   This type of response group is typically referred to as an Interactive Voice Response Call Flow.  These questions, answers, and call flow settings are kept within a workflow.  The Lync Control Panel provides access to create and modify these workflows via a web page, which allows for easy modifications, however this method only supports up to two levels of questions with each question having up to four possible answers.  Via the Lync Management Shell, we have the ability to define any number of IVR questions and any number of answers.  The purpose of this article is a walkthrough of the procedures to create a workflow and to show you how to go beyond the limit of questions and answers available to you via the Control Panel GUI.  This article goes quite deep and can be a lot to consume, but due to the nature of how the examples build upon themselves, I didn’t feel that it should be broken up.  If you’d prefer, there’s also a tl;dr version that is a short and sweet look at the just commands to modify an existing response group.

Creating a Workflow

To begin, ensure that you are logged on as a member of the RTCUniversalServerAdmins group, or as a member of a group that has access to work with Lync Response Groups.

Before you create your workflow, make sure your agent groups and queues are properly defined.  If you don’t typically work with PowerShell, you might want to create your interactive workflow via the Control Panel first, and simply modify it with PowerShell after the fact if you need a larger question/answer set than provided.

Let’s start by defining a basic question and answer set.  We’ll keep this simple, but once you have the basics, you can build on it easily.  It may be easiest to sketch out your IVR flow on a sheet of paper, write out the questions, answers, and actions as seen below.

sketch

Let’s convert it into PowerShell.  We’ll work backwards to build our tree. Let’s start with a new prompt for the Sales Action.

$SalesPrompt = New-CsRgsPrompt -TextToSpeechPrompt “You have chosen sales, thank you.”

In our example, we want to transfer that to the Company_Sales queue.  So we’ll need to create an action and specify the queue.  The easiest way to do this is to pull the queue into a variable and specify it when creating our new action.

$CompanySalesQueue = Get-CsRgsQueue -Identity service:ApplicationServer:lyncpool.domain.com -Name Company_Sales

$SalesAction = New-CsRgsCallAction -Prompt $SalesPrompt -Action TransferToQueue  -QueueID $CompanySalesQueue.Identity

Let’s repeat for Accounting.

$AccountingPrompt = New-CsRgsPrompt -TextToSpeechPrompt “You have chosen accounting, thank you.”

$CompanyAccountingQueue = Get-CsRgsQueue -Identity service:ApplicationServer:lyncpool.domain.com -Name Company_Accounting

$AccountingAction = New-CsRgsCallAction -Prompt $AccountingPrompt -Action TransferToQueue  -QueueID $CompanyAccountingQueue.Identity

Now that we’ve got our actions built, we can move up one more level and build the Answers to our questions.

$SalesAnswer = New-CsRgsAnswer -Action $SalesAction -DtmfResponse 1 -VoiceResponseList Sales -Name “Sales Answer”

$AccountingAnswer = New-CsRgsAnswer -Action $AccountingAction -DtmfResponse 2 -VoiceResponseList Accounting, Accounts -Name “Accounting Answer”

We have our actions for our answers, let’s build our question.

$QuestionPrompt = New-CsRgsPrompt -TextToSpeechPrompt “Please press 1 for Sales or say Sales, or press 2 for Accounting or say Accounting or Accounts”

$QuestionObject = New-CsRgsQuestion -Prompt $QuestionPrompt  -AnswerList ($SalesAnswer, $AccountingAnswer)

$QuestionAction = New-CsRgsCallAction -Action TransferToQuestion  -Question $QuestionObject

We now have what we need to create our  workflow with the New-CsRgsWorkflow command.  There are many parameters that can be specified and these can be found in TechNet article referencing it in the references section of this article.  For our example, we’re going to start with the basics and build on it afterwards.

New-CsRgsWorkflow -Parent “service:ApplicationServer:lyncpool.domain.com”  -Name “Our IVR” -Description “Sales and Accounting IVR” -PrimaryUri “sip:salesacctivr@domain.com” -LineUri “tel:+15556667777” -DisplayNumber “+1 (555) 666-7777” -Active $true -DefaultAction $QuestionAction

FAkecreate2

Running the above command will create the workflow for us, but it wasn’t too complex as there was really only one question and two answers.  The next sections will show you how to add, modify, and remove questions and answers to go as deep as you’d like.

Adding Answers and New Questions

Adding Answers

Now we have a functional Interactive Response Group, but it’s time to make some changes.  Let’s use our example to add a third option to the original question to allow a caller to transfer to support.  We’ll start by building out our new answer as before.

$SupportPrompt = New-CsRgsPrompt -TextToSpeechPrompt “You have chosen support, thank you.”

$CompanySupportQueue = Get-CsRgsQueue -Identity service:ApplicationServer:lyncpool.domain.com -Name Company_Support

$SupportAction = New-CsRgsCallAction -Prompt $SupportPrompt -Action TransferToQueue  -QueueID $CompanySupportQueue.Identity

$SupportAnswer = New-CsRgsAnswer -Action $SupportAction -DtmfResponse 3 -VoiceResponseList Support -Name “Support Answer”

We’ll need to add our new answer on by loading our existing workgroup into a variable we can modify.  Once we’re done, we’ll save our changes by writing it back into to workflow with Set-CsRgsWorkflow.

Let’s load our workflow into a variable.

$workflow =GetCsRgsWorkflow -Name “Our IVR”

If we want to see what answers are already assigned to the first question, we can now review it simply by typing the following command.  Keep in mind that the answers are stored as an array, and can be accessed as such later.

$workflow.DefaultAction.Question.AnswerList

original_two_answers

To add our new answer, we use the following command.

$workflow.DefaultAction.Question.AnswerList.Add($SupportAnswer)

addanswer4

We can confirm by reviewing the contents of $workflow.DefaultAction.Question.AnswerList, that the new answer has been added.  However, we’re not done yet.  We’ve only added the answer to our $workflow variable.  This hasn’t been written back to our workflow.  The final step to save the command is to use the Set-CsRgsWorkflow command as seen below.

SetCsRgsWorkflow $workflow

save2

Adding Questions

So far, we’ve only set up answers that transfer to queues, but what if we need to ask another question before you can be properly transferred?  Let’s take the sales response and divide them into the tea sales team and the biscuit sales team.  Let’s build out a new question as we did at the start.

$TeaSalesPrompt = New-CsRgsPrompt -TextToSpeechPrompt “You have chosen tea sales, thank you.”

$CompanyTeaSalesQueue = Get-CsRgsQueue -Identity service:ApplicationServer:lyncpool.domain.com -Name Company_Tea_Sales

$TeaSalesAction = New-CsRgsCallAction -Prompt $TeaSalesPrompt -Action TransferToQueue  -QueueID $CompanyTeaSalesQueue.Identity

$BiscuitSalesPrompt = New-CsRgsPrompt -TextToSpeechPrompt “You have chosen biscuit sales, thank you.”

$CompanyBiscuitSalesQueue = Get-CsRgsQueue -Identity service:ApplicationServer:lyncpool.domain.com -Name Company_Biscuit_Sales

$BiscuitSalesAction = New-CsRgsCallAction -Prompt $BiscuitSalesPrompt -Action TransferToQueue  -QueueID $CompanyBiscuitSalesQueue.Identity

$TeaSalesAnswer = New-CsRgsAnswer -Action $TeaSalesAction -DtmfResponse 1 -VoiceResponseList Tea -Name “Tea Sales Answer”

$BiscuitSalesAnswer = New-CsRgsAnswer -Action $BiscuitSalesAction -DtmfResponse 2 -VoiceResponseList Biscuits -Name “Biscuit Sales Answer”

$SalesQuestionPrompt = New-CsRgsPrompt -TextToSpeechPrompt “Please press 1 for Tea Sales or say Tea, or press 2 for Biscuit sales or say Biscuits”

$SalesQuestionObject = New-CsRgsQuestion -Prompt $SalesQuestionPrompt  -AnswerList ($TeaSalesAnswer, $BiscuitSalesAnswer)

$SalesQuestionAction = New-CsRgsCallAction -Action TransferToQuestion  -Question $SalesQuestionObject

Now that we have our new question, we’ll need to assign it to an existing response.  Once we’re done, we’ll save our changes by writing it back into to workflow with Set-CsRgsWorkflow.

Let’s load our workflow into a variable.

$workflow =GetCsRgsWorkflow -Name “Our IVR”

If we want to see what answers are assigned to the first question, we can review it simply by typing the following command.  Keep in mind that the answers are stored as an array, and can be accessed as such later.

$workflow.DefaultAction.Question.AnswerList

answerlist1

We can see our sales response action is set to TransferToQueue.  We now want to change that to be a second set of questions.  To do so, we’ll need to change this action.  Remember that the answer list is an array, so to access the first answer, we’d use $workflow.DefaultAction.Question.AnswerList[0], to get to the second we’d use $workflow.DefaultAction.Question.AnswerList[1] and so on.  To change our action to reflect the new question we’d use the following commands.

$workflow.DefaultAction.Question.AnswerList[0].Action=$SalesQuestionAction

AddQuestion2

We can now confirm by reviewing the contents of $workflow.DefaultAction.Question.AnswerList, that the new question has been added.  You might be asking how to go one level deeper now and see the answers to the question you just added.  You can see them by typing the following command.

$workflow.DefaultAction.Question.AnswerList[0].Action.Question.AnswerList

addquestion3

As you can see, we can now add another question one level deeper with a similar command such as $workflow.DefaultAction.Question.AnswerList[0].Action.Question.AnswerList[0].Action=$YetAnotherQuestionAction and so on and so on.

However, we’re still not done yet.  We’ve only added the question to our $workflow variable.  This hasn’t been written back to our workflow.  The final step to save the command is to use the Set-CsRgsWorkflow command as seen below.

SetCsRgsWorkflow $workflow

Removing Answers and Questions

Removing Answers

Removing answers is a bit simpler than adding them, because there’s nothing to create.  Let’s take our accounting answer that we created at the beginning and pull it out.   This isn’t a particularly easy task in the GUI, but PowerShell makes it possible.  Let’s start once again by loading our workflow into a variable.

$workflow =GetCsRgsWorkflow -Name “Our IVR”

Let’s look at that accounting answer we want to remove.  We can see the answers by typing the following command:

$workflow.DefaultAction.Question.AnswerList

RemoveAnswer1

There it is, the second answer.  Remember that these are arrays, and arrays start counting with 0, so to get answer 2 we’ll subtract 1.  In our example, to access answer two, we’d use $workflow.DefaultAction.Question.AnswerList[1], the third answer would be $workflow.DefaultAction.Question.AnswerList[2], etc.  To remove the second answer, the exact command would be:

$workflow.DefaultAction.Question.AnswerList.Remove($workflow.DefaultAction.Question.AnswerList[1])

RemoveAnswer2

RemvoeAnswer3

Which is a bit to type, especially as you dive deeper into deeper levels of questions, but still, not too bad.  🙂

Remember to save it using the following command:

SetCsRgsWorkflow $workflow

Removing Questions

This section is somewhat of a trick, because you don’t just remove a question.  Remember that a question is an action and we can’t just remove an action without replacing it with something else, what would be the point of having an answer without an action?  To replace a question, just rewrite it as seen in the Adding Questions section and replace the action the same way.  To replace it with a queue, build out the action the same way we did in the Adding Answers section and set it as follows (and as always don’t forget to save with Set-CsRgsWorkflow).

$workflow.DefaultAction.Question.AnswerList[0].Action=$ReplacementAction

Modifications

I left modifications for last because it’s difficult to discuss without getting past the question and answer additions, subtractions, and replacements.  Perhaps we want to change a prompt.  Did you notice we added the support response in the Adding Answers section but never modified the prompt to let callers know the option existed?  We can review the prompt by looking at the question with $workflow.DefaultAction.Question, then modify it with:

$workflow.DefaultAction.Question.Prompt.TextToSpeechPrompt=”Please press 1 for Sales or say Sales, press 2 for Accountin or say Accouting, or press 3 for Support or simply say Support.”

ModifyPrompt1

MofifyPrompt2

And as always, don’t forget to save with Set-CsRgsWorkflow.  Did I mention you need to save?  You need to save.

save2

If you made it all the way here to the end, you have my gratitude.  Thank you for reading!