Home > Lync Server/Skype for Business Server > Script: Get-CsUpdateVersion.ps1 – See the Cumulative Update Level Of All Lync/Skype for Business Servers

Script: Get-CsUpdateVersion.ps1 – See the Cumulative Update Level Of All Lync/Skype for Business Servers


My work at Modality Systems often has me doing health checks for customer Lync environments. These can be due to customer requests, or as part of our onboarding for new managed support customers. If you’ve ever had an Active Directory Risk Assessment Program (ADRAP) or Exchange Risk Assessment Program (ExRAP), it’s quite similar. Lots of tasks to run, lots of data to sift through. So it’s always beneficial to standardize and automate the steps to get the data. The same is the case when you’re responsible for your own environment and want to ensure good health.

Just like Get-CsDatabaseUpdateStatus.ps1, Dave Howe from the Lync product group and I teamed up to automate something. In this case, it’s looking at what Cumulative Updates are installed on each server throughout a Lync environment. This script queries each pool, then finds what servers are part of that pool, and queries each server to find the CU that’s installed. It then provides an easy to read output of the entire environment (with exceptions) for easy review. As shown below, we see three multi-server pools, the version number and “friendly” Cumulative Update info.

PS C:\> .\Get-CsUpdateVersion.ps1

ComputerName   : sjc-edge01
PoolFqdn       : sjc-edge01.contoso.com
Version        :
Product        :
Update         :
FriendlyResult : PSRemoting failure
UpToDate       :
UpdateUrl      :

ComputerName   : sjc-fe01
PoolFqdn       : sjc-fe01.contoso.com
Version        : 6.0.9319.272
Product        : Skype for Business Server 2015
Update         : CU4 - 11/04/2016
FriendlyResult : Skype for Business Server 2015 CU4 - 11/04/2016
UpToDate       : False
UpdateUrl      : http://support.microsoft.com/kb/3199093

ComputerName   : sjc-pc01
PoolFqdn       : sjc-pc01.contoso.com
Version        : 6.0.9319.272
Product        : Skype for Business Server 2015
Update         : CU4 - 11/04/2016
FriendlyResult : Skype for Business Server 2015 CU4 - 11/04/2016
UpToDate       : False
UpdateUrl      : http://support.microsoft.com/kb/3199093

The script works fine with Standard Edition servers as well.

In the first example, you see that the first two servers show “PSRemoting failure”. This is because the script uses PowerShell Remoting to connect to each remote server to query information (see installation notes below). PSRemoting doesn’t really work the same when dealing with non-domain joined machines, such as the first two, which are edge servers. So the script isn’t able to communicate with them via PSRemoting, and flags them. If the script can’t ping a server, it will show as “offline”. The friendly name of the CU shown is coded in the online XML file that the script queries. So I’ll update it each time a new CU is released.

By default, the script checks all pools. But you can specify a single pool by using the -PoolFqdn parameter.


Get-CsUpdateVersion.ps1 [[-PoolFqdn] ] [-WhatIf] [-Confirm]


This script uses PowerShell Remoting to query remote servers. PSRemoting is enabled by default on Windows Server 2012 and later, but disabled by default on 2008 R2. To enable PSRemoting on 2008 R2 servers, see Enable-PSRemoting. The script requires Internet access on the machine the script is running on. This is to query the XML file containing the update information.

Execution Policy: Third-party PowerShell scripts may require that the PowerShell Execution Policy be set to either AllSigned, RemoteSigned, or Unrestricted. The default is Restricted, which prevents scripts – even code signed scripts – from running. For more information about setting your Execution Policy, see Using the Set-ExecutionPolicy Cmdlet.


I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.




v3.9 – 03-08-2017 – Get-CsUpdateVersion.v3.9.zip

v3.8 – 02-14-2017 – Get-CsUpdateVersion.v3.8.zip

v3.7 – 02-05-2017 – Get-CsUpdateVersion.v3.7.zip

v3.6 – 01-06-2017 – Get-CsUpdateVersion.v3.6.zip

v3.5 – 11-28-2016 – Get-CsUpdateVersion.v3.5.zip

v3.4 – 11-12-2016 – Get-CsUpdateVersion.v3.4.zip

v3.3 – 08-31-2016 – Get-CsUpdateVersion.v3.3.zip

v3.2 – 07-15-2016 – Get-CsUpdateVersion.v3.2.zip

v3.1 – 07-05-2016 – Get-CsUpdateVersion.v3.1.zip

v3.0 – 04-21-2016 – Get-CsUpdateVersion.v3.0.zip

v2.9 – 04-07-2016 – Get-CsUpdateVersion.v2.9.zip

v2.8 – 01-26-2016 – Get-CsUpdateVersion.v2.8.zip

v2.7 – 12-14-2015 – Get-CsUpdateVersion.v2.7.zip

v2.6 – 11-17-2015 – Get-CsUpdateVersion.v2.6.zip

v2.5 – 11-11-2015 – Get-CsUpdateVersion.v2.5.zip

v2.4 – 10-03-2015 – Get-CsUpdateVersion.v2.4.zip

v2.3 – 09-09-2015 – Get-CsUpdateVersion.v2.3.zip

v2.2 – 07-14-2015 – Get-CsUpdateVersion.v2.2.zip

v2.1 – 06-21-2015 – Get-CsUpdateVersion.v2.1.zip

v2.0 – 05-12-2015 – Get-CsUpdateVersion.v2.0.zip

v1.9 – 02-19-2015 – Get-CsUpdateVersion.v1.9.zip

v1.8 – 02-09-2015 – Get-CsUpdateVersion.v1.8.zip

v1.7 – 01-01-2015 – Get-CsUpdateVersion.v1.7.zip

v1.6 – 12-12-2014 – Get-CsUpdateVersion.v1.6.zip

v1.5 – 11-21-2014 – Get-CsUpdateVersion.v1.5.zip

v1.4 – 09-24-2014 – Get-CsUpdateVersion.v1.4.zip

v1.3 – 09-02-2014 – Get-CsUpdateVersion.v1.3.zip

v1.2 – 08-07-2014 – Get-CsUpdateVersion.v1.2,zip

v1.1 – 06-02-2014 – Get-CsUpdateVersion.v1.1.zip

v1.0 – 05-02-2014 – Get-CsUpdateVersion.v1.0.zip


See the changelog for information on what’s changed/included in each version.

  1. May 6th, 2014 at 09:12 | #1

    Thx Pat for your effort, it was a good solution

  2. May 7th, 2014 at 03:42 | #2

    Fantastic as always Pat. Thanks a ton.

  3. davidchr
    May 16th, 2014 at 11:17 | #4

    Another great tool for Lync admins! Im seeing an issue though…all of my servers in the edge pool are showing the following: fqdn of server (offline)
    I checked execution policy and its remotesigned. The Edge server’s OS is 2012 and they are in the DMZ. We used the following http://technet.microsoft.com/en-us/library/gg398739.aspx to open the necessary ports to/from the edge servers and between edge and fe boxes. Any ideas?

    • Pat Richard
      May 16th, 2014 at 22:58 | #5

      It’s not likely going to work with Edge servers, as their is no AD authentication to those machines.

  4. Andy G
    May 20th, 2014 at 23:52 | #6

    If you have newer Debugging Tools or Resource Kit it detects those as the current version. Perhaps you should only look at the Core Components program as that should always reflect the latest installed version?

    • Pat Richard
      May 30th, 2014 at 11:20 | #7

      That’s being addressed in the new version, as is a quirk around Lync Server 2010.

  5. Mickael B
    August 13th, 2014 at 09:43 | #8

    Great script !
    For the 2013 Edge server, you could use the output of “Get-CsManagementStoreReplicationStatus” to get the “ProductVersion”, which is not very elegant, but should do the trick (at least for 2013)

    • Pat Richard
      August 16th, 2014 at 01:39 | #9

      The problem with that is it’s also not accurate. If you have post CU patches installed, Get-CsManagementStoreReplicationStatus just shows the version to the CU – not to any post CU patches.

      • Brian Longoria
        August 28th, 2014 at 17:13 | #10

        Yep – that’s what led me here. Had all CU 5 updates, and repstatus was still returning .556- I got concerned why there was a difference. Still haven’t found why, but at least this script, plus server control panel\product version and the CU.exe. three confirmations makes me feel a lot more secure. Thanks for the script.

  6. Andrew Burt
    February 24th, 2015 at 20:17 | #11

    Cheers Pat! Script much appreciated!

  7. Dhivya
    March 12th, 2015 at 04:15 | #12

    Great script and working well, is there any option to export the result in CSV file?

    • Pat Richard
      March 12th, 2015 at 06:44 | #13

      Not at this time.

  8. David Paulino
    April 12th, 2015 at 06:57 | #14

    Pat, thanks for this great script.
    I notice that in your script you have “5.0.8308.871”= “Lync Server 2013 CU11 – Feb. 19, 2015”, but if you download and install the latest CU it will go to “5.0.8308.872”.

    • Pat Richard
      April 17th, 2015 at 00:49 | #15

      I’ve requested clarification on this. The original file was .871, and the KB and updates pages still refer to .871. But the file that’s downloaded is .872. As soon as I get some more info, I’ll pass it along.

  9. Martin Boam
    May 12th, 2015 at 05:45 | #16

    Hi Pat, Thanks for the great Script as always! I used against Lync Server 2010 yesterday and I noticed that for 4.0.7577.710 it stated Lync Server 2010 CU15 – Dec. 2015. Wondered if this should be Dec 2014.

    • Pat Richard
      May 12th, 2015 at 08:03 | #17

      Yeah, that’s fixed in the next version.

  10. May 13th, 2015 at 11:43 | #18

    Fantastic script Pat! Worked like a charm and saved me time. Thanks. (it didn’t pick up my 2 Mediation Pools but they were co-located on my 2 Enterprise Front-End pools so it didn’t really matter)

  11. Bernard Dejonckheere
    August 12th, 2015 at 05:52 | #19


    great script.
    I would suggest you added folowing code:
    new-> $FriendlyResult=”Unknown Version”
    switch ([string] $version) {

    • Pat Richard
      August 14th, 2015 at 10:19 | #20

      Thanks for the idea. I’ve got it queued for v2.3.

  12. shane negaard
    February 21st, 2016 at 04:47 | #21

    if you have a copy of the HP 4120 December 2012 cumulative update. 4.0.7577.4366 I would like to get a link to download it.
    I need to roll back to that version in order to fix a nagging issue that was uncovered when I updated to the latest release.
    I have a open case with Microsoft, but they do not offer previous versions of those cumulative updates.
    only the most current one online.
    I had 1 phone with the older version that does not have the issue, but I do not have the CU to import and roll back my phones.
    if anyone has a copy, please reply with a link.

  13. Ryan Patridge
    February 25th, 2016 at 13:06 | #22

    Thanks, great script, Pat!

    Minor problem with version 2.8 – 01-26-2016: the script #Requires -Version 2.0, but Powershell 2.0 doesn’t support CmdletBinding directives or Parameter decorators with null arguments (ie. lacking the “=” operator with an assigned value). Running it in Powershell 2.0 yields the following error message:

    The “=” operator is missing after a named argument.
    At D:\Scripts\PS\Get-CsUpdateVersion.ps1:48 char:38
    + [CmdletBinding(SupportsShouldProcess) <<<< ]
    + CategoryInfo : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : MissingEqualsInNamedArgument

    I quickly "fixed" this by adding "= $false" to all of the unassigned arguments specified in various CmdletBinding directives and Parameter decorators in the script. Some of them might be better set to "$true", but I'm not sure, and lack the cycles to do testing. All the same, after making this "fix", it worked great for me in Powershell 2.0. Thanks again.

  14. Matthew
    April 22nd, 2016 at 13:54 | #23

    Love the script! Just curious why my FE servers show [Lync Server 2013 Post CU5] and not a definite CU version like your screenshots. Any thoughts?

    • Pat Richard
      April 22nd, 2016 at 15:30 | #24

      Because you have a post CU5 update installed. Your version number likely is 5.0.8308.803

  15. Tony Hart
    August 29th, 2016 at 15:28 | #25

    Has it been updated for the August 2016 CU?

  16. Pat Richard
    August 29th, 2016 at 15:31 | #26

    I’m assuming you mean the Lync Server CU for August. Not yet. Should be online in the next day.

  17. Pat Richard
    August 31st, 2016 at 13:42 | #27

    @Tony Hart
    New version is now available

  18. soder
    October 25th, 2016 at 09:15 | #28

    Hello Pat,
    does your script analyze all the components that are available as part of a Cumulative Update package, or is limited only to the FrontEnd patch / Core components patch? I am trying to validate the job done by operations people in order to see all update packages have been installed by them correctly, or they missed some of them.

  19. Robert
    January 12th, 2017 at 07:58 | #29

    Great script, but it does not work on edge servers that are not in a domain.
    “Get-CsService : Cannot find information about the local domain”.

    Is there a way to get the version on Edge servers?


  20. Phil Meyer
    January 13th, 2017 at 14:31 | #31

    Hello Pat,

    I stumbled upon your script while searching for a way to determine Lync version information. Thank you so much for your time and expertise on this and many other subjects!

    I think you should know that the current version of the script, 3.6, is still labeled 3.5 and also asks if you want to download a new version. I changed the following value and it no longer asks, but you might want to make sure the correct version is in your ZIP file. 🙂

    Thanks again!

  21. soder
    February 15th, 2017 at 10:45 | #33

    Hello Pat,

    // trying to clarify 1 more time //
    does your script analyze all the components that are available as part of a Cumulative Update package, or is limited only to the FrontEnd patch / Core components patch? I am trying to validate the job done by operations people in order to see all update packages have been installed by them correctly, or they missed some of them.

    • February 20th, 2017 at 16:21 | #34

      So, it takes a look at the related items shown in Add/Remove programs that have “Microsoft Lync Server”, “Microsoft Office Web Apps Server 2013”, or “Skype for Business Server”, and filters out “Debugging Tools”,”Resource Kit Tools”,”Best Practices Analyzer”, and “Meeting Room Portal”. It then takes the highest version number of what’s left, which should be just the related components. It’s not perfect, but I generally don’t see issues.

      If your operations people are are using the ServerInstaller.exe file to do the upgrade, then you should be fine.

      • sodet
        March 3rd, 2017 at 23:48 | #35

        Thanks Pat for clarification. Thats what I thought actually as well (having my improving but still basic PS knowledge). Reason I was asking because had some recent “whoops” moment, when ops people forgot(?) to actually deploy the RGS part. I was somehow lazy at 1st time to validate their job, and only run this script to confirm the patch-level, and it looked fine (I was too optimistic about the check and moved on). But when our well-known RGS bug was still present on the pool, I had to do a manual investigation, and realized they missed the RGS for some damn reason. For 1st look I thought the script was taking care of all the patchable server components, similar to the serverupdateinstaller wizard table that collects all current-vs-after version numbers, with green check marks and read crosses etc that correlates to a certain CU release. Don’t get me wrong, million kudos to your job, just now I know the proper expectation that I set when checking pool patch level next time. Once again thanks for this great script and explanation!

  22. Josh
    August 3rd, 2017 at 04:16 | #36


    https://www.ucunleashed.com/downloads/2641/version.xml should be get some updates because:

    Version : 5.0.8308.984
    Product :
    Update :
    FriendlyResult : Unknown Version



  23. Josh
    August 3rd, 2017 at 04:19 | #38

    Version : 5.0.8308.992
    Product :
    Update :
    FriendlyResult : Unknown Version

    this is currently latest

  24. soder
    June 21st, 2018 at 05:43 | #39

    Hi Pat,

    would there be a way to feed the script with offline downloaded XML? I cant justify having FE servers to get internet access. But could copy scripts / XMLs to local storage, where I could run them.

  25. Jonathan Christie
    October 11th, 2018 at 10:05 | #40

    Hi Pat
    Any chance you can change the DisplayVersion to a version type, so the new .1001 build comes out as the latest?

    Cheers 🙂

  26. Jonathan Christie
    October 15th, 2018 at 05:54 | #42

    Sorry – I should have specified lync 2013 server – https://www.microsoft.com/en-us/download/details.aspx?id=36820

  27. Jonathan Christie
    October 15th, 2018 at 05:56 | #43

    I also should have said that I was ordering the installed version number as a version (no internet on servers to get the latest)

    [definitely not enough caffeine this morning]

  28. Oliver
    February 4th, 2019 at 09:03 | #44

    Cheers Dudes,

    version.xml is outdated. Latest L2013 comes up 01/19. I have added information to my offline version.xml and set uptodate to 1.

    So your .ps1 is still showing installed Version as .992 on any L2013 Server. But Corecomponents are at .1068 and Mediation still stays at .992

    Maybe it makes senso to focus on corecomponents by your script.


  29. Oliver
    February 4th, 2019 at 09:24 | #45

    Hi Pat,

    seems your array Line 544 is a bad choice. Because when you have a look underneath HKLM and your L2013 Server contains Front End and Mediation Role, you´ll get several Counts for your $version.

    When Mediation Server shows .922 as last and Front End Server .1068 at first then .922 will be taken for “Version Output”

    I would suggest to search for “Microsoft Lync 2013 Server, Core Components” underneath HKLM…\uninstall to obtain current installed version.

  1. May 3rd, 2014 at 23:55 | #1
  2. May 5th, 2014 at 07:28 | #2
  3. May 7th, 2014 at 03:41 | #3
  4. July 3rd, 2014 at 13:13 | #4
  5. November 22nd, 2014 at 15:46 | #5
  6. January 1st, 2015 at 15:51 | #6