2

Using WMI VB scripting, I would like to create/attach multiple child processes to a parent process, such as the explorer process.

When an app is started by clicking on it, it becomes a child process of the explorer process. The same is true for all apps that are loaded when Windows starts up.

If you kill the explorer process using the "End Process Tree" context menu option in the task manager, it kills all child processes of the explorer process as well (a quick, brute force way to clean up memory without restarting).

I have two scripts - one that kills a bunch of specific processes, and another that restarts those processes.

Most of the processes/apps in my scripts are loaded at start-up thus they are children of the explorer process. When I kill the explorer process tree, all these process die, as explained earlier.

When I restart these apps using a script, they are no longer children of the explorer process. When I kill the kill the explorer process tree, the apps started by the script do not die.

Now, I know I can kill each process individually using a script. But it would be nice to just kill the explorer processes tree in a script without having to specify the individual apps I want to kill.

So, if I have one script that can start my apps as children of the explorer process, my other script just has to kill the explorer processes tree.

I have a script that does just that. It loops through and kills all the child processes of the explorer process. However it only works on apps that load at start up or are are clicked on.

Also, by preventing these apps from loading at start-up, Windows loads MUCH faster. Later, I click on my script icon to load my apps when needed.

That's why I want to create a script that can start apps as children of the explorer process.

An interesting side note: I have to postpone killing any command/console processes, otherwise the script may kill itself before getting the rest of the processes.

Any ideas how this can be done?

Below is my code that fails.

Option Explicit
dim wmi, rootProcessName, rootProcess, objStartup, objConfig, objProcess, strComputer, dropbox, itunes, skype
strComputer = "."

dropbox="C:\Program Files\Dropbox\Dropbox.exe"
itunes="C:\Program Files\iTunes\iTunes.exe"
skype="C:\Program Files\Skype\Phone\Skype.exe"

Const NORMAL = 32
Set wmi = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set objStartup =  wmi.Get("Win32_ProcessStartup")
Set objConfig = objStartup.SpawnInstance_
objConfig.PriorityClass = NORMAL

rootProcessName = "'explorer.exe'"
set rootProcess = wmi.ExecQuery("Select * from Win32_Process Where Name = " & rootProcessName )
For Each objProcess in rootProcess
    objProcess.Create dropbox, null, objConfig
    objProcess.Create itunes, null, objConfig
    objProcess.Create skype, null, objConfig
Next

WScript.Quit
tshepang
  • 12,111
  • 21
  • 91
  • 136
user43244
  • 49
  • 2
  • 3

2 Answers2

1

A window's process keeps track of the Process ID of who created it, this is how the relationships are being managed. To get what you want, you either have to change the parent PID stored in the child process, or inject code into the process you want to be the parent and have it create the new child process. Neither of these are really doable.

The real solution is to use Job Objects, that way you can terminate all the processes which are associated with the job all at the same time. But you would have to migrate out of vbscript.

josh poley
  • 7,236
  • 1
  • 25
  • 25
0

The use of JobObjects as proposed by @josh poley is standard practice for grouping processes, but does not work when a process is launched as a DCOM service.

Launching applications from VBScript has a serious downside when it comes to tracking the processes of things instantiated through CreateObject: Depending on what kind of object it is, the application's process may not become a child of the invoking process. Instead, it will start up under an svchost.exe process.

Say we're working in C/C++ and we want to launch Excel from a VB script. In C/C++ we might do the following:

  1. Call CreateJobObject()
  2. Create a suspended process that is to invoke the .VBS script
  3. Add the created process to the job with AssignProcessToJobObject()
  4. Call ResumeThread() to start the suspended process

Given the above, here's roughly what happens:

  1. The created process, P, starts running as a member of job, J.
  2. P launches the VBS file with script host, H (cscript or wscript.exe)
  3. H runs as a child of P, as expected
  4. H executes CreateObject("Excel.Application") starting Excel as a service
  5. Hence, Excel becomes a child of a service host process, not P
  6. This process (svchost.exe -k DcomLaunch) groups DLLs for DCOM execution
  7. The scripting complete, H terminates
  8. E continues on, but P has lost all trace of it

Line 4 is the culprit. Excel is run as a service, because registry entries indicate that it is a DCOM object. A way around this, is to create a shell object, and run the application through that.

dim shell = wscript.createObject("wscript.shell")
shell.run(<path-to-application>\excel.exe)

The downside is that the path to the application must be known.

Spokes
  • 59
  • 1
  • 3