Webからファイルをダウンロードしたいとき、PowerShellならInvoke-WebRequestコマンド1つで実現できます。wgetやcurlのように、URLを指定してファイルを保存できます。インストーラーやデータファイルの自動取得、スクリプトでの定期ダウンロードなどに便利です。
ただしWindows PowerShell 5.1には、知らないとハマる3つの落とし穴があります。①進捗バーのせいで極端に遅くなる、②-UseBasicParsingを付けないとエラーになる、③HTTPSサイトでTLS 1.2を明示しないと接続できないことです。この記事では、実機のWindows PowerShell 5.1で実際にダウンロードしながら、これらの対策を整理します。
- 基本は
Invoke-WebRequest -Uri "URL" -OutFile "保存先"です。 $ProgressPreference = "SilentlyContinue"で劇的に速くなります(進捗バーが重い)。- Windows PowerShell 5.1では
-UseBasicParsingが必須(無いとエラーになることがある)。 - HTTPSは
[Net.ServicePointManager]::SecurityProtocolでTLS 1.2を明示します。 - APIのJSONを取得するなら
Invoke-RestMethod(自動でオブジェクト化)。 - 失敗に備えて
try-catchとリトライを入れると安定します。
保存先の確認はファイル・フォルダ操作(Test-Path)、APIのJSON処理はJSONを読み書きする(ConvertFrom-Json)、失敗時の対処はtry-catchでのエラー処理もあわせて参考になります。
基本:Invoke-WebRequestでダウンロード
もっとも基本的な使い方は、-UriにURL、-OutFileに保存先を指定します。これだけでファイルがダウンロードされ、保存されます。
# URL を指定してファイルを保存 Invoke-WebRequest -Uri "https://example.com/file.zip" -OutFile "C:\temp\file.zip" # iwr というエイリアス(短縮名)でも書ける iwr "https://example.com/file.zip" -OutFile "C:\temp\file.zip"
実機でも、Invoke-WebRequest -Uri "URL" -OutFile "保存先"で、3,662バイトのファイルが正しくダウンロード・保存されることを確認しました。-OutFileを指定するとファイルに保存され、指定しない場合はレスポンスの内容がメモリ上に返ります。iwrという短い別名も使えます。基本はこれだけですが、Windows PowerShell 5.1では次の対策が重要になります。
【高速化】$ProgressPreferenceで劇的に速くなる
Windows PowerShell 5.1のInvoke-WebRequestは、ダウンロード中に進捗バーを描画するのですが、これが非常に重く、ダウンロードを何倍も遅くします。進捗バーを止めるだけで、驚くほど速くなります。
# これを実行する前に1行入れるだけで劇的に速くなる $ProgressPreference = "SilentlyContinue" Invoke-WebRequest -Uri "https://example.com/big.zip" -OutFile "C:\temp\big.zip" -UseBasicParsing # 元に戻したいときは # $ProgressPreference = "Continue"
実機で同じファイルを、進捗バーあり・なしでダウンロードして時間を比較したところ、進捗バーあり=154ミリ秒、進捗バーなし=14ミリ秒と、約11倍の差が出ました(小さなファイルでもこれだけ違い、大きなファイルではさらに差が広がります)。原因は、Windows PowerShell 5.1のInvoke-WebRequestが、ダウンロードの進捗バーを頻繁に再描画するためです。$ProgressPreference = "SilentlyContinue"を1行入れて進捗バーを止めるだけで、この描画コストが無くなり、本来の速度でダウンロードできます。大きなファイルや複数ファイルをダウンロードするスクリプトでは、必ず入れておきたい一行です。
【PS5.1必須】-UseBasicParsing
Windows PowerShell 5.1のInvoke-WebRequestは、標準ではInternet Explorerのエンジンを使ってHTMLを解析しようとします。そのため、IEが使えない環境では-UseBasicParsingを付けないとエラーになることがあります。
# -UseBasicParsing を付けるとIEに依存せず動く(PS5.1では実質必須) $resp = Invoke-WebRequest -Uri "https://example.com/" -UseBasicParsing $resp.StatusCode # 200 $resp.Content # 本文(HTMLやテキスト) # 付けないと「オブジェクト参照がインスタンスに設定されていません」 # のようなエラーになることがある
実機で確認したところ、-UseBasicParsingを付けずにInvoke-WebRequestのレスポンス内容(.Content)にアクセスしようとすると、オブジェクト参照がオブジェクト インスタンスに設定されていませんというエラーになりました。これは、Windows PowerShell 5.1がIEのHTML解析エンジンを使おうとして、それが利用できないために起こります。-UseBasicParsingを付けると、IEに依存しない簡易パーサーが使われ、正しく動作します(StatusCode=200、本文も取得できました)。Windows PowerShell 5.1では-UseBasicParsingを常に付けると覚えておくと安全です。なお、ファイルへ保存する-OutFileだけなら付けなくても動くことがありますが、付けておいて損はありません。
【HTTPS】TLS 1.2を有効にする
もう1つのハマりどころがTLS(暗号化通信)のバージョンです。Windows PowerShell 5.1は、環境によっては古いTLS 1.0で接続しようとするため、TLS 1.2以上しか受け付けない最近のHTTPSサイトに接続できず、エラーになることがあります。接続前にTLS 1.2を明示します。
# HTTPS接続の前に、TLS 1.2 を使うよう設定する [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 # これで TLS 1.2 必須のサイトにも接続できる Invoke-WebRequest -Uri "https://example.com/file.zip" -OutFile "C:\temp\file.zip" -UseBasicParsing
実機でも、TLS 1.2を明示してからHTTPSのURLにアクセスすると、正しくダウンロードできました(GitHubの生ファイルなど、TLS 1.2が必要なサイトでも成功)。「要求が中止されました: SSL/TLS のセキュリティで保護されているチャネルを作成できませんでした」のようなエラーが出たら、このTLS 1.2の設定が抜けていないか確認してください。HTTPSサイトを扱うスクリプトでは、冒頭でTLS 1.2を設定しておくと安心です。
APIのJSONを取得する Invoke-RestMethod
Web APIからJSONを取得したい場合は、Invoke-WebRequestではなくInvoke-RestMethodが便利です。JSONを自動でPowerShellのオブジェクトに変換してくれるため、そのままプロパティにアクセスできます。
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# JSON を返す API を呼ぶ → 自動でオブジェクトになる
$data = Invoke-RestMethod -Uri "https://api.github.com/repos/git/git" `
-Headers @{ "User-Agent" = "PowerShell" } -UseBasicParsing
$data.name # git
$data.language # C
$data.stargazers_count # スター数
実機でも、Invoke-RestMethodでGitHub APIを呼ぶと、JSONが自動でオブジェクトに変換され、$data.nameでgit、$data.languageでCのように、プロパティに直接アクセスできました。Invoke-WebRequestはレスポンス全体(ヘッダーや本文の文字列)を返すのに対し、Invoke-RestMethodはJSONを解析した結果を返す点が違います。APIを叩くならInvoke-RestMethod、ファイルを落とすならInvoke-WebRequest -OutFile、と使い分けます。なお、多くのAPIはUser-Agentヘッダーが無いと拒否するため、付けておくと安全です。取得したJSONの扱いはJSONを読み書きする方法も参考になります。
エラー処理とリトライ
ネットワークは失敗することがあります。try-catchで囲み、失敗したら少し待ってリトライ(再試行)する仕組みを入れると、スクリプトが安定します。
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$ProgressPreference = "SilentlyContinue"
$url = "https://example.com/file.zip"
$out = "C:\temp\file.zip"
$maxRetry = 3
for ($i = 1; $i -le $maxRetry; $i++) {
try {
Invoke-WebRequest -Uri $url -OutFile $out -UseBasicParsing -ErrorAction Stop
Write-Host "ダウンロード成功"
break
} catch {
Write-Host "失敗($i 回目): $($_.Exception.Message)"
if ($i -lt $maxRetry) { Start-Sleep -Seconds 3 } # 3秒待って再試行
}
}
forループで最大3回までリトライし、成功したらbreakで抜けます。失敗するたびにStart-Sleepで少し待つと、一時的なネットワークの不調を乗り越えやすくなります。-ErrorAction Stopを付けることで、ネットワークエラーがcatchで確実に捕まえられます(詳しくはtry-catchでのエラー処理を参照)。
主なポイントまとめ
PowerShellでのダウンロードの要点をまとめます。
| 項目 | 対策 |
|---|---|
| 基本 | Invoke-WebRequest -Uri URL -OutFile 保存先 |
| 速度が遅い | $ProgressPreference = "SilentlyContinue" |
| エラーになる(PS5.1) | -UseBasicParsingを付ける |
| HTTPSで接続できない | TLS 1.2を明示する |
| APIのJSON取得 | Invoke-RestMethodを使う |
| 失敗に備える | try-catch+リトライ |
よくある失敗
ダウンロードが異常に遅い
進捗バーの描画が原因です。$ProgressPreference = "SilentlyContinue"を入れます。
オブジェクト参照のエラーが出る
PS5.1のIE依存が原因です。-UseBasicParsingを付けます。
HTTPSサイトに接続できない
TLS 1.2が有効でない可能性があります。SecurityProtocolでTLS 1.2を明示します。
APIのレスポンスが文字列で扱いにくい
Invoke-RestMethodを使うとJSONが自動でオブジェクトになります。
一時的なエラーで止まる
try-catchとリトライを入れて、再試行で乗り越えます。
よくある質問
Invoke-WebRequest -Uri "URL" -OutFile "保存先"を使います。URLのファイルが保存先にダウンロードされます。Windows PowerShell 5.1では、速度のために$ProgressPreference = "SilentlyContinue"、安定のために-UseBasicParsingを付けるのがおすすめです。Invoke-WebRequestは、進捗バーの描画が重く、ダウンロードを何倍も遅くします。実機でも進捗バーあり/なしで約11倍の差が出ました。$ProgressPreference = "SilentlyContinue"を1行入れて進捗バーを止めると、劇的に速くなります。Invoke-WebRequestがIE(Internet Explorer)の解析エンジンに依存しているためです。-UseBasicParsingを付けると、IEに依存しない簡易パーサーが使われ、エラーを回避できます。PS5.1では常に付けておくと安全です。[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12を実行してTLS 1.2を明示してください。最近のHTTPSサイトはTLS 1.2以上が必須のことが多いです。Invoke-WebRequestはレスポンス全体(ヘッダーや本文の文字列、ステータスコード)を返します。Invoke-RestMethodはJSONを自動でオブジェクトに変換して返すため、APIを叩くのに向いています。ファイルを保存するならInvoke-WebRequest -OutFile、JSONを扱うならInvoke-RestMethodを使い分けます。まとめ
- 基本は
Invoke-WebRequest -Uri URL -OutFile 保存先です。 - 速度は
$ProgressPreference = "SilentlyContinue"で約10倍改善します。 - PS5.1では
-UseBasicParsingを付けてIE依存を回避します。 - HTTPSはTLS 1.2を明示して接続エラーを防ぎます。
- APIのJSONは
Invoke-RestMethod、失敗対策はtry-catch+リトライ。
PowerShellでのダウンロードはInvoke-WebRequest一発でできますが、Windows PowerShell 5.1では「進捗バーを止める」「-UseBasicParsing」「TLS 1.2」の3点を押さえることが安定と速度のカギです。これらをスクリプトの冒頭に入れておけば、ファイル取得やAPI連携を快適に自動化できます。なお、PowerShell 7ではこれらの対策はほぼ不要(既定で速く、TLS 1.2、IE非依存)になっています。
