运行 来自 cmd 批处理的 PowerShell 脚本作为管理员

Run a PowerShell script from a cmd batch as admin

我有一个 PowerShell 安装程序,我想在执行策略可能受限且需要管理员权限的计算机上执行。
理想情况下,我可以将它包装在一个 cmd 批处理中,如下所示:

powershell -Command "Start-Process powershell -Verb runAs -ArgumentList '-noexit','-ExecutionPolicy','bypass','-File','C:\path\setup.ps1'"

问题是当 C:\path\setup.ps1 包含空格时,我无法让它工作,而且如果是相对路径(cd C:\path),路径也不起作用。
有帮助吗?

这里有一个脚本示例,它检查进程是否 运行 已提升,如果不是,它会尝试启动一个新的提升进程。在这种情况下不需要嵌套文件或使用CMD。

这显然伴随着 UAC 提示的警告,就像任何其他以提升的权限启动的进程一样。

$isAdmin = [System.Security.Principal.WindowsPrincipal]::new(
    [System.Security.Principal.WindowsIdentity]::GetCurrent()
).IsInRole('Administrators')

if(-not $isAdmin)
{
    $params = @{
        FilePath = 'powershell' # or pwsh if Core
        Verb = 'RunAs'
        ArgumentList = @(
            "-NoExit"
            "-ExecutionPolicy ByPass"
            "-File `"$PSCommandPath`""
        )
    }
    Start-Process @params
    Exit
}

"I'm elevated"
# Code goes here
  • 同时将直通参数单独传递给Start-Process cmdlet's -ArgumentList parameter may be conceptually preferable, a long-standing bug unfortunately makes it better to encode all arguments in a single string - see

  • 使用-Verb RunAs启动命令并提升(作为管理员),总是使用SYSTEM32 目录作为工作目录 - 即使 -WorkingDirectory 参数(如果存在)也会被忽略。因此,为了设置自定义工作目录并调用 ,必须使用 -Command CLI 参数,并且 Set-Location (cd) 调用必须先于对指定脚本的调用相对路径。

  • cmd.exe 通过 powershell.exe、Windows PowerShell CLI 执行所有这些操作,由于转义要求而使事情复杂化。

应用于您的 powershell.exe CLI 调用(假设目录 C:\path 1 和脚本文件 setup 1.ps1):

powershell -Command "Start-Process -Verb RunAs powershell '-NoExit -ExecutionPolicy Bypass -Command "^"" cd \"^""C:\path 1\"^""; & \"^"".\setup 1.ps1\"^"" "^""'"

注:

  • cmd.exe 开始,"^""(原文如此)是将嵌入在整个 "..." 字符串中的 " 传递给powershell.exe(从 shell-free 上下文,例如计划任务,使用 """ 或更简单地说,\"

  • 为简单起见,对于 双重 嵌套 " 个字符。上面使用了 \-转义技术,带有 \ 个字符。他们自己需要转义为 \.

注意:从 PowerShell CLI 的角度来看 - 包括 PowerShell (Core) 7+(见下文) - \" 总是 有效,但它的使用存在问题来自 cmd.exe,它不能将 \" 理解为 escaped " 字符。因此将其视为常规字符串定界符,这可能会导致它错误地将 \"...\" 解释为 未引用 字符串的一部分,其中 & 等元字符然后可以中断命令,因为它们由 cmd.exe 本身预先解释;例如,powershell -c " \"Abbot & Costello\" "cmd.exe 中断,需要 ^& 而不是 ",或者如上所示,将嵌入的 " 转义为 "^""
powershell -c " "^""Abbot & Costello"^"" "


当您改为调用 pwsh.exe - PowerShell (Core) 7+ CLI - 可以进行两种简化:

  • 除了\"pwsh.exe更简单地支持""嵌入"个字符。在 "..." 个字符串中;后者从 cmd.exe

    开始稳定运行
  • pwsh.exe 现在有一个单独的 -WorkingDirectory 参数,因此允许使用 -File 参数调用脚本 - 但是请注意,文件路径解析before设置工作目录,所以下面使用完整路径。

pwsh.exe -Command "Start-Process -Verb RunAs pwsh.exe '-NoExit -ExecutionPolicy Bypass -WorkingDirectory ""C:\path 1"" -File ""C:\path 1\setup 1.ps1""'"