【问题标题】:Run a PowerShell script from a cmd batch as admin以管理员身份从 cmd 批处理运行 PowerShell 脚本
【发布时间】:2022-01-17 00:14:47
【问题描述】:

我有一个 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),则路径也不起作用。
有什么帮助吗?

【问题讨论】:

  • 您已经以管理员身份运行批处理文件了吗?
  • @AbrahamZinala:不。 cmd 批处理的全部目的是要求用户提升并暂时允许脚本执行。因此,参数-Verb runAsExecutionPolicy bypass
  • 我知道这些论点,只是想在获得更多上下文的同时提供替代解决方案。
  • 为什么需要 Cmd 来运行脚本?为什么不使用自提升的完整 PowerShell 脚本?
  • @SantiagoSquarzon 如果执行策略受到限制,您一开始就无法执行自提升脚本。

标签: powershell batch-file cmd elevated-privileges executionpolicy


【解决方案1】:
  • 虽然将传递参数单独传递给Start-Process cmdlet 的-ArgumentList 参数在概念上可能更可取,但不幸的是long-standing bug 可以更好地将所有参数编码在一个单个字符串 - 见this answer

  • 使用-Verb RunAs 来启动一个命令带有海拔(作为管理员),总是使用 SYSTEM32 目录作为工作目录 - 即使是 -WorkingDirectory 参数,如果现在,被悄悄地忽略了。因此,为了设置自定义工作目录并调用 ,必须使用 -Command CLI 参数,并且必须在调用 relative 指定的脚本之前调用 Set-Location (cd) em> 路径。

  • cmd.exepowershell.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-免费 上下文,例如计划任务,使用""" 或更简单的\"

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

注意:从 PowerShell CLI 的角度来看 - 包括在 PowerShell (Core) 7+ 中(见下文) - \" 总是 有效,但它的使用存在问题来自cmd.exe,它不能将 \" 理解为 转义 " 字符。并因此将其视为常规字符串分隔符,这可能会导致它将 \"...\" 误解为 未引用 字符串的一部分,其中诸如 & 之类的元字符可能会破坏命令,因为它们由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 参数调用脚本 - 但是请注意,文件路径在工作目录之前解析已设置,因此下面使用完整路径。

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

【讨论】:

  • 谢谢。你的"^"" 解决了这个问题。仍然很遗憾地看到,尽管他们付出了所有努力,Microsoft 仍无法为我们提供一个简单的语法来调用管理脚本。在 Linux 中可以像 sudo '/path/to/setup' 一样简单。
【解决方案2】:

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

【讨论】:

  • 谢谢,但是,正如问题中提到的,我事先不知道目标计算机上的执行策略可能是什么,可以将它们设置为限制。
猜你喜欢
  • 2014-07-26
  • 2013-01-16
  • 2014-01-20
  • 1970-01-01
  • 1970-01-01
  • 2015-04-17
  • 2019-04-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多