Search code examples
vbscriptpid

Find my own process ID in VBScript


I'm using the following code snippet to determine what process ID my vbscript is running as:

On Error Resume Next
Dim iMyPID : iMyPID = GetObject("winmgmts:root\cimv2").Get("Win32_Process.Handle='" & CreateObject("WScript.Shell").Exec("mshta.exe").ProcessID & "'").ParentProcessId
If Err.Number <> 0 Then Call Handle_Error(Err.Description)
On Error Goto 0

On my Windows 7 (32-bit) machine this works about 90% of the time and iMyPID contains the process ID of the currently running script. However 10% of the time Handle_Error gets called with the error message "SWbemServicesEX: Not found".

Recently someone else running Windows 7 (64-bit) reported that Handle_Error always gets called with the error message "Out of memory". This seems an insane error message just to find out your own process ID!

Can anyone recommend a better way of doing this?


Solution

  • mshta terminates itself immediately. Maybe it's too late to achieve parent process id by using WMI service.
    So, I'd use something like this to eliminate concurrent script processes.

    1. Generate random things.
    2. Determine an application which could be installed on each system, never terminates by itself (e.g. command prompt with /k parameter).
    3. Start the application in hidden mode with generated random argument (WshShell.Run).
    4. Wait a few milliseconds
    5. Query the running processes by using command line argument value.
    6. Get the ParentProcessId property.
    Function CurrProcessId
        Dim oShell, sCmd, oWMI, oChldPrcs, oCols, lOut
        lOut = 0
        Set oShell  = CreateObject("WScript.Shell")
        Set oWMI    = GetObject(_
            "winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
        sCmd = "/K " & Left(CreateObject("Scriptlet.TypeLib").Guid, 38)
        oShell.Run "%comspec% " & sCmd, 0
        WScript.Sleep 100 'For healthier skin, get some sleep
        Set oChldPrcs = oWMI.ExecQuery(_
            "Select * From Win32_Process Where CommandLine Like '%" & sCmd & "'",,32)
        For Each oCols In oChldPrcs
            lOut = oCols.ParentProcessId 'get parent
            oCols.Terminate 'process terminated
            Exit For
        Next
        CurrProcessId = lOut
    End Function
    
    Dim ProcessId
    ProcessId = CurrProcessId 'will remain valid indefinitely
    
    WScript.Echo ProcessId