简体   繁体   English

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

[英]Run a PowerShell script from a cmd batch as admin

I have a PowerShell setup which I want to execute on a computer where perhaps the execution policy is restricted and requires admin rights.我有一个 PowerShell 设置,我想在执行策略可能受到限制并且需要管理员权限的计算机上执行它。
Ideally, I could wrap it in a cmd batch like follows:理想情况下,我可以将它包装在 cmd 批次中,如下所示:

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

The problem is that I can't make it to work when C:\path\setup.ps1 contains spaces, and also the path does not work if relative (with cd C:\path ).问题是当C:\path\setup.ps1包含空格时,我无法使其工作,并且如果相对路径也不起作用(使用cd C:\path )。
Any help?有什么帮助吗?

Here you have an example of a script that checks if the process is running elevated and if it's not it attempts to start a new process elevated.在这里,您有一个脚本示例,该示例检查进程是否正在运行提升,如果不是,它会尝试启动一个提升的新进程。 There is no need to nest files or use CMD in this case.在这种情况下,无需嵌套文件或使用 CMD。

This obviously comes with the caveat of an UAC prompt, as any other process that is started with elevated permissions.这显然伴随着 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
  • While passing the pass-through arguments individually to the 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 this answer .虽然将传递 arguments单独传递给Start-Process cmdlet 的-ArgumentList参数在概念上可能更可取,但不幸的是,一个长期存在的错误使得在单个字符串中编码所有 arguments 更好 - 请参阅此答案

  • Using -Verb RunAs to launch a command with elevation (as admin), invariably uses the SYSTEM32 directory as the working directory - even a -WorkingDirectory argument, if present, is quietly ignored.使用-Verb RunAs启动具有提升的命令(以管理员身份),总是使用 SYSTEM32 目录作为工作目录 - 即使-WorkingDirectory参数(如果存在)也会被悄悄忽略。 Thus, in order to set a custom working directory and to invoke, the -Command CLI parameter must be used, and a Set-Location ( cd ) call must precede a call to a script specified by relative path.因此,为了设置自定义工作目录并进行调用,必须使用-Command CLI 参数,并且必须在调用相对路径指定的脚本之前调用Set-Location ( cd )。

  • Doing all this from cmd.exe , via powershell.exe , the Windows PowerShell CLI , complicates matters due to escaping requirements. Doing all this from cmd.exe , via powershell.exe , the Windows PowerShell CLI , complicates matters due to escaping requirements.

Applied to your powershell.exe CLI call (assuming dir. C:\path 1 and script file setup 1.ps1 ):应用于您的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\\"^"" "^""'"

Note:笔记:

  • From cmd.exe , "^"" (sic) is the most robust way to pass " that are embedded in an overall "..." string to powershell.exe (from a shell- free context, such as a scheduled task, use """ or, more simply, \" .cmd.exe"^"" (原文如此)是将嵌入在整个"..."字符串中的“ "传递给powershell.exe的最可靠方法(来自壳上下文,例如计划任务,使用"""或更简单的\"

  • For simplicity, for the doubly nested " chars. the \ -escaping technique is used above, with the \ chars. themselves requiring escaping as \\ .为简单起见,对于双重嵌套的"字符。上面使用了\ -转义技术, \字符本身需要 escaping 作为\\

Note: From the PowerShell CLI perspective - including in PowerShell (Core) 7+ (see below) - \" always works, but its use is problematic from cmd.exe , which doesn't understand \" as an escaped " char. and therefore treats it as a regular string delimiter, which can cause it to misinterpret what's been \"...\" as being part of an unquoted strings, where metacharacters such as & can then break the command, because they're interpreted by cmd.exe itself, up front; eg, powershell -c " \"Abbot & Costello\" " breaks from cmd.exe , requiring either ^& instead of " or, as shown above, escaping embedded " as "^"" instead:注意:从 PowerShell CLI 的角度来看 - 包括在 PowerShell (Core) 7+(见下文) - \"总是有效的,但它的使用是有问题cmd.exe " char \"并理解为转义。因此将其视为常规字符串定界符,这可能会导致它将\"...\"误解为未加引号的字符串的一部分,其中元字符(如&可能会破坏命令,因为它们是由cmd.exe解释的cmd.exe本身,在前面;例如, powershell -c " \"Abbot & Costello\" "cmd.exe中断,需要^&而不是"或者,如上所示, Z534F19BE86FF67166CBBF80 嵌入为" EA "^""
powershell -c " "^""Abbot & Costello"^"" "


When you call pwsh.exe instead - the PowerShell (Core) 7+ CLI - two simplifications are possible:当您改为调用pwsh.exe时 - PowerShell (Core) 7+ CLI - 可以进行两种简化:

  • In addition to \" , pwsh.exe more simply supports "" for embedding " chars.除了\"之外, pwsh.exe更简单地支持""用于嵌入"字符。 in "..." strings;"..."字符串中; the latter works robustly from cmd.exe后者从cmd.exe稳健地工作

  • pwsh.exe now has a separate -WorkingDirectory parameter, which therefore allows invoking the script with the -File parameter - do note, however, that the file path is resolved before the working directory is set, so the full path is used below. 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""'"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM