从VBScript获取bat中的错误级别

3
我正在尝试确定用户是否在UAC提示中点击了 “NO”,如果是,则不设置nul端口。
我正在从批处理文件中调用此脚本,如果用户点击“否”,则希望退出。
这是VBScript:
Option Explicit
Main 

Sub Main

    Dim oShell, objWMIService, servSpooler, objReg, objShellApp, result

    Const PrinterPort = "NUL:"
    Const HKLM = &h80000002

    If Not WScript.Arguments.Named.Exists("elevate") Then
        Set objShellApp = CreateObject("Shell.Application")
        objShellApp.ShellExecute WScript.FullName, WScript.ScriptFullName & " /elevate", "", "runas", 0
        WScript.Quit 
    End If

    result = isElevated()

    If result = True Then
        Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
        set servSpooler = objWMIService.Get("Win32_Service.Name='spooler'")
        Set objReg = GetObject("winmgmts:root\default:StdRegProv")

        servSpooler.StopService
        objReg.SetStringValue HKLM, "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports", PrinterPort, ""
        servSpooler.StartService
    Else
        WScript.Quit 1
    End If

End Sub

Function isElevated
    Dim shell, whoami, whoamiOutput, strWhoamiOutput

    Set shell = CreateObject("WScript.Shell")
    Set whoami = shell.Exec("whoami /groups")
    Set whoamiOutput = whoami.StdOut
    strWhoamiOutput = whoamiOutput.ReadAll

    If InStr(1, strWhoamiOutput, "S-1-16-12288", vbTextCompare) Then
        isElevated = True
    Else
        isElevated = False
    End If
End Function

批处理:
cscript "set_port.vbs"
IF ERRORLEVEL 1 (
    ECHO FAIL
    PAUSE
    EXIT
)

现在,我看了这个页面:http://www.robvanderwoude.com/errorlevel.php和其他一些页面,感觉我已经尝试了所有可能的组合。可能是因为我还没有找到正确的组合。希望能得到一些提示和帮助!
基本目标:确定用户是否在UAC提示中点击了NO,然后结束VBScript和批处理文件。
更新:
好的,谢谢所有的回答。现在我相当确定问题出在脚本上。我再次在批处理文件中使用errorlevel,现在它运行得非常好。
至于VBScript: 为了让错误代码(例如1)在用户在UAC提示中点击NO时出现(意味着当前文件未被提升),我需要像这样编写:
If result = True Then
    Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
    set servSpooler = objWMIService.Get("Win32_Service.Name='spooler'")
    Set objReg = GetObject("winmgmts:root\default:StdRegProv")

    servSpooler.StopService
    objReg.SetStringValue HKLM, "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports", PrinterPort, ""
    servSpooler.StartService
    WScript.Quit(0)
Else
    WScript.Quit(1)
End If

但是:在ShellExecute之后的第一个WScript.Quit中,我也需要加上WScript.Quit(1)吗?因为否则我永远不会得到传递给错误级别的错误(或者至少不大于0)。

所以:

    objShellApp.ShellExecute WScript.FullName, WScript.ScriptFullName & " /elevate", "", "runas", 0
    WScript.Quit(1)

我猜主要问题在于点击UAC提示框上的“否”并不会导致错误,所以我需要在那里加上WScript.Quit(1)。

或者我可以换一种方式,如果用户单击了“是”,且脚本已提升,则使用WScript.Quit(1),并在其他地方放置WScript.Quit(0)。

然而,在第一种情况下,我总是得到错误级别1,在第二种情况下,总是错误级别为0。

----------- 更新:

现在我的VBScript文件看起来像这样:

    Option Explicit

    Main 

    Sub Main

    Dim objShell, objWMIService, servSpooler, objReg, objShellApp, result, oShell
    Dim whoami, strWhoamiOutput, whoamiOutput

        Const PrinterPort = "NUL:"
        Const HKLM = &h80000002

    If Not WScript.Arguments.Named.Exists("elevate") Then
            Set objShellApp = CreateObject("Shell.Application")
            objShellApp.ShellExecute WScript.FullName, WScript.ScriptFullName & " /elevate", "", "runas", 0
            WScript.Quit 10
WScript.Echo("Done")
    Else

        Set oShell = CreateObject("WScript.Shell")
        Set whoami = oShell.Exec("whoami /groups")
        Set whoamiOutput = whoami.StdOut
        strWhoamiOutput = whoamiOutput.ReadAll

        If InStr(1, strWhoamiOutput, "S-1-16-12288", vbTextCompare) Then
            Wscript.Echo("ADMIN")
            WScript.Echo("Port")
            Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
            set servSpooler = objWMIService.Get("Win32_Service.Name='spooler'")
            Set objReg = GetObject("winmgmts:root\default:StdRegProv")

            servSpooler.StopService
            objReg.SetStringValue HKLM, "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports", PrinterPort, ""
            servSpooler.StartService
            WScript.Quit 1
        End if
        WScript.Echo("Done 2")

    End If

    End Sub

同时,这里有一个测试批次:

@echo off
cscript "test.vbs"
ECHO %errorlevel%
PAUSE

尽管脚本成功退出并且消息“完成”从未显示,但错误级别输出为10而不是1。


当您使用退出代码退出时,请确保在所有地方都这样做。 - AcidJunkie
你是什么意思?我还需要把它放在哪里? - user3629873
1
在某些地方,您只需使用 WScript.Quit 来退出。在另一个地方,您只需使用 WScript.Quit 1。当您依赖程序/脚本的退出代码时,您必须确保它始终被正确设置。 - AcidJunkie
1个回答

0

调试技巧:

编写一个仅设置错误级别并退出的VBS脚本,并在批处理脚本中运行该脚本。

然后,您可以修改完整的VBS脚本。


我已经做过了,而且当我添加了所有的东西后,它也起作用了,但后来又不起作用了。 - user3629873
你是否注意到,在启动提升测试后,你使用了WScript.Quit而没有设置错误级别? - foxidrive

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接