😎

Invoke-WebRequest を圧倒的に高速化する

2024/07/11に公開

TL;DR

  • Invoke-WebRequest を高速化し隊
  • $ProgressPreference = 'SilentlyContinue'$ProgressPreference = 'Continue' で挟むだけなので副作用はほぼ無い
  • 圧倒的に速くなるので PowerShell 5.1 系を使うことが多い Windows Server では絶対使ったほうがいい

はじめに

Invoke-WebRequest、自動化の仕組みの中で PowerShell で .msi なり .exe をダウンロードして msiexec で実行、みたいなパターンで使われることが多いですよね。
ただ、端的にいって、結構遅くて、ブラウザでダウンロードするときの方が全然早いのになぁ、と常に思っていました。
んで、調べてみたところ、プログレス バー的なあれを出さないと圧倒的に高速化できるみたいです。

なお、環境としては PowerShell 5.1 系が対象で、7 系はそもそも遅くないです。

PS C:\Users\ikko\Downloads> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.22621.3880
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.22621.3880
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

高速化する前

AVD の RDAgent の msi をダウンロードしてみようと思います。
シンプルに Invoke-WebRequest を実行した場合、20 秒くらいかかっています。

PS C:\Users\ikko\Downloads> Measure-Command { Invoke-WebRequest -Uri https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RWrmXv -OutFile .\Microsoft.RDInfra.RDAgent.Installer-x64.msi; Remove-Item .\Microsoft.RDInfra.RDAgent.Installer-x64.msi }


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 20    <<<<<<<< ここ、20 秒ってこと
Milliseconds      : 95
Ticks             : 200958357
TotalDays         : 0.000232590690972222
TotalHours        : 0.00558217658333333
TotalMinutes      : 0.334930595
TotalSeconds      : 20.0958357
TotalMilliseconds : 20095.8357

高速化した後

Invoke-WebRequest の前に $ProgressPreference = 'SilentlyContinue' を追加して、実行後の部分には $ProgressPreference = 'Continue' を追加します。
これだけで、文字どおり、秒で終わる ように変わります。

PS C:\Users\ikko\Downloads> Measure-Command { $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest -Uri https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RWrmXv -OutFile .\Microsoft.RDInfra.RDAgent.Installer-x64.msi; Remove-Item .\Microsoft.RDInfra.RDAgent.Installer-x64.msi; $ProgressPreference = 'Continue' }


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 446    <<<<<<<< ここ、0.446 秒ってこと
Ticks             : 4460986
TotalDays         : 5.16317824074074E-06
TotalHours        : 0.000123916277777778
TotalMinutes      : 0.00743497666666667
TotalSeconds      : 0.4460986
TotalMilliseconds : 446.0986

まとめ

ということで、何かと使いがちな Invoke-WebRequest ですが、高速化する方法を紹介しました。
プログレスバーを非表示にするだけで、こんなに速くなるとは思わず、感動しました。

参考

  • amazon ec2 - Powershell - Why is Using Invoke-WebRequest Much Slower Than a Browser Download?

    9 年前の質問ですが、まだまだ有効な情報でした、ありがたい

https://stackoverflow.com/questions/28682642/powershell-why-is-using-invoke-webrequest-much-slower-than-a-browser-download

  • Invoke-WebRequest (Microsoft.PowerShell.Utility) - PowerShell

https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/invoke-webrequest?wt.mc_id=MVP_391314

Discussion