Search code examples
vbscriptwmiwshwbem

VBScript program incorrectly identifying its PID?


Every time I need to grant user access to a file share on our server, I get numerous occurrences of this popup because the process hits various files whose access rights I can't modify:

Error Applying Security Error

This isn't a problem, but I got tired of having to repeatedly stop what I was working on to click on the "Continue" button. So, I wrote a program to continually scan for an "Error Applying Security" window, and whenever it found one, send it an "Enter" keypress. This worked well enough, but since the central loop never terminates, I decided to add the ability to end the program when it was finished. I could have used an .hta file, but I decided to try a different approach that kept everything in a single file to make future maintenance easier. I adopted the code from this Stack Overflow question to find my program's PID and allow the program to be ended using the Windows TASKKILL command after a popup was closed.

The program seems to work correctly, identifying its PID and passing it to the popup. However, when TASKKILL runs, it claims the PID doesn't exist. Can anyone see what I'm doing wrong? Thanks in advance to all who respond.

'  AutoContinue.vbs
'  Program to automatically close all "Error Applying Security" messages

Option Explicit

Const Hidden = 0
Dim objWshShell, objWMILocator, objWMIService
Dim strComputerName, objArgs, objChildProcess, colPIDs, objPID

Set objWshShell = CreateObject( "WScript.Shell" )
Set objWMILocator = CreateObject( "WBemScripting.SWbemLocator" )
Set objWMIService = objWMILocator.ConnectServer( "", "", "", "" )

Function MyProcessID ()
' MyProcessID finds and returns my own PID.

    MyProcessID = 0
    Set objChildProcess = objWshShell.Exec( "%comspec% /C pause" )
    Set colPIDs= objWMIService.ExecQuery( "Select * From Win32_Process" & _
        " Where ProcessId=" & objChildProcess.ProcessID,, 0 )
    For Each objPID In colPIDs
        MyProcessID = objPID.ParentProcessID
    Next
    Call objChildProcess.Terminate()
End Function

Set objArgs = WScript.Arguments
If objArgs.Count = 1 Then
    If objArgs.Item(0) = "Popup" Then
        objWshShell.Popup( "AutoContinue PID is " & MyProcessID & _
            vbCrLf & "Hit OK when done." )
'        objWshShell.Run "taskkill /PID " & MyProcessID & " /T", 1
        objWshShell.Run "%comspec% /k taskkill /PID " & MyProcessID & " /T", 1
        Set objArgs = Nothing
        Set objWshShell = Nothing
        WScript.Quit
    End If
End If

objWshShell.Run "wscript.exe " & WScript.ScriptName & " Popup", Hidden

Do
    Do
        WScript.Sleep( 500 )
    Loop While Not objWshShell.AppActivate( "Error Applying Security" )
    WScript.Sleep( 100 )
    objWshShell.AppActivate( "Error Applying Security" )
    WScript.Sleep( 100 )
    objWshShell.SendKeys( "{ENTER}" )
Loop While True

Set objWshShell = Nothing

Solution

  • The script identifies its own PID correctly. However, you are trying to kill itself (the script instance with supplied Popup argument) while you need to kill the script instance without it (or with another 1st argument?).

    The following solution could help: supply PID of the instance to kill as 2nd argument (see variable iPid) along with the Popup one…

    '  AutoContinue.vbs
    '  Program to automatically close all "Error Applying Security" messages
    Option Explicit
    Const Hidden = 0
    Dim objWshShell, objWMILocator, objWMIService
    Dim strComputerName, objArgs, objChildProcess, colPIDs, objPID
    
    Set objWshShell = CreateObject( "WScript.Shell" )
    Set objWMILocator = CreateObject( "WBemScripting.SWbemLocator" )
    Set objWMIService = objWMILocator.ConnectServer( "", "", "", "" )
    
    Function MyProcessID ()
    ' MyProcessID finds and returns my own PID.
    
        MyProcessID = 0
        Set objChildProcess = objWshShell.Exec( "%comspec% /C pause" )
        Set colPIDs= objWMIService.ExecQuery( "Select * From Win32_Process" & _
            " Where ProcessId=" & objChildProcess.ProcessID,, 0 )
        For Each objPID In colPIDs
            MyProcessID = objPID.ParentProcessID
        Next
        Call objChildProcess.Terminate()
    End Function
    
    Dim iPid
    iPid = MyProcessID()
    
    Set objArgs = WScript.Arguments
    If objArgs.Count >= 2 Then
        If objArgs.Item(0) = "Popup" Then
            objWshShell.Popup( "AutoContinue PID is " & objArgs.Item(1) & _
                vbCrLf & "Hit OK when done." )
    '        objWshShell.Run "taskkill /PID " & objArgs.Item(1) & " /T /F", 1
            objWshShell.Run "%comspec% /k taskkill /PID " & objArgs.Item(1) & " /T /F", 1
            Set objArgs = Nothing
            Set objWshShell = Nothing
            WScript.Quit
        End If
    End If
    
    objWshShell.Run "wscript.exe """ _
        & WScript.ScriptFullName & """ Popup " & CStr( iPid) , Hidden
    ''                                 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ two arguments
    
    Do
         Do
            WScript.Sleep( 500 )
         Loop While Not objWshShell.AppActivate( "Error Applying Security" )
         WScript.Sleep( 100 )
         objWshShell.AppActivate( "Error Applying Security" )
         WScript.Sleep( 100 )
         objWshShell.SendKeys( "{ENTER}" )
    Loop While True