嗯,我可能有点晚了!说出来只是为了记录 :) 尝试回答同样的问题,我阅读的其他主题没有提到vba,所以我在这里提出一种方法来完成它。
功能:从VBA运行wsshl,打开一个cmd提示符来测试当前用户权限,如果不是管理员,则打开一个powershell窗口,以管理员模式打开一个cmd提示符来运行一些命令行参数...一次性完成(晚绑定,只有msdos)
技巧:不是运行外部批处理文件或其他文件,而是使用dos和运算符将所有命令发送到装配线中。
问题:VBA不会等待最后打开的cmd窗口(异步),因此我添加了...另一个cmd提示符作为“waitonrun”,但也要检查是否发生了可怕的事情。如果不需要等待或验证任何内容,则可以“释放”它们。
工作原理:在mycmd变量中输入您的cmd参数,它可以使用vba变量进行参数化,并运行/编译。UAC将提示以管理员模式打开cmd窗口,然后按照说明操作。
其他可能的用途:在psmeth 2中使用psargsList =“echo。”,如果您想键入其他命令而不是发送一堆参数,则将授予访问上一个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