我可以使用 WMI VB 脚本创建子进程吗?

发布于 2024-07-09 13:01:57 字数 1726 浏览 5 评论 0 原文

使用 WMI VB 脚本编写,我想创建/附加多个子进程到父进程,例如资源管理器进程。

当一个应用程序通过点击启动时,它就成为资源管理器进程的子进程。 对于 Windows 启动时加载的所有应用程序也是如此。

如果您使用任务管理器中的“结束进程树”上下文菜单选项终止资源管理器进程,它也会终止资源管理器进程的所有子进程(一种无需重新启动即可清理内存的快速、强力方法)。

我有两个脚本 - 一个脚本杀死一堆特定进程,另一个脚本重新启动这些进程。

我的脚本中的大多数进程/应用程序都是在启动时加载的,因此它们是资源管理器进程的子进程。 当我杀死资源管理器进程树时,所有这些进程都会消失,如前所述。

当我使用脚本重新启动这些应用程序时,它们不再是资源管理器进程的子进程。 当我杀死资源管理器进程树时,由脚本启动的应用程序不会消失。

现在,我知道我可以使用脚本单独终止每个进程。 但是,最好只在脚本中杀死资源管理器进程树,而不必指定我想要杀死的各个应用程序。

因此,如果我有一个脚本可以将我的应用程序作为资源管理器进程的子进程启动,那么我的另一个脚本只需杀死资源管理器进程树即可。

我有一个脚本可以做到这一点。 它循环并杀死资源管理器进程的所有子进程。 但是,它仅适用于启动时加载或单击的应用程序。

此外,通过阻止这些应用程序在启动时加载,Windows 的加载速度会更快。 随后,我会在需要时单击脚本图标来加载我的应用程序。

这就是为什么我想创建一个脚本,可以将应用程序作为资源管理器进程的子进程启动。

一个有趣的旁注:我必须推迟终止任何命令/控制台进程,否则脚本可能会在获取其余进程之前终止自身。

有什么想法可以做到这一点吗?

下面是我失败的代码。

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

在风中等你 2024-07-16 13:01:57

窗口的进程会跟踪创建它的进程 ID,这就是管理关系的方式。 为了得到你想要的,你要么必须改变子进程中存储的父进程PID,要么将代码注入到你想要成为父进程的进程中并让它创建新的子进程。 这些都不是真正可行的。

真正的解决方案是使用 作业对象,这样您可以同时终止与该作业关联的所有进程。 但你必须从 vbscript 中迁移出来。

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.

冬天旳寂寞 2024-07-16 13:01:57

@josh polly 提议的使用 JobObjects 是对进程进行分组的标准做法,但当进程作为 DCOM 服务启动时不起作用。

在跟踪通过 CreateObject 实例化的事物的进程时,从 VBScript 启动应用程序有一个严重的缺点:根据对象的类型,应用程序的进程可能不会成为调用进程的子进程。 相反,它将在 svchost.exe 进程下启动。

假设我们正在使用 C/C++ 工作,并且希望从 VB 脚本启动 Excel。 在 C/C++ 中,我们可能会执行以下操作:

  1. 调用 CreateJobObject()
  2. 创建一个挂起的进程,该进程将调用 .VBS 脚本
  3. 使用 AssignProcessToJobObject() 将创建的进程添加到作业中
  4. 调用 ResumeThread() 启动挂起的进程

鉴于上述情况,大致发生的情况如下:

  1. 创建的进程 P 开始作为作业成员运行,J.
  2. P 使用脚本主机启动 VBS 文件,H(cscript 或 wscript.exe)
  3. H 作为 P 的子进程运行,正如预期的那样
  4. H 执行CreateObject("Excel.Application") 将 Excel 作为服务启动,
  5. 因此,Excel 成为服务主机进程的子进程,不是 P
  6. 此进程 (svchost.exe -k DcomLaunch) 为 DCOM 执行分组 DLL
  7. 脚本完成,H 终止
  8. E 继续,但 P 已丢失所有踪迹

第 4 行是罪魁祸首。 Excel 作为服务运行,因为注册表项表明它是 DCOM 对象。 解决这个问题的方法是创建一个 shell 对象,并通过它运行应用程序。

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

缺点是必须知道应用程序的路径。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文