Script: Get-CsUpdateVersion.ps1 – See the Cumulative Update Level Of All Lync/Skype for Business Servers
Description
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.
Syntax
Get-CsUpdateVersion.ps1 [[-PoolFqdn] ] [-WhatIf] [-Confirm]
Installation
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.
Donations
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.
Assumptions
Download
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
Changelog
See the changelog for information on what’s changed/included in each version.
Thx Pat for your effort, it was a good solution
Fantastic as always Pat. Thanks a ton.
http://www.lyncnerd.com/2014/05/07/script-get-csupdateversion-ps1-see-the-cumulative-update-level-of-all-lync-servers/
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?
It’s not likely going to work with Edge servers, as their is no AD authentication to those machines.
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?
That’s being addressed in the new version, as is a quirk around Lync Server 2010.
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)
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.
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.
Cheers Pat! Script much appreciated!
Great script and working well, is there any option to export the result in CSV file?
Not at this time.
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”.
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.
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.
Yeah, that’s fixed in the next version.
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)
Hi,
great script.
I would suggest you added folowing code:
new-> $FriendlyResult=”Unknown Version”
switch ([string] $version) {
Thanks for the idea. I’ve got it queued for v2.3.
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.
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.
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?
Because you have a post CU5 update installed. Your version number likely is 5.0.8308.803
Has it been updated for the August 2016 CU?
I’m assuming you mean the Lync Server CU for August. Not yet. Should be online in the next day.
@Tony Hart
New version is now available
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.
Hello,
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?
Cheers
Not at this time
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!
Thanks. A corrected version has been uploaded.
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.
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.
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!
Hi,
https://www.ucunleashed.com/downloads/2641/version.xml should be get some updates because:
Version : 5.0.8308.984
Product :
Update :
FriendlyResult : Unknown Version
🙂
BR,
Josh
5.0.8308.987 has been available since March.
Version : 5.0.8308.992
Product :
Update :
FriendlyResult : Unknown Version
this is currently latest
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.
Hi Pat
Any chance you can change the DisplayVersion to a version type, so the new .1001 build comes out as the latest?
Cheers 🙂
Actually, what gets flagged as the latest is controlled by an online XML file. I show 9319.534 as the latest according to https://www.microsoft.com/en-us/download/details.aspx?id=47690, and that’s what’s listed in the XML file.
Or am I missing something?
Sorry – I should have specified lync 2013 server – https://www.microsoft.com/en-us/download/details.aspx?id=36820
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]
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.
BR,
Oli
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.