fredag den 4. marts 2011

Get parent Process

So I am working on writing a Windows Service in VB.NET
don’t want to tell the whole story now, but its used to deploy applications to servers. It can run as both a console application and Windows Service. On of the problems with Windows Services in Visual Studio is the lack of an easy way to debug/test the service. The way I worked it, was by checking the parent process of my self, and if that process is “services” I then know I need to start ServiceBase

Anyway, while testing it, one machine just refused to start the service. The was no errors in the event log, so I was 99% sure the services wasn’t even being started. Weird, I spent a lot of time troubleshooting that. I have all my code wrapped in Try Catch statements and I log accordingly so this was driving me crazy. Being desperate I finally added a log entry for every single line of code in the 2 main classes to see what the hell was going on. turns out my code for finding parent process was “stalling”.

I used the common WMI approach for finding my parent process, turns out my service “stalled” at this point, I’m guessing since a service needed wasn’t started yet, and my service timed out.

Public Shared Function getParentProcess(ByVal Process As Process) As Process
    Dim myPID As Integer = Process.Id
    Dim objWMIService, objProcess, colProcess
    Dim myPPID As Integer = -1
    objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
    colProcess = objWMIService.ExecQuery("Select * from Win32_Process where ProcessID=" & myPID)
    For Each objProcess In colProcess
        myPPID = objProcess.ParentProcessID()
    Next
    If myPPID > -1 Then
        Try
            Return Process.GetProcessById(myPPID)
        Catch ex As Exception
            Return Nothing
        End Try
    Else
        Return Nothing
    End If
End Function

Sure, that works but .. running as a service I'm guessing some other service need to be started in order for WMI to work. I don’t know, I don’t care I never liked WMI anyway so back to Google and look for an alternative. and this is what I ended up with

Public Const PROCESSBASICINFORMATION As UInteger = 0

<System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack:=1)> _
Public Structure Process_Basic_Information
    Public ExitStatus As IntPtr
    Public PepBaseAddress As IntPtr
    Public AffinityMask As IntPtr
    Public BasePriority As IntPtr
    Public UniqueProcessID As IntPtr
    Public InheritedFromUniqueProcessId As IntPtr
End Structure

<System.Runtime.InteropServices.DllImport("ntdll.dll", EntryPoint:="NtQueryInformationProcess")> _
Public Shared Function NtQueryInformationProcess(ByVal handle As IntPtr, ByVal processinformationclass As UInteger, ByRef ProcessInformation As Process_Basic_Information, ByVal ProcessInformationLength As Integer, ByRef ReturnLength As UInteger) As Integer
End Function

Public Shared Function getParentProcess(ByVal Process As Process) As Process
    Dim pi As New Process_Basic_Information

    Dim RetLength As UInteger
    NtQueryInformationProcess(Process.Handle, PROCESSBASICINFORMATION, pi, Marshal.SizeOf(pi), RetLength)
    Return Process.GetProcessById(pi.InheritedFromUniqueProcessId)
End Function

Ingen kommentarer:

Send en kommentar