MAdCaP.ps1 – A GUI for Lync Analog Devices & Common Area Phones

Creating and administering Analog Devices and Common Area Phones in Lync is sometimes a little tedious. I have a terrible record for forgetting to assign a PIN to Common Area Phones…

Inspired by a customer (and to the horror of a purist peer) I’ve created a PowerShell script that provides a GUI for the administration of both. I give you “MAdCaP.ps1” – short for “Manage Analog Devices & Common Area Phones”.

MAdCaP-1.7-New MAdCaP-1.8-Existing

(Click on the image for a life-size version)


  • Easily Create a new Analog Device or Common Area Phone, and optionally grant the relevant policies and PIN at the same time
  • Grant a Dial Plan, Voice Policy, Client Policy and/or User PIN to one or many already existing devices with a few clicks
  • Set a default OU to speed the creation of new objects and the editing of existing ones
  • Remembers your last-used Registrar Pool and SIP Domain – great for large (global) deployments with many pools and SIP domains
  • View the config of an existing Analog Device or Common Area Phone, and scrape it to the clipboard. (I use this a LOT – I copy the OU of an existing object prior to creating a new one)
  • Basic validity checks: the GO button won’t be enabled until the mandatory parameters contain ‘non-null’ entries
  • Comprehensive input constraints:
    • PIN and Line URI fields will only accept digits (the latter also permitting a “+”)
    • Display Name blocks the entry of restricted characters
    • SIP URI can only be numeric, alpha, or limited punctuation
    • OU and DN fields must contain at least “DN=”, etc
  • All communication with Lync/SfB is phrased within error handlers to prevent the script crashing on bad user-input or system errors
  • Log to screen and optional text file
  • Works with Lync 2010, Lync 2013 & Skype for Business 2015

Let me know in the Comments below if you think it’s screaming out for any other features, or if something’s broken when run against your deployment.


  • Your first visit to the Existing Object tab might be quite slow if you have a VAST deployment with lots of existing objects. Once you’ve set a default OU deeper into the forest (click the Browse button!) it will load much faster
  • If you’re creating a New device there’s usually a brief but noticeable lag between its creation and being able to then retrieve it and Grant policies. I’ve incorporated some handling that’s meant to cater for this, but if you strike any problems, just click to the Existing tab, Refresh, select your new device (which should have appeared by now), then re-apply the Policy settings
  • Related to the above, it seems it’s not possible to set a PIN straight after creating a new Common Area Phone. (Others – here and here – have tried and hit the same obstacle). The work-around is as per above
  • The “user-proofing” is comprehensive but not perfect. It’ll capture errors to the on-screen log and optional text file if you’re caught doing anything naughty (like specifying a name or number that’s already in use, or a bad OU)
  • If you name your new device “Error” it’ll falsely trigger the error-handling & derail the script
  • It won’t delete objects, or change the parameters of existing ones (beyond the policies, PIN & potentially the DisplayName). I made a deliberate decision to omit the Remove functionality, and in so doing limiting the damage that someone could do if they were having a bad day

Revision History

6th June 2020: Updated the Download link to point to GitHub.

v2.1 – 9th June 2018

  • Rearranged calls to “handler_ValidateGo” to fix where the Go button wasn’t lighting/going out
  • Corrected errors in the New Object DN and OU popup help text

v2.0 – 29th April 2018

  • Incorporated my version of Pat’s “Get-UpdateInfo”. Credit:
  • Added test for AD module to prevent re-loading unnecessarily
  • Suppressed lots of “loading” noise from verbose output with “-verbose:`$false”
  • Stripped the “Tag:” name from the start of the relevant policies (kinda redundant, and was getting in the way of below)
  • Updated the Existing Objects tab: the Policies update in real-time to show the selected object’s values
  • Replaced the “Browse” button on the Existing Objects tab with a new “Filter” button and form
  • Improved efficiency:
    • The “Refresh” button on the Existing items tab (function “Update-DeviceList”) now reads ADs & CAPs into separate global arrays
    • “Update-Display” now just reads the item directly from the relevant array rather than re-querying
    • “Update-DeviceList” no longer fires if the user Cancels or makes no change on the OU / Browse form
    • “Grant-Policy” now checks the existing and new policy values & skips the commands that would make no change
  • Peppered “write-progress” throughout the loading process to help debugging
  • Added handling for “-debug” switch for in-depth debug display
  • Corrected tab order on the Existing items tab
  • Added “-ShowExisting” switch so you can launch with that tab selected

v1.9 : 29th September 2017.

  • Fixed bug where selecting the “Existing Objects” tab on launch (without doing anything else) didn’t pick up the default.

v1.8 : 22nd September 2017.

  • Added the OU picker to the “Existing Objects” tab
  • Added a “Select & Make Default” button to the OU picker & associated code to save/read config
  • Saved the chosen RegistrarPool & SIPDomain to the new config file
  • Corrected minor whoops: the OK message after creating a new device referenced the “Existing Item” tab but it’s correctly the “Existing Object” tab
  • Revised OU TextBox & DN TextBox to remove the code that moves the cursor to the end of the line with every character
  • Neatened OU TextBox & DN TextBox to remove duplicate calls to handler_ValidateGo

v1.7 : 27th June 2017. MAJOR UPDATE / REFRESH!

  • Added the “OU” picker stolen from Anthony Caragol’s brilliant Lync_Common_Area_Phone_Tool_v1_2.ps1
    – (
    – Added the “sticky” enhancement so it opens to the previously selected OU. Tip: Copy/Paste from an Existing object on the other tab!
  • Rearranged the tabs: Policies are now only visible for Existing objects
    – (timing problems caused real headaches trying to set a Policy or PIN when you initially create the object)
  • Disabled the PIN text box on the “Existing Object” tab if you’ve ONLY selected an Analog Device
  • Enabled “DN” for AnalogDevices (previously not an option – was that old Lync 2010 behaviour or a coding error?)
  • Script now lets you specify a DN and an OU – an invalid pairing – but will disregard/ignore the OU & use the DN
  • Changed script to (re)populate the AD & CA phone lists each time you select the “Existing Item” tab – where it previously did this on script load
  • When an object is created on the New tab and you select the Existing tab the script now pre-selects that object (if it exists when we query for it)

    – if it doesn’t and you press Refresh, it will auto-select the object just created

  • Added a popup MsgBox to indicate success/fail after creating an object on the New tab
  • Added “-warningaction silentlycontinue” liberally to suppress the yellow that sprays in the underlying P$ window if you’ve been deleting policies, etc that are still assigned to users or devices

v1.6 : 1st March 2016.

  • Added Location Policy to the policies you can set. (Thank you @JohnACook)

v1.5 : 28th Dec 2014.

  • Signed script (thanks DigiCert!). Changed “$objNewDisplayNumberTextBox.add_TextChanged” to accept a dash as valid

v1.4 : 1st Nov 2013.

  • Added quotes around Gateway, Line URI & PIN before sending them to Lync

v1.3 : 11th June 2013.

  • Corrected bug where I was incorrectly sending “DN=” instead of “CN=” to create a CommonAreaPhone referencing an existing object

v1.2 : 26th April 2013.

  • Added quotes around registrar in “$objGoButton.Add_Click” as an FQDN with ‘-‘ was being rejected and raising errors

v1.1 : 5th March 2013.

  • I’ve revised the regex rules to permit the “;ext=” suffix on the Line URI. (Thanks Andy for pointing out my oversight)


You’ll find a code-signed version of the script on GitHub. You’re welcome to pinch, adapt or improve upon the code with my blessing. If you encounter any problems with it please create an issue on the repo.


Thanks to all who contributed to the above.



  1. Hey Greig— great to meet you this week. I’ve been looking over your script as I am trying to start working on a few GUI’s of my own and I noticed an issue… your line URI field doesn’t all extensions! the tel:+XXXXXXXXXXX;ext=XXXX format is pretty common here in the states. Maybe a regex tweak is in order? Love the script otherwise though. Thanks for sharing

  2. I love this script, it means the service desk can administrate these phones, which is always a good thing!

    Just an FYI there’s a bug in the Display number when creating a common area phone. If you put in “(111) 222-3333”, the display number will come out as (111) 2223333 without the hyphen. Since this is the standard format in the States it’s a pretty necessary thing.

    • Hi Dan,

      Are you after more than what’s on the “Existing Object” tab (the RH image up the top of the post), or have you encountered a catastrophic bug where that tab yields no results?

Leave a Reply

Your email address will not be published. Required fields are marked *

... and please just confirm for me that you're not a bot first: Time limit is exhausted. Please reload the CAPTCHA.

This site uses Akismet to reduce spam. Learn how your comment data is processed.