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.
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
<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