Lync Server 2013/Skype for Business Health Check Script

Hi All

It's the season to be jolly I am having fun seeing the kids get excited about Santa visiting soon. I finally have a spare moment and so I thought I would post a Lync Server 2013 Health Check Script I put together to help do some daily checks about your Lync Server 2013 environment. It's meant to be a sample script to get you started scripting daily health check type activities to help with operating your environment. Marc (one of 4 Lync PFEs in Australia) and I have been thinking of putting together an Lync Server 2013 operational activities (Daily/Weekly/Monthly checks) series and so I thought I'd kick off with a bit of a teaser to get us started with the "Operational Activities" series.

Update: 10th of June 2015 (at the end of this post)

Getting Started – What does the script do?

So my script is used to check the following things in Lync:

  • Are all Lync Services running (using a list of servers as an input);
  • How many hotfixes have been installed on the affected server?
  • Is each server pingable?
  • How many services are running on each box?
  • What IP address, DNS settings, Gateway configured on each box?
  • Approximately how many people will be hosted by the server (based purely on an average of user accounts across the total number of Front Ends in the Pool);
  • How many processes are running on the machine?
  • Is CMS replicated across all servers, and if not what servers is not replicated to?
  • What's the result of Get-CSWindowsService;
  • What Error and Critical Error events have been logged in the "Lync Server" event log in the past 2 days;
  • What's the SQL Mirror status?

Pre-Requisites – What are the pre-requisites needed to run the script?

The following pre-requisites are needed to run the script:

  • Lync Server 2013 core components – you'll need the Lync Server 2013 core components in order to run Lync Management shell options;
  • User Account – A user account with CSAdministrator and Local Admin on each server you are interrogating

The Inputs – What can you configure when you run the script?

You can configure the following options as arguments when running the script:

  • -PoolName – you can use the -PoolName argument to supply the Front End Pool name that should be used to review how many users are homed on the Pool;
  • -RptDir – The Rpt Dir argument is used to provide a location on the server running the script to put the outputted HTML report file. Usually something like c:\SystemStatus
  • -LogFile – The name of the logfile that will be created containing the results of the script;
  • -ServerFile – This argument is used to supply a .TXT file with the list of servers that will be interrogated as part of the script. Include in the TXT file the name of all your Front End, Persistent Chat and Mediation Servers. Unfortunately Edge's aren't tackled as they sit in a workgroup and so typically authentication against the WORKGROUP machine can be a challenge;
  • -SendEmail – this argument is used if you want to get the script to send the outputted HTML as an email and send to a set of email addresses.
  • -NumOfDays – Is an integer value representing the number of days back to look when reviewing the "Lync Server" event logs for Critical and Error alerts;
  • -EventData – Is a Boolean argument representing whether or not to collect event log results. As it can sometimes take a bit of processing time to filter through events you can optionally choose to turn of collecting event data;
  • -Environment – This is a cosmetic argument and used to put a nice name in the report. The default value is Contoso so change to match something that makes sense for your environment;

Sending the Output of the Script as Email

To send the output of the script as email you need to use the -SendEmail $True argument. Also, I need to do some improvements in the script, but for now you need to update the EmailLogToTeam function in the script. In this function you need to update the $Recipients, $CC, $BCC, $SMTPHost and the $FromAddress variables to values that make sense for your environment. I'll fix this up in the next revision of the script so we can populate these with arguments in the script. You'll notice I also have included an If ($Debug) statement in the function, that way you can use different To, CC and BCC values to test out the script. You can use your own email address in all three values when testing the script is working properly (in your Test environment of course!).

##———————————————————————– ## Function: EmailLogToTeam ## Purpose: This function is used to SystemStatus Lync ##———————————————————————– function EmailLogToTeam {  param ([string]$strBody)  $strDate = get-date -uFormat "%d-%m-%Y"

 OutLn "INFO: Backing up Lync platform configuration information"

 If ($Debug) {      $Recipients=""      $CC=""      $BCC=""  } Else {      $Recipients=""      $CC=""      $BCC=""  }

 $SMTPHost=""  $FromAddress=""

 #Setting a subject for the email  $strMailSubject = "Lync 2013 SystemStatus – $ENVIRONMENT $strUserDomain – Pool $PoolName – $strDate"

 OutLn "INFO: Sending email to $Recipients"  Send-MailMessage -To $Recipients -From $FromAddress -CC $CC -BCC $BCC -Subject $strMailSubject -BodyAsHtml:$True -SmtpServer $SMTPHost -Body $strBody #Send the email


The Output – What does it look like?

So the script output looks like this

The summary table including details about servers in the Front End Pool you selected to review.

CMS Replication Status

A list of the most frequent events that have occurred in the past 2 days for each server in the servers file.

The SQL Mirroring Status

Running the Script

To run the script you can use the following command line…

.\SystemStatus.ps1 -Action status -ServerFile c:\scripts\systemstatus\servers.txt -PoolName -SendEmail $true -Environment Contoso -EventData $True

This is what the script looks like when it is executing…

What's in Servers.txt

Well I am glad you asked, nothing too fancy just a list of servers you want to interrogate with the per server checks. It will look something like this:

The key thing here is to make sure that the second column includes the name of the pool the server is in (if a Standalone just use the FQDN of the server), and then the third column is whether the product is Lync Server 2013 or Skype for Business 2015.

Well I hope you get some benefit from this script and remember use this just as a sample to get yourself started building your own Health Check Script, and please make sure you test in a test environment before moving to a production environment.

Happy Lync'ing and have a great Christmas and New Year



v1.18 of the script is attached!


Update: 10th June 2015

I have been playing around with Get-WinEvent compared to Get-EventLog and found Get-WinEvent is much faster when trawling through a remote server's events. So if you add the following two functions to the script, you can then make use of Get-WinEvent which should speed up running this script.

## Function: Get-RecentLyncWarningsWinEvent
## Purpose: This function is used to
function Get-RecentLyncWarningsWinEvent
param ([string]$strServer,[string]$strLog)
[string] $strResult = "";

 $objEvents = Get-WinEvent -ComputerName $strServer -FilterHashTable @{logname="$strLog";starttime=$StartTime;Level=3}
if ($objEvents.Count -gt 0) {
$strReturn = $objEvents.Count.ToString()
} Else {
$strReturn = "0"
return $strReturn

## Function: Get-RecentLyncErrorsWinEvent
## Purpose: This function is used to
function Get-RecentLyncErrorsWinEvent
param ([string]$strServer,[string]$strLog)
[string] $strResult = "";

 $objEvents = Get-WinEvent -ComputerName $strServer -FilterHashTable @{logname="$strLog";starttime=$StartTime;Level=1,2}
if ($objEvents.Count -gt 0) {
$strReturn = $objEvents.Count.ToString()
} Else {
$strReturn = "0"
return $strReturn

Then to make use of these functions you need to make a change in the Check-LyncSystemStatus function.  You can just add "WinEvent" to the Get-RecentLyncErrors and Get-RecentLyncWarnings calls (shown below).

$strLyncErrors= (Get-RecentLyncErrorsWinEvent$strServer"Lync Server")
OutLn"<TIME> $i – Getting recent warnings for $strServer"
$strLyncWarnings= (Get-RecentLyncWarningsWinEvent$strServer"Lync Server")

Don't forget to test in a test environment :).