vba - 以管理员身份运行命令提示符命令

标签 vba excel 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

最佳答案

好吧,我可能要迟到了!说它是为了记录 :) 试图回答同样的问题,我读过的其他主题没有提到 vba,所以我在这里提出一种方法。

  • 它的作用:从打开 cmd 提示符的 vba 运行 wsshl 来测试 当前用户权限,如果不是管理员,那么它会打开一个 powershell 窗口 在运行某些 cmd 行的管理模式下打开 cmd 提示符 论点...一次性(后期绑定(bind),只是 msdos)

  • 诀窍:不是运行外部批处理文件,而是全部 命令使用 dos & 操作符在流水线上发送。

  • 问题:VBA 不会等待最后打开的 cmd 窗口 (异步)所以我添加了...另一个 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

关于vba - 以管理员身份运行命令提示符命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27773726/

相关文章:

regex - VBA RegEx 查找文件

java - C# 创建的新进程无法访问某些文件

excel - 使用 VBA 在单元格中插入多个双引号

vba - 错误 1004 - 此选择在 Range.Insert 上无效

excel - 如何在VBA中提取第二个空格后的文本

vba - 将 Outlook 2013 搜索文件夹电子邮件导出到 Excel

excel - 如何提取公式中使用的单元格?

excel - 我的 Web 查询可以在 Excel 中运行,但不能在 VBA 中运行

groovy - 如何通过groovy从cmd写入日志文件? (等级)

java - 启用 32 位和 64 位 Java 运行时环境