如何防止 VBScript 独立运行 运行?

How do i prevent a VBScript from running standalone?

我正在混合 VbScript 和 CMD,我可以使用

轻松调用 VBScript
cscript.exe //NoLogo "%~dp0TASK.vbs" >>"%~dp0output.txt"

但我需要禁用用户点击VBScript调用各种错误的功能,而不是通过批处理文件调用。

我的第一次尝试是在 运行 cscript.exe 之前将一个变量设置到文本文件中,然后使用 VBScript 中的错误处理来判断是否可以收集该变量,但它也添加了很多时间写剧本。

VBScript 是否有办法判断它是由 CMD 启动的,还是通过双击启动的,并能够相应地执行操作?

一种方法是让您的 VBS 文件检查参数是否存在,如果不存在则停止执行。

在您的 VBS 脚本中:

If WScript.Arguments.Count = 0 then
    ' No parameters provided. Can stop here.
End If

当你调用你的VBS文件时,只要传递任何参数就满足条件:

REM This will work.
cscript.exe //NoLogo "%~dp0TASK.vbs" "hello world"

REM So will this.
cscript.exe //NoLogo "%~dp0TASK.vbs" 1 2 3 4

REM This will not.
cscript.exe //NoLogo "%~dp0TASK.vbs"

这不会阻止人们 运行 手动(使用参数)或创建具有参数的快捷方式。它只会真正直接停止 运行 VBS(因为不会传递参数)。

这是一个简单的函数,检测parent进程标题。您可以检查进程是否由 CMD shell(标题为 cmd.exe)或 double-click(explorer.exe)启动:

If LCase(GetParentProcessCaption()) <> "cmd.exe" Then WScript.Quit

' the rest part of your code here

Function GetParentProcessCaption()
    With GetObject("winmgmts:\.\root\CIMV2:Win32_Process.Handle='" & CreateObject("WScript.Shell").Exec("rundll32 kernel32,Sleep").ProcessId & "'")
        With GetObject("winmgmts:\.\root\CIMV2:Win32_Process.Handle='" & .ParentProcessId & "'")
            With GetObject("winmgmts:\.\root\CIMV2:Win32_Process.Handle='" & .ParentProcessId & "'")
                GetParentProcessCaption = .Caption
            End With
        End With
        .Terminate
    End With
End Function

在您问题的上下文中,允许将参数从 CMD shell 进程传递到 WSH 脚本 child 进程的另一种方法可能会有用。它使用环境变量和 WScript.Shell object。考虑以下示例。

task.cmd 文件的代码:

set myvar=myvalue
wscript "%~dp0task.vbs"

对于 task.vbs 文件:

WScript.Echo CreateObject("WScript.Shell").Environment("process").Item("myvar")

我得到的输出如下:

注意,只有 child 个进程可以访问进程环境变量。

当您双击 .vbs 文件时,操作由以下注册表项决定:

  • Computer\HKEY_CLASSES_ROOT\VBSFile\Shell\Open\Command

如果您要更改密钥,您将更改双击操作,但不会影响您通过直接调用 cscript.exe 显式启动命令的能力。

如果bat文件会在vbs文件运行时保持cmd.exe打开,您可以尝试检测vbs文件中的cmd进程继续执行。

将其放在 vbs 文件的开头:

Set shell = CreateObject("WScript.Shell")
list_str = shell.Exec("tasklist").stdOut.ReadAll 'get a list of processes by calling the windows program 'tasklist.exe'
If InStr(list_str, "cmd.exe") = 0 Then WScript.Quit 'quit if process is not found