locked
Monitor based on PowerShell occasionally show ExitCode -1 when Launch a Process RRS feed

  • Question

  • good dat every one.

    I have encounter some problem.

    i need to monitor status of a programm (HP OM Agent). i write a ps script wich launch a process ovc.exe, then i parse output.

    in ISE all is ok. bhut when i use this script in monitor(s) i occasionally got ExitCode -1 (but monitored program is fine).

    here is my code

    ##			  <![CDATA[
    				# functions chapter
    				function KillChildProcs {
    					$CProcId = ([System.Diagnostics.Process]::GetCurrentProcess()).Id
    					$ChProcs = Get-WmiObject -Class Win32_Process -Filter "ParentProcessID=$CProcId"
    					if ($ChProcs){ 
    						foreach ($ChProc in $ChProcs ){
    							"Child Process PID is " + $ChProc.ProcessId + " and its name is " + $ChProc.path
    							"Killing this proc"
    							kill $ChProc.ProcessId -Force        
    						}
    					}else {
    						"No child process"
    					}
    				}
    
    				# init SCOM vars
    				$Result = 0
    				$Description = $null
    				$msgaError = $null
    				$agtPath = $null
    				$strLBinDir=$null
    				$ProcessInfo=$null
    				$Process=$null
    				$msgaSts=$null
    				$api=$null
    				$bag=$null
    
    				$api = New-Object -comObject 'MOM.ScriptAPI'
    				$api.LogScriptEvent('ChkOMAgtBuffState.ps1', 47, 4, "chk OMAgtBuff started")
    
    				# run opcmsga.exe - status and check it output
    				try{
    					# getting agent path
    						try{
    							$agtPath = (Get-Item 'Registry::HKLM\SOFTWARE\Hewlett-Packard\HP OpenView').GetValue('InstallDir')
    						}catch{
    							$ErrorMessage = $_.Exception.Message
    							$FailedItem = $_.Exception.ItemName
    							$api.LogScriptEvent('chkOMAgt.ps1',48,4,"Cant get HP Agent Path from regestry, fallback to default "+$ErrorMessage)
    							$Description = $Description  + "ERROR getting Agent Path from Regestry : "+$ErrorMessage + "`r`n"
    						}finally{
    							if (!$agtPath){ $agtPath = "DefPath"}     
    						}
    						#try to launch opcmsga.exe
    						try{
    							$strLBinDir = $agtPath + "lbin\eaagt"
    							$ProcessInfo = New-Object System.Diagnostics.ProcessStartInfo
    							$ProcessInfo.FileName = $strLBinDir + "\opcmsga.exe"
    							$ProcessInfo.RedirectStandardError = $true
    							$ProcessInfo.RedirectStandardOutput = $true
    							$ProcessInfo.UseShellExecute = $false
    							$ProcessInfo.Arguments = "-status"
    							$Process = New-Object System.Diagnostics.Process
    							$Process.StartInfo = $ProcessInfo
    							$Process.Start() | Out-Null                            
    								if ($Process.WaitForExit(12000)){
                                        "ExitCode = " + $Process.ExitCode
    									if ($Process.ExitCode -eq 0){
    										$msgaSts = $Process.StandardOutput.ReadToEnd()
    										if ($msgaSts -like '*Message Agent is not buffering*'){
    											$Result=0
    											$Description = $Description  +$msgaSts +"`r`n"                             
    										}else{
    											$Result=1
    											$Description = $Description  + $msgaSts  +"`r`n"
    										}
    									}else{
    										$Result=1
    										$Description = $Description + "ERROR : opcmsga.exe return error Exit Code is "+$Process.ExitCode+ "Error Output is " + $Process.StandardError.ReadToEnd() + "`r`n"
    									}
                                } else{
                                    $Result=1
    								$Description = $Description + "ERROR : opcmsga.exe Timeout" + $Process.StandardError.ReadToEnd() + "`r`n"
                                }                                                  
    							$Process.close()				            
    						}catch{
    							$ErrorMessage = $_.Exception.Message
    							$FailedItem = $_.Exception.ItemName
    							$Result=1
    							$Description = $Description + "ERROR launching opcmsga.exe " + $ErrorMessage + "`r`n"                
    						}finally{
    							$api.LogScriptEvent('ChkOMAgtBuffState.ps1', 47, 4, "COM object created")
    							$bag = $api.CreatePropertyBag()
    							$api.LogScriptEvent('ChkOMAgtBuffState.ps1', 47, 4, "Bag created")
    							$bag.addvalue("Result", $Result)
    							$bag.addvalue("Description", $Description)
    							$api.LogScriptEvent('ChkOMAgtBuffState.ps1', 47, 4, "Bag set " + $bag)
    							$bag
    				        
    						}
    				}catch{
    				}finally{
    				$Result
    				$Description
    				#clearing Varibles
    				KillChildProcs
    				Remove-variable	Result
    				Remove-variable	Description
    				Remove-variable	msgaError
    				Remove-variable	agtPath
    				Remove-variable	strLBinDir
    				Remove-variable	ProcessInfo
    				Remove-variable	Process
    				Remove-variable	msgaSts
    				Remove-variable	api
    				Remove-variable	bag
    				}
    ##			  ]]>

    and another one

    ##<![CDATA[
    
    #function declaration
    function KillChildProcs {
        $CProcId = ([System.Diagnostics.Process]::GetCurrentProcess()).Id
        $ChProcs = Get-WmiObject -Class Win32_Process -Filter "ParentProcessID=$CProcId"
        if ($ChProcs){
            foreach ($ChProc in $ChProcs ){
                "Child Process PID is " + $ChProc.ProcessId + " and its name is " + $ChProc.path
                "Killing this proc"
                kill $ChProc.ProcessId -Force
            }
        }else {
            "No child process"
        }
    }
    $Process=$null
    $matches=$null
    $bag=$null
    $Description=$null
    $regexp = "(?<Process>^\w+)(?:\s+)(?<Description>(?:\w+)(?:(?:\s\w+){1,}))(?:\s+)(?<Type>\w\S+)(?:\s+)(?<PID>\S+)(?:\s+)(?<Status>\w+$)"
    $ErrorMessage=$null
    $FailedItem=$null
    $agtPath =$null
    $isRegexped=$null
    $ovcError=$null
    
    $api = New-Object -comObject 'MOM.ScriptAPI'
    $api.LogScriptEvent('chkOMAgt.ps1',48,4,"Script Started")
    try{
        $agtPath = (Get-Item 'Registry::HKLM\SOFTWARE\Hewlett-Packard\HP OpenView').GetValue('InstallDir')
    }catch{
        $ErrorMessage = $_.Exception.Message
    	$FailedItem = $_.Exception.ItemName
    	$api.LogScriptEvent('chkOMAgt.ps1',48,4,"Cant get HP Agent Path from regestry, fallback to default "+$ErrorMessage)
        $Description = $Description  + "ERROR getting Agent Path from Regestry : "+$ErrorMessage + "`r`n"
        $agtPath = "DefPath"    
    }
    
    $ProcessInfo = New-Object System.Diagnostics.ProcessStartInfo
    $ProcessInfo.FileName = "ovc.exe"
    $ProcessInfo.RedirectStandardError = $true
    $ProcessInfo.RedirectStandardOutput = $true
    $ProcessInfo.StandardOutputEncoding=[System.Text.Encoding]::GetEncoding("windows-1252")
    $ProcessInfo.UseShellExecute = $false
    $ProcessInfo.Arguments = "-status"
    $Process = New-Object System.Diagnostics.Process
    $Process.StartInfo = $ProcessInfo
    
        # Creating string builders to store stdout and stderr.
        $StdOutBuilder = New-Object System.Text.StringBuilder
        $StdErrBuilder = New-Object System.Text.StringBuilder
        # Adding event handers for stdout and stderr.
        $action = {
            if (! [String]::IsNullOrEmpty($EventArgs.Data)) {
                $Event.MessageData.AppendLine($EventArgs.Data)
            }
        }
        #declare stdErr and stdOut Events
    $StdOutEvent = Register-ObjectEvent -InputObject $Process -Action $action -EventName 'OutputDataReceived' -MessageData $StdOutBuilder
    $StdErrEvent = Register-ObjectEvent -InputObject $Process -Action $action -EventName 'ErrorDataReceived' -MessageData $StdErrBuilder
    try{
            $Process.Start() | Out-Null
            $api.LogScriptEvent('chkOMAgt.ps1',48,4,"ovc started ")
            $Process.BeginOutputReadLine()
            $Process.BeginErrorReadLine()
            $Process.WaitForExit()
    
            # Removing and unregistering events to retieve process output.
            Remove-Event -SourceIdentifier $StdOutEvent.Name -EA SilentlyContinue
            Remove-Event -SourceIdentifier $StdErrEvent.Name -EA SilentlyContinue
            Unregister-Event -SourceIdentifier $StdOutEvent.Name
            Unregister-Event -SourceIdentifier $StdErrEvent.Name
            $api.LogScriptEvent('chkOMAgt.ps1',48,4,"StdOut is " +$StdOutBuilder.ToString())
            $api.LogScriptEvent('chkOMAgt.ps1',48,4,"ErrOut " +$StdErrBuilde.ToString())
            $api.LogScriptEvent('chkOMAgt.ps1',48,4,"ExitCode is " +$Process.ExitCode)
            $StdOut = $StdOutBuilder.ToString().split("`r`n");
            $StdErr = $StdErrBuilder.ToString().split("`r`n");
            $ExitCode = $Process.ExitCode
            if($ExitCode -eq 0){
                foreach ($ab in $StdOut){                       
                            $isRegexped = $ab -match $regexp
                            if($isRegexped){
                            	$api.LogScriptEvent('chkOMAgt.ps1',48,4,"got output line" +$line)
                                if ($matches['Status'] -ne "Running") {$Result=1}
                                $Description = $Description + $matches['Process']+"`t"+$matches['Status'] + "`r`n"
                                $matches=$null
                            }
                        }
                
            }else{
                $api.LogScriptEvent('chkOMAgt.ps1',88,4,"ExitCode is" +$ExitCode)
                $api.LogScriptEvent('chkOMAgt.ps1',88,4,"StdOut is" +$StdOut)
                $Description = $Description  + 'ovc exited with errors'+ "`r`n" + $StdErr
                $api.LogScriptEvent('chkOMAgt.ps1',48,4,"ovc exited with errors")
                $Result=1
            }
    }catch{
        $ErrorMessage = $_.Exception.Message
    	$FailedItem = $_.Exception.ItemName
    	$Result=1
    	$Description = $Description + "ERROR parsing ovc.exe " + $ErrorMessage + "`r`n"
    
    }
    
        "---------------------------------"
    
        $Process.close()
        if ($Result -ne 1){$Result=0}
        $Description
        $Result
        $bag = $api.CreatePropertyBag()
        $bag.addvalue("Result" , $Result)
        $bag.addvalue("Description" , $Description)
        $bag
        $api.LogScriptEvent('chkOMAgt.ps1',48,4,"Script Finished `r`nResult ="+$Result+"`r`nDescription is `r`n"+$Description)
        #"cleaning child process and remove varibles"
        KillChildProcs
        Remove-Variable regexp
        Remove-Variable Result
        Remove-Variable Description
        Remove-Variable ovcError
        Remove-Variable isRegexped
        Remove-Variable ProcessInfo
        Remove-Variable Process
        Remove-Variable matches
        Remove-Variable bag 
      ##  	]]>




    Monday, July 7, 2014 10:06 AM

All replies

  • Hi,

    As far as I can see in the script, you write a command to return the $Process.ExitCode 

    It seems like that the script works but with error message, would you please share the full error message here for further analysis.

    If the script works in Powershell ISE and also works in Powershell Console, I think this is not scripting error, but we need to know what the whole script is doing(I have to say that I am not a developer), would you please tell more about the script.

    And please also compare the conditions when you run the script manully and in the monitor, such as whether the process is stared each time, what account is used to run the script. If you run it in the monitor, then the account used should be the action account for the monitor.

    Hope this may help.

    Regards,

    Yan Li


    Regards, Yan Li


    • Edited by Yan Li_ Tuesday, July 8, 2014 1:20 PM edit
    Tuesday, July 8, 2014 1:20 PM
  • I have no data in stdOut nor in ErrOut.

    when i simulate error i got ExitCode greater than 0 and error description

    but in real life some times script work fine and ovc put in stdout some data but sometime inside the  monitor this script throw ExitCode -1 and no output at all.

    in that time i call ovc in RDP session and it was work ok. 


    i tried to change $ProcessInfo.FileName = "ovc.exe" to cmd /c ovc.exe but all in vain

    Tuesday, July 8, 2014 1:48 PM
  • Hi,

    Please refer to the following link:

    http://technet.microsoft.com/en-us/video/how-do-i-create-a-rule-and-monitor-using-a-windows-powershell-script-in-a-system-center-operations-manager-management-pack.aspx

    Best Regards,

    Vincent Wu


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.

    Tuesday, July 15, 2014 9:43 AM
  • Hi,

    Is there any update?

    Best Regards,

    Vincent Wu


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.

    Thursday, July 17, 2014 9:25 AM
  • i will reply you later  on monday 21, when i can reach test eviroment
    Thursday, July 17, 2014 2:00 PM
  • i saw this video but do not find any mention about Process.ExitCode 

    my script works fine if i call it from PowerShell but if it run in SCOM ExitCode turn to -1.

    i insert in my script recursion and find that it takes 2-3 times to get ExitCode >= 0

    why it can be so?

    Monday, July 21, 2014 7:15 AM
  • Hi,

    Please refer to the following link:

    http://technet.microsoft.com/en-us/sqlserver/system.diagnostics.process.exitcode(v=vs.108).aspx

    Best Regards,

    Vincent Wu


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.

    Thursday, August 7, 2014 2:09 AM
  • Hi,

    Any update?

    Best Regards,

    Vincent Wu


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.

    Monday, August 11, 2014 2:09 AM
  • i have read this topic but cant find any reference to -1 value for exit code.

    even more i have some document for ovc programm,  HP provide.

    there are NO exit codes less than 0. so it might be a OS value?

    now we have encounter 100% CPU load by monitoringhost.exe

    http://support.microsoft.com/kb/968967

    provide some hotfixes but OS where i encount this issue is windows 2008 R2

    is this hotfix applicatable for 2008 R2

    Monday, September 1, 2014 12:18 PM