Showing posts with label powershell. Show all posts
Showing posts with label powershell. Show all posts

Friday, February 15, 2013

Cross-Post: Lync Environment Documentation Script

This post is just to get the word out a bit wider about a script that my colleague, Chris Cook, has developed. 

Basically this script will gather complete information about a Lync environment (server specs, topology, networking, DNS, certificates, etc) and then auto-generate a Word report and Visio diagram.

Please go HERE and read additional information and download instructions.

Thursday, March 15, 2012

Enabling Privileged Accounts for Lync

While it is not recommended to enable privileged accounts (e.g. Domain Admins) for Lync or Exchange, sometimes it is needed.

By default, Lync blocks the option when trying to enable a Domain Admin from the Lync Control Panel.  In my example, I am enabling the Administrator account.  I receive the following error:

Active Directory operation failed on <DC server name>. You cannot retry this operation: “Insufficient access rights to perform the operation…..”

Lync - Enable Admin failure

The error is pretty explanatory.  So to test out the solution in the error, we should try enabling the privileged account by:

  • Logging into server as a member of the Domain Admins group
  • Enabling the user using the Lync Management Shell (LMS)

So trying again from the Lync Management Shell:

Enable-CsUser Administrator –SipAddressType SamAccountName –SipDomain twhlab.com –RegistrarPool pool.twhlab.com

Lync - Enable Admin command

The command runs successfully and now the Administrator account is enabled for Lync.

Lync - Enable Admin CP

Enabling privileged accounts must be performed from the Lync Management Shell.

Monday, February 20, 2012

Configuring Accounts for Synthetic Transactions in Lync Server

Lync Server has numerous “Test-“ cmdlets that will allow for Lync administrators to validate certain functions.  Below are just some of the “Test-“ cmdlets that are available (a full list can be viewed here):

  • Test-CsAddressBookService
  • Test-CsAddressBookWebQuery
  • Test-CsAVConference
  • Test-CsDialinConferencing
  • Test-CsGroupIM
  • Test-CsIM
  • Test-CsP2PAV
  • Test-CsRegistration

When trying to run one of these cmdlets, you will get the following error:  “There is no test user assigned for <poolName>. Please check test user settings.”

Our example runs the following command:

Test-CsIM –TargetFQDN pool.twhlab.com

Lync ST - before error 1

You could run this command and specify user accounts, passwords, and SIP addresses every time, but this can get a bit cumbersome if you plan on using the “Test-“ cmdlets frequently or use an automated job.

The following procedure will show you how to configure user accounts to be used with synthetic transactions.

First Step - Create two user accounts

These can be (and should be) disabled since these accounts will only be used to run the “Test-“ cmdlets.  After creating the AD accounts, enable them for Lync.

Lync ST - Users

Note: you should create two test accounts for each Lync pool.

Second Step - Configure the Lync test accounts for Synthetic Transactions

Run the following command:

New-CsHealthMonitoringConfiguration –Identity <poolName> –FirstTestSamAccountName <FirstUserAccount> –FirstTestUserSipUri <FirstUserSIPAddress> –SecondTestSamAccountName <SecondUserAccount> –SecondTestUserSipUri <SecondUserSIPAddress>

In my example, I run:

New-CsHealthMonitoringConfiguration –Identity pool.twhlab.com –FirstTestSamAccountName Homelab\LyncSynthUser1 –FirstTestUserSipUri “sip:LyncSynthUser1@twhlab.com” –SecondTestSamAccountName Homelab\LyncSynthUser2 –SecondTestUserSipUri “sip:LyncSynthUser2@twhlab.com”

Lync ST - New-CsHeath

Once the accounts have been configured, you can change or remove the configurations with the Set-CsHealthMonitoringConfiguration or Remove-CsHealthMonitoringConfiguration cmdlets.

Step Three – Test the configuration

Now that the accounts have been provisioned and configured for synthetic transactions, it is time to test.  If the accounts were set up correctly, you should be able to run previous command that failed (without specifying users or credentials):

Test-CsIM –TargetFQDN pool.twhlab.com

Lync ST - before sucess1

Configuring synthetic transactions allows administrators to run tests without having to supply user names or passwords for the required test accounts.

Wednesday, September 21, 2011

Understanding and Enforcing Licensing for the Lync Standard User CAL–Part 2

In Part 1 of this article we looked at what functionality is included in the Standard CAL for Lync.  Now it is time to show how to enforce functionality by creating or modifying policies and configurations.

There are three primary places that must be configured to enforce the Standard CAL:

  • Conferencing Policy
  • Meeting Configuration
  • Lync Outlook plug-in

Conferencing Policy

By default, Enterprise CAL functionality is enabled.  By looking at the Global conferencing policy (which gets assigned by default), we can see that most conferencing functionality is enabled:

Lync SCAL2 - global default

If your environment will only have Standard CAL users then all the following configurations can be performed at the Global scope level.  Looking at the parameters in the Global conferencing policy, we need to modify the following:

  • AllowIPAudio: False
  • AllowIPVideo: False
  • AllowUserToScheduleMeetingsWithAppSharing: False
  • AllowAnonymousParticipantsInMeetings: False
  • AllowPolls: False (wasn’t 100% sure on this one since it is not specifically defined in the licensing matrix)
  • EnableAppDesktopSharing: None (remember you can view, but not initiate)
  • EnableDialinConferencing: False

I will create a new conferencing policy based on these criteria:

New-CsConferencingPolicy –Identity “Conf-StandardCAL” –AllowIPAudio $false –AllowIPVideo $false –AllowUserToScheduleMeetingsWithAppSharing $false –AllowPolls $false –EnableAppDesktopSharing None –EnableDialinConferencing $false

Lync SCAL2 - conf-scal

Note the following:

  • Data Collaboration must be enabled to allow for multi-party File Transfer
  • Do not throttle the Max Meeting Size parameter to two or less since this would disable multi-party IM.  The following screenshots show the effect of throttling the Max Meeting Size:

Lync SCAL - drag 3rd limited meetingLync SCAL - drag 3rd limited meeting - other

Meeting Configuration

By default, users within your company join Online Meetings as presenters.  You should change this default setting so that only the Organizer is the presenter.  This will prohibit Standard CAL users joining the meeting as a presenter.  The Organizer can always change per meeting at the time of scheduling the meeting within the Meeting Options of the Online Meeting.  To change the default behavior, navigate in the Lync Control Panel to Conferencing –> Meeting Configuration.  Select “None” in the Designate as presenter drop-down.

Unfortunately, the only scope options are Global, Site, and Pool. Change the options of the Meeting Configuration so that “None” is set to the default presenter:

Lync SCAL2 - meet config - markup

Lync Outlook Plug-in

Lync will install the Lync Outlook plug-in by default as part of the Lync client install.  This is great compared to OCS where it was two different installs, but can cause a confusing experience for Standard CAL users.  The only reason to use the plug-in is to schedule conferences. 

Remember that Standard CAL users can attend a conference, but cannot initiate/schedule a conference.  If the Outlook plug-in remains visible, the Standard CAL user can still create an online meeting.  My suggestion is to disable the Lync Outlook plug-in, this will not prohibit them from attending a meeting that they are invited to.

The registry setting that controls the load behavior of the Outlook plug-in is:

HKEY_CURRENT_USER\Software\Microsoft\Office\Outlook\Addins\UCAddin.UCAddin.1\

  • DWORD: LoadBehavior
  • Value (Decimal): 2

This can easily be rolled out and applied to StandardCAL users with a GPO:

Lync SCAL2 - gpo

Part 2 of this post describes how to enforce the Standard CAL Lync settings described in Part 1.  Licensing and interpretation of licensing is always tough, so if you feel that I have misrepresented the licensing provided to the Standard CAL user or feel that I have missed a configuration, please leave a comment.

Tuesday, May 24, 2011

Documenting your Lync Voice Configuration

First off, all credit for this post goes to my colleague Chris Cook.  He provided all of the powershell scripting behind the tool.

UPDATED: Added download of file HERE

I have found it very difficult to easily document a voice configuration within Lync.  That is when I approached my scripting buddy Chris.  He developed this script to extract the export from the Lync Control Panel Voice Configuration:

LyncVoice - Export config - markup

When exporting the configuration, it saves as a *.vcfg file.  Using Chris’ handy powershell cmdlet, we can extract the contents of the *.vcfg file into an Excel spreadsheet with different tabs for each area: Dial Plan, Voice Policy, Route, PSTN Usage, and Trunk Configuration.

Copy the following powershell script as a .ps1 file and save in the same location as the exported *.vcfg file.

Download LyncVCFGConverter.ps1 here

##################################################
#
#  LyncVCFGConverter.ps1
#  Format Exported .vcfg file from Lync to Excel
#
#  Author: Chris Cook
#
#  Use at your own risk!
#
##################################################
 
 
cls
#Collect VCFG Filename from Command Line Arguments
$VCFGFileName = $args[0]
Write-Host "Importing XML Config..."
$VCFGXML = [xml](get-content $VCFGFileName)
Write-Host "Done"
 
#Get current working directory and convert it to a string.
$CurrentDirectory = Get-Location
$CurrentDirectory = $CurrentDirectory.ToString()
 
#Set the file name for the Excel Spreadsheet we're working with.
#Drop the VCFG extension and add " - Voice Config.XLSX" to the end.
Write-Host "Starting Excel..."
$ExcelFileName = $VCFGFileName.substring(0,$VCFGFileName.Length - 5) + " - Voice  Config.XLSX"
 
#Create the Excel Instance we will be working with.
$ExcelApp = New-Object -comobject Excel.Application
 
#Create a new Workbook and add 2 extra sheets for 5 total.
Write-Host "Configuring Worksheets..."
$Workbook = $ExcelApp.Workbooks.Add()
$Worksheets = $WorkBook.Worksheets.Add()
$Worksheets = $WorkBook.Worksheets.Add()
 
#Name the sheets in the Workbook and assign variables to them.
$LocationProfilesSheet = $Workbook.Worksheets.Item(1)
$LocationProfilesSheet.Name = "Location Profiles"
$PSTNUsagesSheet = $Workbook.Worksheets.Item(2)
$PSTNUsagesSheet.Name = "PSTN Usages"
$PSTNRoutesSheet = $Workbook.Worksheets.Item(3)
$PSTNRoutesSheet.Name = "PSTN Routes"
$VoicePolicySheet = $Workbook.Worksheets.Item(4)
$VoicePolicySheet.Name = "Voice Policies"
$TrunkSheet = $Workbook.Worksheets.Item(5)
$TrunkSheet.Name = "Trunk Configuration"
Write-Host "Done"
 
#Configure layout for Location Profile Sheet
Write-Host "**Building Location Profile Sheet**"
$LocationProfilesSheet.Cells.Item(1,1) = "Dial Plan"
$LocationProfilesSheet.Cells.Item(1,2) = "Scope"
$LocationProfilesSheet.Cells.Item(1,3) = "Dial Plan Description"
$LocationProfilesSheet.Cells.Item(1,4) = "Rule"
$LocationProfilesSheet.Cells.Item(1,5) = "Rule Description"
$LocationProfilesSheet.Cells.Item(1,6) = "Pattern"
$LocationProfilesSheet.Cells.Item(1,7) = "Translation"
$LocationProfilesSheet.Cells.Item(1,8) = "Dialin Conferencing Region"
 
$CurrentRow = 2
 
#Import XML data into Excel fields.
$LocationProfiles = @($VCFGXML.Datasource.LocationProfiles.Datasource)
ForEach ($DialPlan in $LocationProfiles){
Write-Host "Found Dial Plan: " $DialPlan.DialPlanName
ForEach ($Rule in $DialPlan.Rules.Datasource){
Write-Host "Importing Rule: " $Rule.Name
$LocationProfilesSheet.Cells.Item($CurrentRow,1) = $DialPlan.Name
$LocationProfilesSheet.Cells.Item($CurrentRow,2) = $DialPlan.Scope
$LocationProfilesSheet.Cells.Item($CurrentRow,3) = $DialPlan.Description
$LocationProfilesSheet.Cells.Item($CurrentRow,4) = $Rule.Name
$LocationProfilesSheet.Cells.Item($CurrentRow,5) = $Rule.Description
$LocationProfilesSheet.Cells.Item($CurrentRow,6) = $Rule.Pattern
$LocationProfilesSheet.Cells.Item($CurrentRow,7) = $Rule.Translation
$LocationProfilesSheet.Cells.Item($CurrentRow,8) = $DialPlan.DialinConferencingRegion
$CurrentRow = $CurrentRow + 1
}
}
Write-Host "**Done with Location Profile Sheet**"
 
#Configure layout for PSTN Usages Sheet
Write-Host "**Building PSTN Usages Sheet**"
$PSTNUsagesSheet.Cells.Item(1,1) = "Name"
$PSTNUsagesSheet.Cells.Item(1,2) = "Identity"
$PSTNUsagesSheet.Cells.Item(1,3) = "Scope"
$CurrentRow = 2
 
#Import XML data into Excel fields.
$PSTNUsages = @($VCFGXML.Datasource.PSTNUsages.Datasource)
ForEach ($Usages in $PSTNUsages){
ForEach ($Usage in $Usages.Usages.Datasource){
Write-Host "Importing Usage: " $Usage.Name
$PSTNUsagesSheet.Cells.Item($CurrentRow,1) = $Usage.Name
$PSTNUsagesSheet.Cells.Item($CurrentRow,2) = $Usages.Identity
$PSTNUsagesSheet.Cells.Item($CurrentRow,3) = $Usages.Scope
$CurrentRow = $CurrentRow + 1
}
}
Write-Host "**Done with PSTN Usages Sheet**"
 
#Configure layout for PSTN Route Settings Sheet
Write-Host "**Building PSTN Route Settings Sheet**"
$PSTNRoutesSheet.Cells.Item(1,1) = "Route Name"
$PSTNRoutesSheet.Cells.Item(1,2) = "Usage"
$PSTNRoutesSheet.Cells.Item(1,3) = "Route Description"
$PSTNRoutesSheet.Cells.Item(1,4) = "Number Pattern"
$PSTNRoutesSheet.Cells.Item(1,5) = "Supress Caller ID"
$PSTNRoutesSheet.Cells.Item(1,6) = "PSTN Gateway"
$CurrentRow = 2
 
#Import XML data into Excel fields.
$RouteSettings = @($VCFGXML.Datasource.PSTNRouteSettings.Datasource)
ForEach ($RouteGroup in $RouteSettings){
ForEach ($Route in $RouteGroup.Routes.Datasource){
Write-Host "Importing Route: " $Route.Name
$PSTNRoutesSheet.Cells.Item($CurrentRow,1) = $Route.Name
$PSTNRoutesSheet.Cells.Item($CurrentRow,3) = $Route.Description
$PSTNRoutesSheet.Cells.Item($CurrentRow,4) = $Route.NumberPattern
$PSTNRoutesSheet.Cells.Item($CurrentRow,5) = $Route.SuppressCallerId
ForEach ($Usage in $Route.Usages.Datasource){
$PSTNRoutesSheet.Cells.Item($CurrentRow,2) = $Usage.Name
}
ForEach ($Gateway in $Route.Gateways.Datasource){
$PSTNRoutesSheet.Cells.Item($CurrentRow,6) = $Gateway.ServiceId
}
$CurrentRow = $CurrentRow + 1
}
}
Write-Host "**Done with PSTN Route Settings Sheet**"
 
#Configure layout for Voice Policies Sheet
Write-Host "**Building Voice Policies Sheet**"
$VoicePolicySheet.Cells.Item(1,1) = "Voice Policy Name"
$VoicePolicySheet.Cells.Item(1,2) = "Description"
$VoicePolicySheet.Cells.Item(1,3) = "Scope"
$VoicePolicySheet.Cells.Item(1,4) = "Usage"
$VoicePolicySheet.Cells.Item(1,5) = "Allow Simultaneous Ring"
$VoicePolicySheet.Cells.Item(1,6) = "Allow Call Forwarding"
$VoicePolicySheet.Cells.Item(1,7) = "Allow PSTN Rerouting"
$VoicePolicySheet.Cells.Item(1,8) = "Enable Delegation"
$VoicePolicySheet.Cells.Item(1,9) = "Enable Team Call"
$VoicePolicySheet.Cells.Item(1,10) = "Enable Call Transfer"
$VoicePolicySheet.Cells.Item(1,11) = "Enable Call Park"
$VoicePolicySheet.Cells.Item(1,12) = "Enable Malicious Call tracing"
$VoicePolicySheet.Cells.Item(1,13) = "Enable Bandwidth Policy Override"
$CurrentRow = 2
 
#Import XML data into Excel fields.
$VoicePolicies = @($VCFGXML.Datasource.VoicePolicies.Datasource)
ForEach ($Policy in $VoicePolicies){
Write-Host "Importing Policies for: " $Policy.Name
ForEach ($Usage in $Policy.Usages.Datasource){
$VoicePolicySheet.Cells.Item($CurrentRow,1) = $Policy.Name
$VoicePolicySheet.Cells.Item($CurrentRow,2) = $Policy.Description
$VoicePolicySheet.Cells.Item($CurrentRow,3) = $Policy.Scope
$VoicePolicySheet.Cells.Item($CurrentRow,4) = $Usage.Name
$VoicePolicySheet.Cells.Item($CurrentRow,5) = $Policy.AllowSimulRing
$VoicePolicySheet.Cells.Item($CurrentRow,6) = $Policy.AllowCallForwarding
$VoicePolicySheet.Cells.Item($CurrentRow,7) = $Policy.AllowPSTNReRouting
$VoicePolicySheet.Cells.Item($CurrentRow,8) = $Policy.EnableDelegation
$VoicePolicySheet.Cells.Item($CurrentRow,9) = $Policy.EnableTeamCall
$VoicePolicySheet.Cells.Item($CurrentRow,10) = $Policy.EnableCallTransfer
$VoicePolicySheet.Cells.Item($CurrentRow,11) = $Policy.EnableCallPark
$VoicePolicySheet.Cells.Item($CurrentRow,12) = $Policy.EnableMaliciousCallTracing
$VoicePolicySheet.Cells.Item($CurrentRow,13) = $Policy.EnableBWPolicyOverride
$CurrentRow = $CurrentRow + 1
}
}
Write-Host "**Done with Voice Policies Sheet**"
 
#Configure layout for Trunks Sheet
Write-Host "**Building Trunk Sheet**"
$TrunkSheet.Cells.Item(1,1) = "Trunk Name"
$TrunkSheet.Cells.Item(1,2) = "Trunk Identity"
$TrunkSheet.Cells.Item(1,3) = "Scope"
$TrunkSheet.Cells.Item(1,4) = "Rule"
$TrunkSheet.Cells.Item(1,5) = "Rule Description"
$TrunkSheet.Cells.Item(1,6) = "Concentrated Topology"
$TrunkSheet.Cells.Item(1,7) = "Enable Bypass"
$TrunkSheet.Cells.Item(1,8) = "Enable Refer Support"
$TrunkSheet.Cells.Item(1,9) = "SRTP Mode"
$TrunkSheet.Cells.Item(1,10) = "Max. Early Dialogs"
$TrunkSheet.Cells.Item(1,11) = "Pattern"
$TrunkSheet.Cells.Item(1,12) = "Translation"
$CurrentRow = 2
 
#Import XML data into Excel fields.
$TrunkGroup = @($VCFGXML.Datasource.Trunks.Datasource)
ForEach ($Trunk in $TrunkGroup){
Write-Host "Found Trunk: " $Trunk.Name
ForEach ($Rule in $Trunk.Rules.Datasource){
Write-Host "Importing Rule: " $Rule.Name
$TrunkSheet.Cells.Item($CurrentRow,1) = $Trunk.Name
$TrunkSheet.Cells.Item($CurrentRow,2) = $Trunk.Identity
$TrunkSheet.Cells.Item($CurrentRow,3) = $Trunk.Scope
$TrunkSheet.Cells.Item($CurrentRow,4) = $Rule.Name
$TrunkSheet.Cells.Item($CurrentRow,5) = $Rule.Description
$TrunkSheet.Cells.Item($CurrentRow,6) = $Trunk.ConcentratedTopology
$TrunkSheet.Cells.Item($CurrentRow,7) = $Trunk.EnableBypass
$TrunkSheet.Cells.Item($CurrentRow,8) = $Trunk.EnableReferSupport
$TrunkSheet.Cells.Item($CurrentRow,9) = $Trunk.SRTPMode
$TrunkSheet.Cells.Item($CurrentRow,10) = $Trunk.MaxEarlyDialogs
$TrunkSheet.Cells.Item($CurrentRow,11) = $Rule.Pattern
$TrunkSheet.Cells.Item($CurrentRow,12) = $Rule.Translation
$CurrentRow = $CurrentRow + 1
}
}
Write-Host "**Done with Voice Policies Sheet**"
 
 
 
 
 
#Make Excel visible to the user.
$ExcelApp.Visible = $True
$Workbook.SaveAs($CurrentDirectory + "\" + $ExcelFileName)
 
#$ExcelApp.Quit()

Now open up a powershell command window and navigate to the directory with the .ps1 file and .vcfg file and run the following command:


.\LyncVCFGConverter.ps1 CustomerA_Lync.vcfg


LyncVoice - PS command


The script will extract the data and create an Excel spreadsheet.  The progress is shown as the script is running:


LyncVoice - PS command execute-markup


Once the script is complete, the Excel spreadsheet will be saved and launched.  You will notice that the spreadsheet is divided into different tabs:


LyncVoice - Excel - markup


Here are some examples from some of the other tabs…


Voice Policies:


LyncVoice - Excel -policies - markup


Trunk Configuration:


LyncVoice - TrunkConfig - markup


Hopefully this will help you out on documenting your Lync Voice configurations!  Again, thanks to Chris Cook for the heavy lifting on the powershell scripts.