以admin身份运行命令提示符命令

时间:2015-01-05 05:07:21

标签: excel vba excel-vba cmd

我可以使用以下代码在命令提示符窗口中从vba运行命令

Private Sub CMDTest()
'command for cmd to execute
Dim command As String
command = "dir"

Call Shell("cmd.exe /S /K" & command)
End Sub

但是它不以管理员权限运行。如果command是需要管理权限的东西,我该如何从具有管理权限的vba运行它?

我试图以各种方式使用ShellExecute并且没有运气。我使用的代码如下,我可以作为管理员打开命令提示符窗口,但无法运行dir命令。

Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _
    ByVal hWnd As Long, _
    ByVal lpOperation As String, _
    ByVal lpFile As String, _
    ByVal lpParameters As String, _
    ByVal lpDirectory As String, _
    ByVal nShowCmd As Long) As Long

Const SW_SHOWNORMAL = 1

Public Sub test()

  ShellExecute 0, "runas", "cmd.exe", "", vbNullString, SW_SHOWNORMAL

End Sub

2 个答案:

答案 0 :(得分:0)

此vbscript与VBA兼容,在文件的右键菜单中运行动词。程序让RunAs升级到菜单上的管理员。

HelpMsg = vbcrlf & "  ShVerb" & vbcrlf & vbcrlf & "  David Candy 2014" & vbcrlf & vbcrlf & "  Lists or runs an explorer verb (right click menu) on a file or folder" & vbcrlf  & vbcrlf & "    ShVerb <filename> [verb]" & vbcrlf & vbcrlf & "  Used without a verb it lists the verbs available for the file or folder" & vbcrlf & vbcrlf
HelpMsg = HelpMsg & "  The program lists most verbs but only ones above the first separator" & vbcrlf & "  of the menu work when used this way" & vbcrlf & vbcrlf 
HelpMsg = HelpMsg & "  The Properties verb can be used. However the program has to keep running" & vbcrlf & "  to hold the properties dialog open. It keeps running by displaying" & vbcrlf & "  a message box." 
Set objShell = CreateObject("Shell.Application")
Set Ag = WScript.Arguments 
set WshShell = WScript.CreateObject("WScript.Shell") 
Set fso = CreateObject("Scripting.FileSystemObject")

    If Ag.count = 0 then 
        wscript.echo "  ShVerb - No file specified"
        wscript.echo HelpMsg 
        wscript.quit
    Else If Ag.count = 1 then 
        If LCase(Replace(Ag(0),"-", "/")) = "/h" or Replace(Ag(0),"-", "/") = "/?" then 
            wscript.echo HelpMsg 
            wscript.quit
        End If
    ElseIf Ag.count > 2 then 
        wscript.echo vbcrlf & "  ShVerb - To many parameters" & vbcrlf & "  Use quotes around filenames and verbs containing spaces"  & vbcrlf
        wscript.echo HelpMsg 
        wscript.quit
    End If

    If fso.DriveExists(Ag(0)) = True then
        Set objFolder = objShell.Namespace(fso.GetFileName(Ag(0)))
'       Set objFolderItem = objFolder.ParseName(fso.GetFileName(Ag(0)))
        Set objFolderItem = objFolder.self
        msgbox ag(0)
    ElseIf fso.FolderExists(Ag(0)) = True then
        Set objFolder = objShell.Namespace(fso.GetParentFolderName(Ag(0)))
        Set objFolderItem = objFolder.ParseName(fso.GetFileName(Ag(0)))
    ElseIf fso.fileExists(Ag(0)) = True then
        Set objFolder = objShell.Namespace(fso.GetParentFolderName(Ag(0)))
        Set objFolderItem = objFolder.ParseName(fso.GetFileName(Ag(0)))
    Else
        wscript.echo "  ShVerb - " & Ag(0) & " not found"
        wscript.echo HelpMsg 
        wscript.quit
    End If

    Set objVerbs = objFolderItem.Verbs

    'If only one argument list verbs for that item

    If Ag.count = 1 then
        For Each cmd in objFolderItem.Verbs
            If len(cmd) <> 0 then CmdList = CmdList & vbcrlf & replace(cmd.name, "&", "") 
        Next
        wscript.echo mid(CmdList, 2)

    'If two arguments do verbs for that item

    ElseIf Ag.count = 2 then
        For Each cmd in objFolderItem.Verbs
            If lcase(replace(cmd, "&", "")) = LCase(Ag(1)) then 
                wscript.echo(Cmd.doit)
                Exit For
            End If
        Next
    'Properties is special cased. Script has to stay running for Properties dialog to show.
        If Lcase(Ag(1)) = "properties" then
            WSHShell.AppActivate(ObjFolderItem.Name & " Properties")
            msgbox "This message box has to stay open to keep the " & ObjFolderItem.Name & " Properties dialog open."
        End If  
    End If
End If

答案 1 :(得分:0)

嗯,我可能迟到了!说出来是为了记录:)试图回答相同的问题,我读过的其他主题都没有提及vba,所以我在这里提出一种解决方法。

  • 功能:从vba运行wsshl,打开一个可进行测试的cmd提示符 当前用户权限,如果不是admin,则它将打开一个powershell窗口 在运行某些cmd行的管理模式下打开cmd提示符 参数...一口气(后期绑定,仅msdos)

  • 诀窍:而不是运行外部批处理文件,否则,全部 命令是使用dos&运算符在装配线中发送的。

  • 问题:VBA不会等待最后打开的cmd窗口 (asynchrone),所以我添加了...另一个cmd提示符充当“ waitonrun” 而且还要检查没有发生任何可怕的事情。如果没有 需要等待或验证任何内容,它们可以被“释放”。

  • 工作原理:在mycmd变量中输入您的cmd参数,可以是 使用vba变量进行参数设置,然后运行/编译。 UAC将提示 在管理员模式下打开cmd窗口,然后按照说明进行操作。

  • 其他可能的用途:使用psargsList =“ echo”。在psmeth 2中,访问 如果要输入最后一个cmd提示(管理模式) 其他命令,而不是发送一堆参数。在这种情况下 “ waitonrun”提示允许暂停vba,直到完成为止。

下面是使用icacls收回文件所有权的示例。

Sub acmd()

   '--------
   'settings
   '--------
   Dim output As String: output = Environ("userprofile") & "\Desktop\test.txt" ' a file

   Dim mycmd As String: mycmd = "icacls " & output & " /grant %username%:F " 'an msdos cmd to run as admin

   '---------
   '2 methods
   '---------
   'exact same versions but different syntax, the first is shorter, the second uses -ArgumentList argument of powershell that can be usefull in other cases
   'note: first run of powershell may take some time

   Dim psmeth As Long: psmeth = 1 '2
   Dim psargsList As String, psargs As String

   '------
   'layout
   '------
   'trying to lighten a bit the expression and the cmd prompt
   'msg could also be other cmd arguments

   Dim msg1 As String, msg2 As String, msg3 As String

   msg1 = "echo.& echo.""- listing files with ownership"" & echo."
   msg2 = "echo.& echo.""- applying cmd"" & echo.& echo. "
   msg3 = "echo.& echo.""Done! now press [enter]"" & echo."


   With CreateObject("wScript.Shell")

       If psmeth = 1 Then
       'add an msdos '&' between msdos args and cut the vba string with a vba '&' where you want to insert vba variables
       'from the last cmd point of view it will be the same cmd line, a succession of cmd arg1 & arg2 & arg3, the 'encapsulation' between \"""" is a bit more tricky
       'there are some warnings you can see when using -noexit after powershell cmd but it doesn't seems to hurt
       psargs = msg1 & " & dir " & output & " /q & " & msg2 & " & " & mycmd & " & " & msg3 & " & pause"
       .Run "cmd /c net session >nul 2>&1 & if ERRORLEVEL 1 ( Powershell -Command ""& { Start-Process cmd.exe \""""/c " & psargs & "\"""" -verb RunAs -wait }"" )", 1, True ' 3rd win only? ok too; add -noexit after Powershell to see warnings

       ElseIf psmeth = 2 Then
       'based on same principle, it works also with powershell's -ArgumenList 'arg1','& arg2','& arg3',.. syntax, there is a little less escaping but it needs to open a '4th' cmd window with /k (and VBA wont wait for it!) so that it doesn't close and runs cmd line args in assembly line
       'the cuts '...', are arbitrary, then inside them cut the vba string to insert vba variables
       psargsList = "-ArgumentList 'cmd /k ','" & msg1 & " & echo. &','dir " & output & " /q ',' & echo. & " & msg2 & "',' & " & mycmd & " ','& " & msg3 & " & pause ','& exit'"
       .Run "cmd /c net session >nul 2>&1 & if ERRORLEVEL 1 ( Powershell -Command ""& { Start-Process cmd.exe " & psargsList & " -verb RunAs -wait }"" )", 1, True

       End If

       If psmeth = 1 Or psmeth = 2 Then
       'we need some 'waitonrun', here a simple confirmation window
       .Run "cmd /c tasklist |find ""cmd.exe"" >nul && (set /p""= Holding on VBA till you close admin windows. Press [enter] when ready"" & taskkill /f /im ""cmd.exe"") || echo. ""dummy"">nul", 1, True
       End If

   End With

   '------------------
   Debug.Print "-end-"
   '------------------

   End Sub