#LOGS & EXCEPTIONS###########################################################
$CS_MODULE_NAME = "SkypeForBusiness"
$CS_MODULE_ADDED = "SkypeForBusiness Module is added";
$CS_MODULE_ALREADY_LOADED = "SkypeForBusiness Module is already loaded. No need to reload."
$CS_MODULE_FAILED_LOAD = "Failed to load SkypeForBusiness Module. Error: {0}."
$EXCEPTION_MESSAGE = "An internal exception occurred during script execution. Line: {0}, Exception : {1}."
$PROPERTY_VALUE = "Value of {0} is {1}."
$NO_NULL = "Error: {0} can not be null."
$MESSAGE_LENGTH_HIT_LIMIT = "MESSAGE TRUNCATED DUE TO SIZE LIMIT. Max Limit is [{0}]."
#############################################################################
#Helper Functions For Module Loading#########################################
$Script:logMessage = new-object System.Text.StringBuilder
function TRACE ($message)
{
$Script:logMessage.Append($message) | out-null
$Script:logMessage.Append("`n") | out-null
}
function IsCSModuleLoaded()
{
(get-module $CS_MODULE_NAME ) -ne $null
}
function LoadCSModule()
{
# Script execution are managed by SCOM powershell module.
# MonitoringHost.exe is hosting powershell runspaces.
# SCOM might run the scripts on the same process and reuse the app domain if neccesary.
# Double check on wheter module is loaded or not.
if (IsCSModuleLoaded)
{
TRACE ($CS_MODULE_ALREADY_LOADED)
}
else
{
# Refresh PSModulePath in case new build is deployed into different folder but SCOM Agent is not restarted
$psPaths = $env:PSModulePath -split ";"
$env:PSModulePath = ($psPaths + ([Environment]::GetEnvironmentVariable("PSModulePath", "Machine") -split ";" | ?{$psPaths -notcontains $_})) -join ";"
TRACE("PS Module Path: " + $env:PSModulePath)
# Due to possible race condition between steps of checking module is loaded and loading module steps,
# we need to double check after module loading attempt.
$moduleImported = $false
$retryCount = 0
# Unfortunately, foreach loop is iterating over $null values. Thank you, Powershell!!!
# In other words;
# foreach {$x in $null} {"test"} => Is printing "test" one time.
# to prevent this we need to use below format.
# foreach (... in strip-null (..)) {}
# E.g foreach {$x in strip-null($null)} {"test"} => Does not print "test".
# http://www.techtalkz.com/microsoft-windows-powershell/165444-foreach-null-interates-block.html
function strip-null($obj)
{
if ($obj -ne $null) { $obj }
}
#############################################################################
#Helper Functions For Error Logging##########################################
# We need to log a success event if there is a previous failure.
# if this function returns false then either previous run was success, expired or not exist.
# if this function returns true then previous run was error.
function ReadResultFromRegKey($regPath, $feature)
{
$result = $false
if (test-path $regPath)
{
$InternalErrorKey = (Get-Item $regPath)
if ($InternalErrorKey -ne $null)
{
$prevExecutionResult = $InternalErrorKey.GetValue($feature)
if ($prevExecutionResult -ne $null)
{
$decomposedResult = @($prevExecutionResult.Split(";"))
if ($decomposedResult.Count -eq 2)
{
$prevExecutionDateTimeTicks = [Int64]::Parse($decomposedResult[0])
$prevExecutionResult = $decomposedResult[1] -as [string]
$maxExpirationTicks = [TimeSpan]::FromSeconds($INTERVAL_SECONDS + $TIMEOUT_SECONDS).Ticks
$currentExpirationTicks = [System.DateTime]::UtcNow.Ticks - $prevExecutionDateTimeTicks
# Check whether registry key entry is expired.
if ($currentExpirationTicks -le $maxExpirationTicks)
{
$result = ($prevExecutionResult -eq $true)
}
}
}
}
}
$result
DETAILTRACE ("Read Result {0} From Regkey [Path={1} Property={2}]" -f $result, $regPath, $feature)
return
}
# Create an Operations Manager EventLog reference.
$EventLog = New-Object System.Diagnostics.EventLog("Operations Manager")
# Set the Source to Health Service Script. This is used in the expression in the rule.
$EventLog.Source = "Health Service Script"
function WriteResultIntoEventLogIfNecessary($IsExceptionOccurredInCurrentRun)
{
$logFlag = $null
if (test-path $LOG_REG_KEY)
{
$logFlag = (Get-ItemProperty $LOG_REG_KEY).LogOpsMgr
}
# Three conditions should be satisfied to skip event logging.
# * There should not be Internal Exception in previous run.
# * There should not be Internal Exception in current run.
# * Tracing Registry key is not ON.
if (($IsInternalExceptionOccurredInPreviousRun -eq $false) -and
($IsExceptionOccurredInCurrentRun -eq $false) -and
(($logFlag -ne 1) -and ($logFlag -ne 2)))
{
return
}
# Create an EventInstance reference. We pass a Task Category of None ( as indicated by 0 )
$EventInstance = New-Object System.Diagnostics.EventInstance($EVENT_ID, 0 , $EVENT_SEVERITY)
$DisplayName = $EVENT_SCRIPT_NAME
$EventLogMessage = ""
if($logFlag -eq 2)
{
$logMessage.Append($detailLogMessage) | out-null
}
# We need to safeguard ourself against the message limit. The documented message limit is 32786 bytes (~32K).
# http://msdn.microsoft.com/en-us/library/aa363679(VS.85).aspx
# however, when we use mom api to log event it adds some characters to the messages.
# Thus, we restrict the message limit here to 30720(30K).
# if the message is greater than this, we simply truncate it and update the log message.
$maxLimit = 30000
if($logMessage.Length -gt $maxLimit)
{
TRACE ($MESSAGE_LENGTH_HIT_LIMIT -f $maxLimit)
$EventLogMessage = $logMessage.ToString().Substring(0, $maxLimit)
}
else
{
$EventLogMessage = $logMessage.ToString()
}
#SCRIPT INFO#################################################################
$currentUser = whoami
# Check the execution policy of scripts and see if it is what is expected for our scripts to run if not
# set it to RemoteSigned which is the least supported execution policy this is a fix for RTMA-1762.
$supportedExecutionPolicies="RemoteSigned","Unrestricted","Bypass"
$executionPolicy = get-executionpolicy
if(!($supportedExecutionPolicies -contains $executionPolicy))
{
set-executionpolicy RemoteSigned
$executionPolicy = get-executionpolicy
}