以管理员身份从 cmd 批处理运行 PowerShell 脚本

问题描述 投票:0回答:2

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

powershell batch-file cmd elevated-privileges executionpolicy
2个回答
6
投票
  • Windows PowerShell(见PowerShell(核心)7+底部部分),使用

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

  • 虽然将传递参数 单独 传递给

    Start-Process
    cmdlet 的
    -ArgumentList
    参数在概念上可能更可取,但不幸的是,一个 长期存在的错误 使得它 更好地将所有参数编码在一个 单个字符串中 - 见这个答案

  • 通过

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

应用于您的

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\\\"' "
  • 注意嵌入的

    "
    字符。是双重转义,如
    \\\"
    :首先作为
    \"
    以便在outer
    powershell.exe
    调用期间保留,然后再次用于innerone.

  • 虽然这 通常 有效,但存在 edge cases 其中基于

    \
    的转义是 的,即如果脚本路径或文件名包含
    cmd.exe
    元字符,例如
    &
    ;在这种情况下,
    "^""
    (原文如此)必须用于第一轮
    "
    -转义:

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

注:

  • cmd.exe
    (批处理文件)
    "^""
    (原文如此)是将嵌入在整个
    "
    字符串中的
    "..."
    传递给
    powershell.exe
    的最可靠方法,如上所示,而它
    ""
    pwsh.exe
    ,PowerShell(核心)CLI(见下文)。

  • 相比之下,从无壳上下文(例如,计划任务)

    \"
    在两个版本中都运行良好。

  • 有关详细信息,请参阅此答案


当您改为调用

pwsh.exe
- PowerShell (Core) 7+ CLI - 可以进行简化,甚至可能不需要解决方法:

  • pwsh.exe
    does 默认情况下保留调用者的工作目录,即使使用
    -Verb RunAs
    does 尊重
    -WorkingDirectory
    参数与
    -Verb RunAs
    .

  • 除了

    \"
    之外,
    pwsh.exe
    更简单支持
    ""
    嵌入
    "
    字符。在
    "..."
    字符串中;后者从
    cmd.exe

  • pwsh.exe
    本身现在有一个
    -WorkingDirectory
    参数
    ,因此允许使用
    -File
    参数调用脚本:

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

1
投票

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

    Start-Process @params
    return
}

"I'm elevated"
# Code goes here
© www.soinside.com 2019 - 2024. All rights reserved.