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

时间:2019-01-28 19:25:15

标签: powershell

我有一个PowerShell脚本文件存储在内部工件服务器中。脚本URL为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'

我想知道是否有更短的方法。

2 个答案:

答案 0 :(得分:1)

一个简短的命令,它可以通过HTTP下载脚本并在本地执行该脚本(可选地带有参数),这可以利用以下优点:

  • irm的别名Invoke-RestMethod代替(New-Object System.Net.WebClient).DownloadString()
  • 在不必要的地方省略报价
  • 依靠位置参数绑定
& ([scriptblock]::Create((irm http://company-server/bootstrap.ps1))) RunJob

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

一种甚至更简短但也许更晦涩的方法是使用iex ,这是Invoke-Expression的内置别名,由this GitHub comment提供。

iex "& { $(irm http://company-server/bootstrap.ps1) } RunJob"

顺便说一句:一般使用Invoke-Expression should be avoided

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


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

有两种解决方法


子进程中运行脚本:

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

注意事项:

  • 以上内容仅可在PowerShell中使用;从PowerShell外部,必须使用powershell -c "..."而不是powershell { ... },但是请注意,如果需要,请正确转义 embedded 双引号(对于带有PS元字符和/或自定义的URL带有空格的参数)可能会变得棘手。

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


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

注意:该命令分布在多行上,以提高可读性,但它也可以用作单行代码:

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

明显的缺点是命令要长得多。

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


潜在的未来增强功能

This GitHub issue(自PowerShell Core 6.2.0-preview.4起编写)建议增强
Invoke-Commandicm)cmdlet,以大大简化下载脚本和-执行方案,以便您可以按以下方式调用有问题的脚本:

# WISHFUL THINKING as of PowerShell Core 6.2.0-preview.4
icm -FileUri http://company-server/bootstrap.ps1 RunJob

或者,如果需要对下载方面进行更多控制(例如,传递凭据):

# WISHFUL THINKING as of PowerShell Core 6.2.0-preview.4
irm http://company-server/bootstrap.ps1 | icm -FromPipeline RunJob

答案 1 :(得分:0)

这是一个较短的解决方案(158个字符)

$C=(New-Object System.Net.WebClient).DownloadString("http://company-server/bootstrap.ps1");icm -ScriptBlock ([Scriptblock]::Create($c)) -ArgumentList "RunJob"

这里是121

$C=(curl http://company-server/bootstrap.ps1).content;icm -ScriptBlock ([Scriptblock]::Create($c)) -ArgumentList "RunJob"

这里是108

$C=(curl http://company-server/bootstrap.ps1).content;icm ([Scriptblock]::Create($c)) -ArgumentList "RunJob"

这里是98

$C=(iwr http://company-server/bootstrap.ps1).content;icm -sc([Scriptblock]::Create($c)) -ar RunJob

感谢Ansgar Wiechers

相关问题