VBScript';Shell执行返回代码

VBScript';Shell执行返回代码,vbscript,uac,Vbscript,Uac,是否有可能使用返回码(可能是Bool?)来了解UAC对话框是否被接受或拒绝?我现在不需要检查就可以这样做,如下所示 Set Shell = CreateObject("Shell.Application") Shell.ShellExecute "wscript.exe", """" & SOME_LOG_PARSING_SCRIPT_FULLPATH_HERE & """ uac", "", "runas" 我很高兴知道用户是否接受uac对话框(如果有)。尽管ShellExe

是否有可能使用返回码(可能是Bool?)来了解UAC对话框是否被接受或拒绝?我现在不需要检查就可以这样做,如下所示

Set Shell = CreateObject("Shell.Application")
Shell.ShellExecute "wscript.exe", """" & SOME_LOG_PARSING_SCRIPT_FULLPATH_HERE & """ uac", "", "runas"
我很高兴知道用户是否接受uac对话框(如果有)。

尽管ShellExecute实际上没有返回任何内容,因为该方法是异步运行的(即,在不等待新进程终止的情况下立即返回)。VBScript中的同步调用可以使用和方法进行,但这些方法不允许特权提升

基本上,不,你所问的是不可能的。

几十次说:然而,有一种解决办法,它很有可能回答这个问题,尽管仍然存在非零的错误回答概率。以下是此类解决方案的草稿,请参见下面的脚本:

  • 如果已经提升,则答案为100%:不需要UAC提示
  • 否则,请在UAC提示符之前和之后计算提升的
    wscript.exe
    • 如果计数器匹配,则UAC提示可能被拒绝
    • 如果计数器不同,则UAC提示可能已批准
如果同时异步启动或完成提升的
wscript.exe
,上述方法可能会失败…例如,从
RDP
会话或任务调度程序等

option explicit
On Error GoTo 0
Dim strResult: strResult = Wscript.ScriptName

Dim objShell, svcCounter, preCounter, postCounter
Set objShell = CreateObject("Shell.Application")

svcCounter  = 0
preCounter  = 0
postCounter = 0

Call TestProcess ( "SVC", svcCounter, "svchost.exe" )
strResult = strResult & vbNewLine & Cstr( svcCounter)

If svcCounter  = 0 Then
    '' elevated already
    strResult = strResult & vbNewLine & "UAC prompt not required"
    objShell.ShellExecute "wscript.exe" _
        , """" & "D:\VB_scripts\SO\37911301.vbs" & """ uac" , "", "runas", 1
Else
    preCounter  = 0

    Call TestProcess ( "pre", preCounter, "wscript.exe" )

    ' By default, Windows Vista/7/8's UAC prompt is shown on a _secure desktop_
    ' suspending calling process temporarily:
    objShell.ShellExecute "wscript.exe" _
        , """" & "D:\VB_scripts\SO\37911301.vbs" & """ uac" , "", "runas", 1

    Call TestProcess ( "post", postCounter, "wscript.exe" )

    strResult = strResult & vbNewLine & Cstr( preCounter) & vbTab & Cstr( postCounter)
    If preCounter = postCounter Then
        strResult = strResult & vbNewLine & "UAC prompt PROBABLY refused" 
    Else
        strResult = strResult & vbNewLine & "UAC prompt PROBABLY approved"
    End If
End If

Wscript.Echo strResult
Wscript.Quit

Sub TestProcess( byVal sStage, byRef nCounter, byVal strCap)

  strResult = strResult & vbNewLine & sStage 
  Dim strQuery, objWMIService, colItems, objItem, sCaption, sCmdLine
  Const wbemFlagReturnImmediately = &h10
  Const wbemFlagForwardOnly       = &h20

  strQuery = "SELECT * FROM Win32_Process WHERE Caption = '" & strCap & "'"

  Set objWMIService = GetObject("winmgmts:\\" & "." & "\ROOT\CIMV2")
  Set colItems = objWMIService.ExecQuery(strQuery _
          , "WQL", wbemFlagReturnImmediately + wbemFlagForwardOnly)

  For Each objItem in colItems
      sCaption = objItem.Caption
      sCmdLine = objItem.CommandLine
      if VarType( sCmdLine ) = 1 Then nCounter = nCounter + 1  'Null => elevated
      strResult = strResult & vbNewLine & sCaption
      strResult = strResult & vbTab & objItem.ProcessId
      strResult = strResult & vbTab & sCmdLine
      'strResult = strResult & vbTab & VarType( sCmdLine ) & vbTab & TypeName( sCmdLine )
  Next
End Sub

请注意,
strResult
中的所有垃圾仅用于调试目的。而且……我知道,如果高架车对蚊子的攻击已经太重了,我就用
TestProcess
呼叫进行测试……

可能不是完全重复,但这似乎非常相关:我必须忍受PEBKAC的痛苦,因为我看不出他的实际答案在哪里。他只是贴了一个手册部分,但没有回答OP的问题。。。事实上,也许这没有帮助,但被接受的答案似乎会给你一些想法。如果没有,希望其他人能给你一个更好的答案。这可以满足我100%的需求。非常感谢你的工作!