从 HTTP 下载脚本并使用 Powershell 使用参数运行它的最短方法是什么?

Tom*_*nik 3 powershell

我有一个 PowerShell 脚本文件存储在内部工件服务器中。脚本网址为http://company-server/bootstrap.ps1.

下载该脚本并使用自定义参数执行的简洁方法是什么?

我想将这样的命令发送给用户,他们会一遍又一遍地复制粘贴它,因此它必须是单行并且应该很短。

我目前所做的工作,但它又长又笨拙:

$c=((New-Object System.Net.WebClient).DownloadString('http://company-server/bootstrap.ps1'));Invoke-Command -ScriptBlock ([Scriptblock]::Create($c)) -ArgumentList 'RunJob'
Run Code Online (Sandbox Code Playgroud)

我想知道是否有更短的方法来做到这一点。

mkl*_*nt0 6

注意:从代码高尔夫的角度来看,通过消除无关紧要的空白,可以进一步缩短下面的解决方案;例如, &{$args[0]}hi而不是 & { $args[0] } hi. 然而,为了可读性,保留了这样的空白。

通过 HTTP 下载脚本并在本地执行(可选地使用参数)的命令的简短表述可能是这样的,利用:

  • 别名,irm代替Invoke-RestMethod(New-Object System.Net.WebClient).DownloadString()
  • 省略不必要的引用
  • 依赖位置参数绑定
& ([scriptblock]::Create((irm http://company-server/bootstrap.ps1))) RunJob
Run Code Online (Sandbox Code Playgroud)

RunJob是 OP 传递给脚本的自定义参数。

一种更短但可能更晦涩的方法是使用 的iex内置别名,由GitHub 评论Invoke-Expression提供。

iex "& { $(irm http://company-server/bootstrap.ps1) } RunJob"
Run Code Online (Sandbox Code Playgroud)

顺便说一句:在一般使用中,应避免使用 Invoke-Expression

该命令使用可扩展字符串("..."字符串插值)创建一个字符串,其中远程脚本的内容包含在脚本块中{ ... },然后在子作用域 ( &) 中调用该字符串。请注意传递给脚本的参数必须位于 "...".


但是,有一个一般警告(这对您来说似乎不是问题):如果脚本以 终止exit,则调用的 PowerShell 实例也会退出

有两种解决方法


在子进程中运行脚本:

powershell { iex "& { $(irm http://company-server/bootstrap.ps1) } RunJob" }
Run Code Online (Sandbox Code Playgroud)

注意事项:

  • 以上仅适用于 PowerShell 内;在 PowerShell 外部,您必须使用powershell -c "..."代替powershell { ... },但请注意,如果需要的话,正确转义嵌入的双引号(对于带有 PS 元字符和/或带有空格的自定义参数的 URL)可能会很棘手。

  • 如果脚本旨在修改调用者的环境,则修改将由于在子进程中运行而丢失。


首先将脚本保存到临时文件

注意:为了便于阅读,该命令分布在多行中,但它也可以作为一行使用:

& {
  $f = Join-Path ([IO.Path]::GetTempPath()) ([IO.Path]::GetRandomFileName() + '.ps1'); 
  irm http://company-server/bootstrap.ps1 > $f;
  & $f RunJob;
  ri $f
}
Run Code Online (Sandbox Code Playgroud)

明显的缺点是命令更长。

请注意,该命令在编写时考虑到了稳健性和跨平台兼容性,因此它也可以在所有支持的平台上的 PowerShell Core中运行。根据您需要支持的平台/您愿意做出的假设(例如,当前目录是可写的),可以缩短命令。


未来潜在的增强功能

GitHub 问题 #5909,从 PowerShell Core 6.2.0-preview.4 开始编写,并从 PowerShell Core 7.0 开始修订,建议增强
Invoke-Command( icm) cmdlet 以大大简化下载脚本和执行场景,以便您可以调用脚本问题如下:

# WISHFUL THINKING as of PowerShell Core 7.0
# iwr is the built-in alias for Invoke-WebRequest
# icm is the built-in alias for Invoke-Command.
iwr http://company-server/bootstrap.ps1 | icm -Args RunJob
Run Code Online (Sandbox Code Playgroud)

GitHub 问题 #8835更进一步,建议创建一个 RFC 来引入一个新的 PowerShell提供程序,允许在以前只接受文件的地方使用 URL,从而实现以下调用:

# WISHFUL THINKING as of PowerShell Core 7.0
& http://company-server/bootstrap.ps1 RunJob
Run Code Online (Sandbox Code Playgroud)

然而,虽然这些选项非常方便,但也需要考虑安全隐患。