[英]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,它本身不涉及脚本的执行文件):
-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). - 如果这样做,则必须将它们括在''....''
中,并且嵌入'
必须转义为''''
(原文如此)。
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.