如何防止 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
我正在混合 VbScript 和 CMD,我可以使用
轻松调用 VBScriptcscript.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