SCOM Powershell Monitoring Managament pack - Issue getting script to operate

Hello,

I am trying to get a two factor monitor functioning that utilizes the “NET USE” command to check the status of all the mapped drives on a server. An if/else statement determines if any drives are in the “UNAVAILABLE” or “Disconnected” state and then sets a variable to either “FAIL” or “Success” depending on the result. Nothing seems to be working with this, the code works locally just fine, but I still cannot get it to alert in SCOM. I have other two factor monitors working with the exact same server, so its not a group/agent/permission related issue.

I have also attempted to run the ‘NET USE’ via ‘cmd.exe /c “net use”‘ without any success.

Below is the code I am using within the ‘script’ tab:

$api = New-Object -comObject “MOM.ScriptAPI”
$PropertyBag = $api.CreatePropertyBag()

$drives = net use | select-string “OK”, “Disconnected”, “Unavailable”

if (($drives -match “Disconnected”) -or ($drives -match “Unavailable”)) {
$result = “FAIL”
}else{$result = “SUCCESS”}

$PropertyBag.AddValue(‘Result’,$result)
$PropertyBag

Thank you all in advance for any assistance you can provide!

Hey,

Make sure to add a break at the end of your script, that can sometimes cause issues.

Also, add some logging to your script to help troubleshoot. I updated your script a little bit, then you filter on event 11001 in the event viewer (Operations Manager log).

Another thing to consider is that it could be that the user context the script is running under does not have the mapped drives.

$api = New-Object -comObject "MOM.ScriptAPI"
$PropertyBag = $api.CreatePropertyBag()

$ScriptName = "Get-MappedDrives.ps1"
$EventID = "11001"
$whoami = whoami 

Try {
    $drives = net use | select-string "OK", "Disconnected", "Unavailable"
    if (($drives -match "Disconnected") -or ($drives -match "Unavailable")) { $result = "FAIL" } else { $result = "SUCCESS" }
    
    $PropertyBag.AddValue('Result', $result)
    $PropertyBag

    $api.LogScriptEvent($ScriptName,$EventID,0,"`n  Outcome of script: $result `n Drives found: $Drives `n Running as $whoami.")

}

Catch
{
    $ErrorMessage = $_.Exception.Message
    $api.LogScriptEvent($ScriptName,$EventID,0,"`n  $ErrorMessage `n Running as $whoami.")
}

Br,

Jasper

Your original post has some age on it so you may have solved your issue already but I'll post a response anyway so that it might help someone else some day. I tested your snippet with the Show-SCOMPropertyBag function in my SCOMHelper PowerShell module available from PSGallery (info here: https://blogs.msdn.microsoft.com/tysonpaul/2018/08/06/scomhelper-powershell-module-a-scom-admins-best-friend/ ). (shameless plug there, sorry but it's quite relevant here).

Your code seems good when run as me, a local admin on the box. However sometimes you get mixed results, no pun intended, when a workflow runs as the default action account, in this case it is likely LocalSystem on your server.

So now what?
I highly recommend adding a logging function to your scripts. This will make it SOOO much easier to detect when your workflows are running and what they are doing. It makes debugging much easier.
First, I’ll show you a snippet which demonstrates how you could use a logging function in a script.
Second, I’ll show you how to customize this specifically for YOUR monitor scenario above with the SquaredUp Community PowerShell MP monitor wizard. Creating a monitor (or rule or task) with the SquaredUp wizard in the Console you don’t get quite as much artistic freedom as you would if you were authoring an MP the hard way with some other tool like an XML editor or Visual Studio.

Here’s the logging example template:

<#
  Name: LogIt
  Author: Tyson Paul
  Notes: https://blogs.msdn.microsoft.com/tysonpaul/
  Description: A simple way to either do or don't output debugging info to the OpsMan log.
	I usually use EventID range 9990-9999 for my scripts.

Example:
$msg = "CustomMessage at Line# $(LINE): "
LogIt -EventID $_EventID -Type $critical -Message $msg -Proceed $WriteToEventLog

#>

param(
[String]$WriteToEventLog=‘False’
)
[Bool]$WriteToEventLog = [System.Convert]::ToBoolean($WriteToEventLog)

########################################################################################################
Function LogIt ([int]$EventID, [int]$Type=2, [string]$Message=“No message specified.”, [int]$Proceed=$false) {
$oEvent = New-Object -comObject ‘MOM.ScriptAPI’
$TimeStamp = (get-date -format “yyyy-MM-dd-HHmmss”)
$output = @"

TimeStamp: $TimeStamp
ThisScript: $ThisScript
RunningAs: $(whoami.exe)
Message: $Message

Any errors will appear below:

$($Error | Select * | Out-String)

"@

If ($Proceed) {
	$oEvent.LogScriptEvent("$ThisScript",$EventID,$Type,$output)
}
Write-Verbose '`n`n-----------------------------------------'
Write-Verbose $output
Write-Verbose '-----------------------------------------'

}
########################################################################################################

Function Get-CurrentLineNumber {
$MyInvocation.ScriptLineNumber
}
########################################################################################################

New-Alias -Name LINE -Value Get-CurrentLineNumber –Description ‘Returns the current line number in a PowerShell script file.’ -ErrorAction SilentlyContinue

$ThisScript = “MyScriptName.ps1”
[Int]$info=0
[Int]$warn=2
[Int]$critical=1

$Message = "CustomMessage at Line# $(LINE): "
LogIt -EventID 9998 -Type $critical -Message $Message -Proceed $true

Here’s YOUR snippet with logging added…

# UNComment this for testing, force logging activity
[Bool]$WriteToEventLog = $true


########################################################################################################
Function LogIt ([int]$EventID, [int]$Type=2, [string]$Message="No message specified.", [int]$Proceed=$false) {
	$oEvent = New-Object -comObject 'MOM.ScriptAPI'
	$TimeStamp = (get-date -format "yyyy-MM-dd-HHmmss")
	$output = @"

TimeStamp: $TimeStamp
ThisScript: $ThisScript
RunningAs: $(whoami.exe)
Result: $result
Message: $Message

Any errors will appear below:

$($Error | Select * | Out-String)

"@

	If ($Proceed) {
		$oEvent.LogScriptEvent("$ThisScript",$EventID,$Type,$output)
	}
	Write-Verbose '`n`n-----------------------------------------'
	Write-Verbose $output
	Write-Verbose '-----------------------------------------'
}
########################################################################################################

Function Get-CurrentLineNumber { 
    $MyInvocation.ScriptLineNumber 
}
########################################################################################################

New-Alias -Name __LINE__ -Value Get-CurrentLineNumber –Description 'Returns the current line number in a PowerShell script file.' -ErrorAction SilentlyContinue

$ThisScript = "MyScriptName.ps1"
[Int]$info=0
[Int]$warn=2
[Int]$critical=1
$Result = 'N/A'
$Message = "Begin script $($ThisScript) $(__LINE__). "
LogIt -EventID 9990 -Type $critical -Message $Message -Proceed $true

$api = New-Object -comObject 'MOM.ScriptAPI'
$PropertyBag = $api.CreatePropertyBag()

LogIt -EventID 9990 -Type $critical -Proceed $true -Message "Getting drives with NET command... $($ThisScript) $(__LINE__): "
$drives = net.exe use | Select-String 'OK', 'Disconnected', 'Unavailable'
 
if (($drives -match 'Disconnected') -or ($drives -match 'Unavailable')) {
    $result = 'FAIL'
    LogIt -EventID 9990 -Type $critical -Proceed $true -Message "Drive failure detected $($ThisScript) $(__LINE__): [$($result | Out-String )]"
}
else{
    $result = 'SUCCESS'
    LogIt -EventID 9990 -Type $critical -Proceed $true -Message "Drives seem fine. $($ThisScript) $(__LINE__)."
}

$PropertyBag.AddValue('Result',$result)
$Message = "End script $($ThisScript) $(__LINE__). "
LogIt -EventID 9990 -Type $critical -Message $Message -Proceed $true
$PropertyBag

This should allow you to gain some idea of what the script is doing and provide visibility if there are any errors in the script.
My guess is there is something wrong with your condition detection (Healthy vs Unhealthy) criteria. Maybe a typo? Don’t copy/paste from websites. Often times the characters are encoded weird and this can cause a workflow to puke.

Or perhaps when the script runs as LocalSystem the NET USE command is failing. You might also want to wrap your risky commands within a Try/Catch bock(s) to detect unexpected behavior.
Good luck!
-Tyson