An Administrator’s First Look at PowerShell in Lync Server 2010 (Communications Server ’14’)

With Communications Server "14" on the horizon and promising extensive support for PowerShell, you'll need to know what works and what doesn't, and how to find out more. Desmond Lee gives a distilled overview of what you'll need to know.

The full feature-set of Communications Server “14” was officially announced during the keynote at TechEd North America 2010 in New Orleans. While a lot of enthusiasm was focused on the many new enhancements to functionality and productivity, which are visually captivating for end-users, many IT administrators were equally keen to learn more about the management of their Unified Communications environment with the new Communications Server Management Shell.

This article provides a distilled-yet-comprehensive first look at this exciting opportunity to put your PowerShell knowledge to good use in CS “14”. It assumes that you already have at least a basic understanding of Windows PowerShell, and is written based on the CS “14” beta milestone. As the contents of CS “14” are still evolving, bear in mind that there will likely be changes between the beta release and the final release to manufacturing (RTM) version.

Communications Server “14” or more commonly Wave 14, is now officially re-branded to Microsoft Lync 2010 to unify, “link” and “sync” the various ‘OCS’ products and services together. You can read more about this official announcement here.

A Little Bit of History

PowerShell v1.0 was publicly released to the web as a free download in November 2006. Available for Windows XP SP2, Vista SP1, Windows Server 2003 SP1 and Windows Server 2008, its only dependency is the .NET Framework version 2.0. This must be separately downloaded for older machines, and ships with newer Windows operating system from Windows Vista SP1 and up. The initial release of Office Communications Server 2007, as well as Release 2, didn’t include native PowerShell cmdlet support, and neither do previous versions of Windows OS or enterprise applications like Exchange 2003.

Nevertheless, the previously mentioned platforms come packaged with a rich set of functionality in the form of Windows Management Instrumentation (WMI), since Windows 2000. This technology exposes a common, unified programming interface for virtually all aspects of Windows management imaginable to an IT administrator. That doesn’t mean that PowerShell users can’t get their hands dirty tinkering with these platforms by tapping into WMI. In the traditional spirit of PowerShell one-liners, Get-WMIObject is the cmdlet you will use to manipulate WMI classes and objects (or its gwmi alias). It’s one of the few cmdlets which is designed to execute against a remote machine that relies on the .NET Framework’s remoting functionality, and naturally, it works just as well on the local machine.

“Communications Server “14”, known affectionately as Wave 14, is coming to a Windows server near you […] with the long-awaited PowerShell support…”

Although you can quickly get up to speed in your PowerShell scripting by consulting the excellent built-in Help database or Get-Member cmdlet, finding the right WMI method, object property or attribute can be a real pain e.g. how do I determine which WMI class actually contains the right attribute that corresponds to a user’s URI? To fill this gap, several applications, most of them free, can be used to ease the development of solutions based on WMI by discovering the necessary attributes. Some examples are SAPIEN’s WMI Explorer (free, and part of PrimalScript), Windows Management Instrumentation Tester (WBEMTest), the WMI Administrative Tools or WMIExplorer (

Of course, instead of building your own WMI solutions from scratch, you can deploy a handy PowerShell script named OCS-r2.ps1, which relies extensively on Get-WMIObject and is available as part of the OCS 2007 R2 Resource Kit. Supplementing this with the OCS PowerPack will reduce your learning curve, and have you quickly building and rolling out PowerShell-based scripts in your organization. Bear in mind that for this PowerPack to work, you’ll need to install PowerGUI beforehand; thankfully, both the GUI and the PowerPack  are gratis and downloadable from Quest Software. You can read up on a recent TechNet Next Hop article “Ten Steps to PowerShell Scripting with Office Communications Server 2007 R2” to learn more about using WMI in PowerShell.

Fast forward to the year 2010 and Communications Server “14”, known affectionately as Wave 14, is coming to a Windows server near you. With it, the long-awaited PowerShell support finally debuts and WMI formally ceases to exist in the product. As of this writing, the official stand is that the cmdlets are designed to work with CS “14” only (i.e. backward compatibility is not supported). If you scan the inline Help documentation, certain cmdlets describe their suitability for use with previous product versions. Such cmdlets exist primarily to assist the IT administrator to migrate from OCS 2007 R2 or deal with basic user account administration, so you’ll have to continue using Get-WMIObject and building occasionally cryptic SQL statements via the WQL query language to properly administer OCS 2007 (RTM and R2) with PowerShell. Until the final release, we shall have to wait to see the extent to which the new PowerShell cmdlets can be applied when you are using older versions of OCS.

PowerShell in CS “14”

Let’s take a quick look at the administration and management of CS “14”. With over 500 cmdlets ready to ship in the product, product management coverage is very extensive and amazingly impressive for the initial release of native PowerShell support in the CS Management Shell. The sole pre-requisites are at least .NET Framework 2.0 and v2.0 of PowerShell (although Out-Gridview and a few other cmdlets require .NET Framework 3.5 or above). As you read around the subject, you may come across the term “Windows Management Framework” (KB968929), which is actually comprised of Windows PowerShell 2.0, Windows Remote management 2.0 (WinRM) 2.0 and Background Intelligent Transfer Service 4.0 (BITS). These components must be separately downloaded and installed for supported Windows versions prior to Windows 7, but will be automatically included as part of the installation of any CS “14” server roles or the new management and administration tools on more recent OS versions.

The adoption of PowerShell for management in CS “14” closely mirrors that of Exchange Server 2007/2010; in short, all the graphical user interfaces are driven by PowerShell. Hidden in the background, CS PowerShell taps into the new Central Management Store (CMS) which contains key pieces of information regarding topology, configuration settings and policies. To maintain backward compatibility with OCS 2007, R2 and third party applications, most user account attributes, including Service Control Points (SCP), remain stored in the Active Directory configuration and domain partitions.

“…despite the shiny new Silverlight 4.0 web-based Communications Server Control Panel (CSCP for short), you’ll find yourself often going back to the CS Management Shell to administer your CS infrastructure.”

Your first encounter of CS PowerShell in action is when you run the CS “14” setup during the AD preparation steps, where the relevant cmdlets and full syntax will be shown when the process actually begins. You can even skip the graphical setup entirely and utilize the CS PowerShell cmdlets right away if you know what you’re doing. Unlike the implementation in Exchange, you will not see the resulting PowerShell cmdlets and parameters exposed after clicking through the wizards to, for instance, Cs-enable an existing AD user. The product group has heard this feedback loud and clear, although there is no guarantee that this will change in the final release.

Modules are a new feature of Windows PowerShell v2.0; a module is where all items associated with a product such as Communications Server “14” reside (help files, cmdlets, functions, etc.). The CS “14” module is named OCS, and is automatically pre-loaded whenever you start the CS Management Shell. Somewhat similar to how a typical PowerShell snap-in works, you can manually introduce the OCS and other unrelated modules to your session using the Import-Module cmdlet. To find out which modules are loaded in a PowerShell instance, you can run the cmdlet that goes by the intuitive name of Get-Module.

It’s worth mentioning  that despite the shiny new Silverlight 4.0 web-based Communications Server Control Panel (CSCP for short), you will find yourself often going back to the CS Management Shell to administer your CS infrastructure. In fact, a number of settings can only be carried out using the shell; a prime case is the new E9-1-1 service for the North American market.

Getting Help

The sheer number of PowerShell cmdlets available means that it can prove to be a challenge for an administrator to discover the ones that are specific to CS “14”. Fortunately, the CS PowerShell team has adopted the convention of prefixing all nouns in a cmdlet with Cs (e.g. Get-CsUser). As a result, one way to locate them is to use the command Get-Command -noun cs*; you’ll quickly find that this returns not just cmdlets, but a bunch of functions in the current PowerShell session as well.



Set-CsNetworkSubnet [[-Ident…
Set-CsPinPolicy [[-Identity]…
param([Parameter(Mandatory =…
Set-CsPresencePolicy [[-Iden…
Set-CsPrivacyConfiguration […
Set-CsProxyConfiguration [[-…
Set-CsPstnGateway [[-Identit…

Table 1: Get-Command -noun cs*

The bad news is that you cannot combine this with the -commandtype parameter to filter out the results just to items categorized as cmdlets; this command will throw an error: Get-Command * -commandtype cmdlet -noun cs*. You can find a workaround using the Where-Object described later in this section.

By far the single most effective means to determine the complete list of CS “14” cmdlets is to use the construct Get-Command -module OCS. The -module OCS parameter tells the PowerShell cmdlet to restrict operations to the commands imported as a part of the Communications Server module. Such a mechanism helps prevent the possibility of namespace crash with other PowerShell cmdlets installed on your system. In contrast, the 2007/2010 versions of Exchange and Data Protection Manager provide tailor-made cmdlets to produce just product-specific cmdlets i.e Get-Excommand and Get-DPMcommand.

To learn about the distinctive objects that you can operate on, you can execute the PowerShell command in the CS Management Shell as illustrated:

You can further limit your scope to specific words found anywhere in the noun of a cmdlet, like this:

Once you obtain the desired cmdlet listing, it is a simple matter of tagging on familiar PowerShell verbs such as Get, Set, Remove, etc. to perform an action on the items of interest (objects) e.g. Remove-CsPhoneUsage. Having said that, take note that there is not always a matching verb for each cmdlet. Get-CsUser is one such CS “14” cmdlet without a New-CsUser or Remove-CsUser counterpart. For more information on the variations of cmdlets, take a look at the “Field Guide to CS ’14’ Cmdlets“.

Table 2: Get-Command -module OCS | Select-Object -unique noun

Identity and Scope

Communications Server “14” Scopes




Configuration settings or policies that will be applied to the entire Communications Server infrastructure (location agonistic) referenced using the global reserved keyword.


Maps to physical locations that are geographically separated using the site reserved keyword e.g. Zurich, Singapore and Redmond. Machines in a site are usually connected in a high-speed, low-latency network. The concept of a CS “14” site is not quite the same as that of an Exchange 2003 site or Active Directory site (although there are similarities), and clarifying that subtle distinction is unfortunately outside the scope of this article.


Represents a Communications Server service role that can be served by one or more computers setup in a pool, e.g. Registrar and User Services. You can roughly equate this to an Office Communications Server 2007 R2 pool, where all machines in the pool (CS service role) must share the same settings described at the service scope.


Refers to deploying Communications Server as a service in the cloud; this is a reserved keyword and is currently not supported by CS PowerShell in CS “14”.

Tag (or

Direct application of policies at a per-user or group of users scope with tag as the reserved keyword (optional). Without the tag or global keyword used as the identity, CS “14” will always default to the per-user scope.

Scope works in such a way that the nearest policy or configuration setting always takes precedence. That is to say, settings at the per-user scope will always “overwrite” similar ones defined in the service, site and global scope level, in that order. No conflicting equivalents at the global scope can be created nor can the default ones, which are always created during the installation of CS “14”, be deleted. However, a global configuration setting or policy can be always modified by an IT administrator.

CS PowerShell cmdlets share many common parameters that you can uniformly apply pretty much across the board. For instance, you need to know that the -Identity property enables the cmdlet to correctly bind to a specific entity or object in CS. This can be any CS “14” object, such as a regular user account (which is taken as an object in its entirety, so SamAccountName, SIP address, etc. can all be used to identify it), AD security group, the name of a CS “14” Registrar Pool (Front-End server) or a conferencing policy. To uniquely pinpoint a scope in CS, you prelude the identity with the global, site, service or tag keyword, follow by a colon (:). See the sidebar for a description of these new terms introduced in CS “14”.

Let us start off with an example to illustrate the concept of scopes. The command New-CsConferencingConfiguration -identity “site:ch_zurich” creates a new conferencing configuration at the site scope with the name ch_zurich. The end result is that the entire CS “14” environment that is linked to ch_zurich will automatically “inherit” whatever settings that an administrator defines at this particular site. It is important to realize that at the site and service level, changes are immediately assigned to the site or service scope upon successful execution of the cmdlet.

Here’s another example, this time for creating a policy. The New-CsConferencingPolicy “ch_confPolicyExec” statement will automatically build a new policy at the per-user scope, where the identity is fully described as tag:ch_confPolicyExec internally. As mentioned in the sidebar, without a prefix or the global keyword, the -identity property in a policy cmdlet (and never a configuration cmdlet) will always imply the per-user scope, I’ll explain the reason for this shortly (it boils down to the difference between a configuration and a policy in CS “14”). The point of this example is that, as an administrator, you have to manually assign such a policy to one or more users in a separate step.

The New-CsConferencingPolicy cmdlet additionally supports creation of a conferencing policy at the site level; meaning that adding the site: prefix will do the trick. Nonetheless, any attempt to create a new policy at the global scope will fail, as that will generate an impermissible conflict (see the earlier sidebar). All this talk on scope can cause quite a bit of confusion, so to establish exactly which scope is applicable to a cmdlet, always consult the inline help with the -full or -detailed parameter.

In practice, you can usually leave out -Identity, since any value supplied immediately after the cmdlet name is position-aware i.e. it is assumed to target the first parameter (-Identity). As you would imagine, calling a “Get” type of CS PowerShell cmdlet alone by itself without any parameters will generally return you a list of matching results. For example, running Get-CsConferencingPolicy will retrieve all the conferencing policies defined across available CS scopes. Conversely, “Set” cmdlets will automatically modify just the global configuration settings or policies in the absence of an identifier. In other cases, CS PowerShell will display a prompt to solicit information, so as to clearly make out the intended identity for cmdlets like Grant-CsVoicePolicy.  If you have been asking yourself what clearly differentiates between policies and configuration settings, keep reading or jump straight to the sidebar for a quick explanation.

PowerShell has in-built support for the asterisk (*) and question mark (?) wildcards, so you may be tempted to try to be creative with the use of wildcards in the value supplied to the -Identity parameter. Unfortunately, this is not a supported scenario for the use of the -Identity parameter. A command like Get-CsVoicePolicy global will show you the default voice policy at the global scope in Communications Server. Modifying it to Get-CsVoicePolicy g* will fail with an error similar to the following (how to get around this is described a bit later in the article).

An exception to this rule is the Get-CsUser and Get-CsAdUser pair of cmdlets. Specifying wildcards in the values supplied to their -Identity parameters is permitted e.g. Get-CsUser -Identity “d*”. The limitation here is that the search works only against the Displayname attribute and nothing else (even if they are valid user account identities, such as a SIP address).


Another basic cmdlet parameter you should get familiar with is -Filter, which, as the name implies, informs CS PowerShell to limit the query to the given search boundary. Most CS PowerShell cmdlets support filtering on an object’s identity, while others permit filtering on a wider variety of parameters. So, you can be as precise as Get-CsVoicePolicy global or you can go ahead with Get-CsVoicePolicy -Filter g* to get a broader range of results.

Admittedly, it remains possible to first retrieve the entire list before passing the resulting objects down the pipeline for processing by Where-Object, although using -Filter is recommended as it is optimized for better performance. Notably, Cs-specific attributes for user accounts do not work well with Where-Object (as I’ll explain in just a moment). Either way, this is how you can get around the wildcard constraint described previously. By the way, you can always filter on a CS scope by prefixing the identity with global, site, service or tag e.g. Get-CsLocationPolicy -Filter tag:*.

You should also understand that some cmdlets demand that the -Filter parameter obey the Where-Object filtering syntax instead of a simple bunch of characters that make up a string type. For example,  Get-CsUser -filter d* stops dead in its tracks, but Get-CsUser -filter { displayname -like “d*” } will work without any complaint. Still others may permit filtering on defined properties only (New-CsConferencingPolicy is one such cmdlet). Again, the only sure way is to consult the in-line Help to learn about the valid syntax.

There is at least one more parameter, called -LdapFilter, which you should familiarize yourself with. This filter is geared towards working with generic attributes found in all Active Directory user accounts (such as department and title). To effectively deploy this filter, you have to become conversant with the LDAP filter format. You can read “Retrieving Active Directory and Communications Server User Accounts” to appreciate how you can put this into action.

Management Essentials

The concepts of separate configuration settings and policies are brand new in CS “14”, and ones you should make sure you understand clearly given that, as a full-time system administrator responsible for your Windows environment, you are going to spend more than half of your time in the user management space. Changes at the global, site and service scope levels are seldom performed right after the setup and configuration phase for a new CS “14” server role deployment is completed, and will need to evolve in step with your organization. Tasks like the default Address Book server configuration and corporate-wide voice settings fall under this category, and are collectively referred to as “configuration settings” in CS.

However, in your daily operational and support role, you will mostly be setting policies that frequently apply at the per-user scope. When deployed in this fashion, they are (unsurprisingly) known as “per-user policies”. Like a configuration setting, a policy can potentially be applied at the global, site and service scopes. The key distinction is that only policies, and never configuration settings, can be pushed down to the per-user scope. More significantly, the application of settings to users and groups no longer happens through Group Policy for Cs-enabled users that are homed on the CS “14” infrastructure.

“By now, you must have guessed that you can indeed manage the entire CS “14” infrastructure through the CS Management Shell […] as long as you fulfill the prerequisites pointed out earlier.”

While there is no official classification of the various CS “14” Powershell cmdlets out of the box, you can easily deduce their purposes simply by searching for hints in the name. You will notice that the majority of the configuration settings and policies will actually contain the word configuration or policy in the noun part of the cmdlets. Set-CsMeetingConfiguration and New-CsConferencingPolicy are two examples. Still, you should keep a look out for exceptions that depart from this naming convention, such as Get-CsDialPlan (itself a type of policy). With the administrative tasks fully driven by CS PowerShell, this signals the end of having to fiddle with LCSCmd.exe at the command line for administrators in CS “14”.

In the course of user administration, you will work mainly with the pair of Get-CsUser and Get-CsAdUser cmdlets. Why two different cmdlets, you ask? Get-CsUser is designed primarily for managing accounts that are already enabled for Communications Server; CS specific attributes are “toggled on” for an account when it is Cs-enabled, and can only be retrieved via Get-CsUser, e.g. RegistrarPool. On the other hand, to inspect any Active Directory accounts, Get-CsAdUser is the right cmdlet to summon, regardless of whether an account is Cs-enabled or not. As you get to know the product, there will be ample situations where you need to combine these two cmdlets to obtain the results you are seeking for.

By now, you must have guessed that you can indeed manage the entire CS “14” infrastructure through the CS Management Shell, which is installed by default on all of the CS server roles (Front-End, Audio/Video server pool, etc.). As long as you fulfill the prerequisites pointed out earlier, including having x64 editions of Vista SP2 and above, the CS Shell can be installed on any administrative workstation in the domain.


In this article, you were introduced to several key new CS “14” concepts after walking through a brief history on Windows PowerShell and WMI management. You learnt about the global, site, service and per-user scopes, where you make configuration settings or apply policies to different object identities. You have also seen how to seek help and optimize administrative tasks by bringing in applicable filtering techniques. All this information, taken together, will prepare you to confidently deploy CS PowerShell in the management of your upcoming CS “14” infrastructure. Have fun!


Communications Server “14” PowerShell Blog:

TechNet Next Hop Technical Resources – Unified Communications:

Unified Communications Group Team Blog:

Microsoft Communications Server Technical Reference Hub:

Communications Server Team Blog:

Communicator Team Blog:

Windows PowerShell Blog:

Office Communications Server Forums: