我无法以管理员权限从 VBA 成功运行我的 PowerShell 脚本。

我研究了该论坛中的各种答案并尝试进行调整,但没有成功。

当我执行下面的 VBA 脚本时,有一个窗口会打开不到一秒钟然后关闭(我不知道它是 Powershell 还是命令窗口),并且脚本没有运行,因为它没有完成其工作,并且立即完成(没有等待十秒钟)。此外,没有任何内容写入StdOutStdErr

如果脚本从提升的命令窗口或提升的 Powershell 窗口运行,它将按设计运行。

该脚本旨在暂时断开网络适配器。目前该脚本已简化,并且仅适用于名为 的适配器Ethernet

Powershell 脚本

Disable-NetAdapter -name Ethernet -confirm:$false
Start-Sleep -Seconds 10
Enable-NetAdapter -name Ethernet -confirm:$false

运行提升的命令窗口代码
C:\PowerShell Scripts>"disable network temporarily.ps1"

不起作用的 VBA 代码

'Needs reference to Windows Script Host Object Model
Option Explicit
Sub TempNetworkDisable()
    Dim wshShell As wshShell
    Dim wshShellExec    As Object
    Dim strCommand      As String
    Dim strOutput

    strCommand = "pwsh.exe -c Start-Process -Verb RunAs pwsh.exe \"" -ExecutionPolicy Unrestricted -NoExit -f `\""C:\PowerShell Scripts\Disable Network Temporarily.ps1`\"""
    
    Set wshShell = New wshShell
    Set wshShellExec = wshShell.Exec(strCommand)
    strOutput = wshShellExec.StdOut.ReadAll()
    Debug.Print "StdOut:", strOutput

    strOutput = wshShellExec.StdErr.ReadAll()
    Debug.Print "StdErr:", strOutput
End Sub
  • Windows 11 专业版

    • 版本 10.0.22631 内部版本 22631
  • PS版本 7.4.6
  • 适用于 Microsoft 365 MSO 的 Microsoft® Excel®(版本 2409 内部版本 16.0.18025.20160)64 位
  • VBA 7.1.1143

4

  • 尝试运行 powershell shell 而不是运行脚本,然后手动运行脚本来测试是否具有所需的权限。


    – 

  • 理论上,可以限制办公应用程序以提升的权限运行,以防止病毒攻击。


    – 

  • 根据您创建的应用程序,您可以使用 Windows 服务来执行此类任务。应用程序可以使用自定义命令与服务进行交互。


    – 

  • 1
    @rotabor 该Disable-NetAdapter命令需要提升的权限。


    – 


最佳答案
1

  • 您的方法存在的直接问题是缺少转义结尾"[1]

    ' Note the \"" before the closing "
    ' To run the elevated pwsh.exe process *synchronously*, i.e. to wait
    ' for it to exit, add -Wait before -Verb RunAs
    strCommand = "pwsh.exe -c Start-Process -Verb RunAs pwsh.exe \""-ExecutionPolicy Unrestricted -NoExit -f `\""C:\PowerShell Scripts\Disable Network Temporarily.ps1`\""\"""
    
    • 请注意,如果您从非提升的进程运行生成的命令行,您将收到一个交互式提示,以授权创建提升的进程(以管理权限运行的进程,通过 请求Start-Process -Verb RunAs)。

    • 避免 UAC 提示的唯一方法是首先在提升的进程中运行,或者完全禁用(部分)UAC,强烈不建议这样做。否则,只有一个有限的解决方法:假设您原则上是管理员,您可以设置一个计划任务,其中预配置的命令将以提升权限运行,然后您可以从非提升的进程中按需调用该命令,而不会触发 UAC 提示。有关更多信息,

      请参阅

  • 但是,这会带来后续问题:您正在读取外部、临时 的 stdout 和 stderr 流pwsh.exe,这些流将为空,因为嵌套的提升进程在新窗口pwsh.exe中打开,这意味着它的输出流未连接到外部进程。

    • 笔记:

      • 您的外部pwsh.exe调用(有助于启动另一个具有提升的pwsh.exe进程的调用)和脚本都不是设计用于产生输出的,因此也许您不需要解决这个问题 – 假设没有发生错误;但是,如果您确实想捕获任何错误,则该问题确实需要解决。*.ps1
    • 您唯一的选择是捕获提升的进程在(临时)文件中的输出流。

    • 虽然确实提供-RedirectStandardOutput-RedirectStandardError接受文件路径的参数,但它们不能在您的情况下使用,因为可能出于安全考虑的设计,非提升的进程不允许捕获提升的进程的输出。

    • 因此,您需要通过使用重定向来捕获提升的进程内部的输出,这需要从基于( ) 的 CLI 调用切换到基于( ) 的 CLI 调用。-f-File-c-Command

    • 然后您必须在事后用 VBA 代码读取目标文件的内容。

' Note the addition of -Wait to the Start-Process call, 
' the switch to -c in the nested call, 
' the use of & the call operator to invoke the script, the
' switch to '...' quoting around the script-file path,
' and the > and 2> redirections with sample output file names
' stdout.txt and stderr.txt
strCommand = "pwsh.exe -c Start-Process -Wait -Verb RunAs pwsh.exe \""-ExecutionPolicy Unrestricted -NoExit -c & 'C:\PowerShell Scripts\Disable Network Temporarily.ps1' >stdout.txt 2>stderr.txt\"""

' ...

' After synchronous execution (due to -Wait), read the output files, stdout.txt and stderr.txt
' Without -Wait, you'd have to track the lifetime of the elevated
' process manually.

[1] 虽然您的原始代码因此存在语法错误,但pwsh.exe 悄悄忽略它的方式实际上是后者的一个错误,从 PowerShell 7.4.x 开始;一个简单的复制:(pwsh -nop -c "\"hi"从 PowerShell 外部;从 PowerShell 或 POSIX shell,使用pwsh -nop -c '"hi');请参阅

但是,失败- 抽象地 –
反映在进程退出代码中,该代码设置为1

5

  • 1
    谢谢。很简单——缺少 `\` <sigh>。现在它正常工作了(除了必须处理 UAC 对话框)。有什么方法可以避免处理这个问题吗?


    – 


  • 此外,现在它正在工作,我不需要捕获任何错误,但感谢您对这部分代码的洞察。


    – 

  • 嗯。我发现你提到的关于忽略语法错误的错误已经存在四年了。


    – 

  • 1
    @RonRosenfeld,很不幸,是的。我还在答案的顶部附近添加了有关如何避免 UAC 提示的信息,但出于安全原因,这通常是不明智的。


    – 


  • 1
    谢谢。我会想办法以提升的权限运行相关的 excel 文件。这似乎可以避免提示。


    –