简体   繁体   English

运行 Powershell 脚本时 ExecutionPolicy 出现问题

[英]Trouble with ExecutionPolicy when running Powershell scripts

I am trying to write a Powershell script to automate general tasks on a new computer including installing software.我正在尝试编写一个 Powershell 脚本来自动执行新计算机上的一般任务,包括安装软件。 ExecutionPolicy has been the bane of my existence when it comes to blocking me from running automated scripts that I have been writing.当阻止我运行我一直在编写的自动化脚本时,ExecutionPolicy 一直是我存在的祸根。

One of my PS scripts requires elevated Admin privileges, so I have a batch file where I am calling to launch PS as Administrator but I am still getting stuck with the script instantly closing/failing due to ExecutionPolicy.我的一个 PS 脚本需要提升的管理员权限,所以我有一个批处理文件,我在其中调用以管理员身份启动 PS,但由于 ExecutionPolicy,我仍然遇到脚本立即关闭/失败的问题。 Ideally, I would like a way to bypass the ExecutionPolicy on a per script basis instead of completely changing it and then changing it back.理想情况下,我想要一种基于每个脚本绕过 ExecutionPolicy 的方法,而不是完全更改它然后再将其更改回来。

I have looked up different Set-ExecutionPolicy methods but they don't seem to work.我查找了不同的 Set-ExecutionPolicy 方法,但它们似乎不起作用。

I need a generic command in a.bat file to launch a specified powershell script as Admin AND bypassing the current ExecutionPolicy.我需要 a.bat 文件中的通用命令以管理员身份启动指定的 powershell 脚本并绕过当前的 ExecutionPolicy。

I need a generic command in a.bat file to launch a specified powershell script as Admin AND bypassing the current ExecutionPolicy.我需要 a.bat 文件中的通用命令以管理员身份启动指定的 powershell 脚本并绕过当前的 ExecutionPolicy。

The key is to use the -ExecutionPolicy CLI parameter (which only the inner powershell call below needs; the sole purpose of the outer one is to launch the target session with elevation (as admin), which itself doesn't involve execution of a script file):关键是使用-ExecutionPolicy CLI参数(只有下面的内部powershell调用需要;外部调用的唯一目的是使用提升(作为管理员)启动目标 session,它本身不涉及脚本的执行文件):

  • Caveat : If your effective execution policy is controlled by GPOs (Group Policy Objects), it can not be overridden [1] - neither with the -ExecutionPolicy CLI parameter, nor in-session with Set-ExecutionPolicy - the solution below won't work.警告:如果您的有效执行策略由GPO (组策略对象)控制,则无法覆盖[1] - 既不能使用-ExecutionPolicy CLI 参数,也不能使用Set-ExecutionPolicy进行会话 - 下面的解决方案将不起作用. See this answer for details.有关详细信息,请参阅此答案

Also - unrelated to execution policies - additional work is required in order to preserve the caller's working directory , because elevated sessions default to the SYSTEM32 directory .此外 - 与执行策略无关 -需要额外的工作来保留调用者的工作目录,因为提升的会话默认为 SYSTEM32 目录 Therefore, the command below incorporates an explicit Set-Location call to set the working directory.因此,下面的命令包含一个显式的Set-Location调用来设置工作目录。 Note that in order to call a script located in that directory you need to prefix its name with .\ (eg, .\script.ps1 instead of just script.ps1 ):请注意,为了调用位于该目录中的脚本,您需要在其名称前加上前缀.\ (例如, .\script.ps1而不仅仅是script.ps1 ):

:: Run from cmd.exe / a batch file.
:: The target script file is '.\script.ps1' in this example, and
:: 'foo 1' and 'bar' are sample arguments to pass to it.
powershell -noprofile -c Start-Process -Verb RunAs powershell '-noexit -noprofile -ExecutionPolicy Bypass -c Set-Location -LiteralPath ''%CD:'=''''%''; ^& .\script.ps1 ''foo 1'' bar'

-noexit keeps the elevated session open after the specified .ps1 script terminates; -noexit在指定的.ps1脚本终止后保持提升的 session 打开; remove it, if you want the session and thereby its window to close automatically.如果您希望 session 及其 window 自动关闭,请将其删除。
-noprofile suppresses loading of the profile scripts; -noprofile禁止加载配置文件脚本; in the second powershell call, that isn't strictly necessary, but still advisable for a predictable execution environment.第二次powershell调用中,这不是绝对必要的,但对于可预测的执行环境来说仍然是可取的。

Note:笔记:

  • In order to avoid " -related escaping hell, the above solution uses '...' strings only, as understood by PowerShell in the context of a -c ( -Command ) CLI call, which, however, assumes the following:为了避免" -related escaping 地狱,上面的解决方案仅使用'...'字符串,正如 PowerShell 在-c ( -Command ) CLI调用的上下文中所理解的那样,但是,它假定以下内容:

    • The script file name / path itself and the pass-through arguments mustn't contain ' chars.脚本文件名/路径本身和传递 arguments 不得包含'字符。 - if they do, they must be enclosed in ''....'' and the embedded ' must be escaped as '''' (sic). - 如果这样做,则必须将它们括在''....''中,并且嵌入'必须转义为'''' (原文如此)。

      • For the Set-Location call above, this is handled automatically by using cmd.exe 's string-replacement technique on its %CD% variable ( %CD:'=''''% ).对于上面的Set-Location调用,这是通过在其%CD%变量 ( %CD:'=''''% ) 上使用cmd.exe的字符串替换技术自动处理的。
    • If the script file path or pass-through arguments contain spaces , there mustn't be runs of multiple spaces - if so (which would be very unusual in the case of paths), " -quoting would have to be used. Otherwise, values with spaces must be enclosed in ''...'' , as shown with the foo 1 argument above.如果脚本文件路径或传递 arguments 包含空格,则不能有多个空格的运行 - 如果是这样(这在路径的情况下是非常不寻常的),则必须使用" -引号。否则,值空格必须包含在''...''中,如上面的foo 1参数所示。

    • Since the script file is invoked via -c ( -Command ) rather than via -f ( -File ), the interpretation of arguments passed to it may situationally differ - see this answer .由于脚本文件是通过-c ( -Command ) 而不是-f (-File) 调用的,因此传递给它的-File的解释可能因情况而异 - 请参阅此答案


[1] There is a limited workaround: Execution policies only relate to script files , so reading a script file's content into memory and executing that - be it via constructing a script block first or by passing it directly to the usually-to-be-avoided Invoke-Expression - is a way to bypass the active execution policy. [1] 有一个有限的解决方法:执行策略仅与脚本文件相关,因此将脚本文件的内容读入 memory 并执行它 - 无论是首先构建脚本块还是将其直接传递给 usually-to-be- avoided Invoke-Expression - 是一种绕过主动执行策略的方法。 A simplified example:一个简化的例子:
powershell -noprofile -c "Invoke-Expression (Get-Content -Raw c:\path\to\foo.ps1)" . powershell -noprofile -c "Invoke-Expression (Get-Content -Raw c:\path\to\foo.ps1)" That said, the technique won't work if the code executed this way calls other script files, which may also happen implicitly when modules are auto-imported.也就是说,如果以这种方式执行的代码调用其他脚本文件,该技术将不起作用,这也可能在自动导入模块时隐式发生。

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

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