Monday, 20 March 2017

Use WMI to find PID from exe name

I'm starting to like WMI. I tend to be old school and will often google for a Windows API solution because I can call these in VBA. I know .NET programmers have a wonderful library but often clients place restrictions on one's VBA project.

For a little while I have been wresting with some Windows Api code which enumerates all of the processes, enumerates all the modules and then for the first module handle (conventionally the exe name) return the image (file) name. Except it's broken, something to do with mixing 32 and 64 bit processes. Arggghhh!

So why not for some WMI code? Here is some below, and is nice and short. I'm guess WMI has been developed as part of the Powershell initiative and so is probably the future. I think I will reach for WMI first hand in future.

Option Explicit

Sub TestGetProcessIds()
    Dim dicProcessIds As Scripting.Dictionary
    Set dicProcessIds = GetProcessIds("excel.exe")
    Debug.Print dicProcessIds.Keys()(0)
End Sub

'**********************************************************************************
'* GetProcessIds uses WMI's Win32_Process instead of
'* EnumProcesses, EnumProcessModules and GetModuleFileNameExA to match exe name
'**********************************************************************************
Function GetProcessIds(ByVal sImageName As String) As Scripting.Dictionary

    Dim dicProcessIds As Scripting.Dictionary
    Set dicProcessIds = New Scripting.Dictionary

    Dim objWMIService As Object
    Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
    Dim colItems As Object
    Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process" & _
               " WHERE Name = '" & sImageName & "'", , 48)
    Dim objItem As Object
    For Each objItem In colItems
        If Not dicProcessIds.Exists(objItem.ProcessId) Then 
            dicProcessIds.Add objItem.ProcessId, 0
        End If
    Next
    
    Set GetProcessIds = dicProcessIds

End Function


No comments:

Post a Comment