PowerShellでファイルを一括ダウンロード【非エンジニア向け】

# これは何?
エンジニアでない人でもちょっとしたコードを書いて仕事をサクッと終わらせるためのTipsの紹介を目的とした記事です。

# 注意事項
非IT企業にお勤めの方は、このTipsを後任に引継ぐような業務にはくれぐれも利用しないでください。
業務フローの変更などによりコードの修正が必要になった場合、後任の方に大きな負担がかかるだけでなく、業務の遅滞・停止に発展する可能性があります。
あくまでもご自身の作業の範囲で、涼しい顔で定時退社するデキるビジネスマンになるための秘密道具としてご活用ください。

# このTipsの利用シーン
イントラサイトなどから複数の資料を大量にダウンロードするような場面で効果的です。
ダウンロード先のフォルダやダウンロードした際のファイル名も指定できるので、ダウンロード後にファイルを移動したりリネームさせる手間を省くこともできます。

# PowerShellって?
Windowsに標準で搭載されているプログラム言語です。
コマンドプロンプト(黒い画面)のように一行ずつコマンド(命令)を書いて実行したり、今回紹介するような予め書いたコードを実行することもできます。
実行ファイルの拡張子は``.ps1``ですが、メモ帳などで作成したテキストファイルの拡張子を``.txt``から``.ps1``に変更してあげればOKです。
なお、Windowsには標準でISE(あいす)というエディタが標準で用意されており、そこでコードの記述や確認(デバッグ)などが行えます。

# サンプルスクリプト全文
まずはサンプルスクリプト(コード)全体を紹介します。(詳しい解説は後半に)
なお、元となった事例ではFTPサーバーに動画ファイルを、WebサーバーにPDF等の資料ファイルをそれぞれ保存していたため、それら2つのサーバーからファイルを取得する前提の内容になっています。

## PowerShell
```powershell
# ダウンロード用のフォルダを作成
New-Item 'C:\Users\Desktop\DownloadFile\Seminar01' -ItemType Directory

# FTPサーバーのUser・Pass・URLを定義
$user = 'SampleUser'
$pass = 'hogehoge'

# FTPログイン情報をcredに定義
$str = ConvertTo-SecureString $pass -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($user, $str)

# ファイルダウンロード(FTP)
Invoke-WebRequest -Uri "192.168.x.x/SeminarMovie.mp4" -OutFile "C:\Users\Desktop\DownloadFile\Seminar01\SeminarMovie.mp4" -Credential $cred
# ファイルダウンロード(HTTP)
Invoke-WebRequest -Uri "http://home.intra/SeminarText.pdf" -OutFile "C:\Users\Desktop\DownloadFile\Seminar01\SeminarText.pdf"
```
## BAT
```bat
echo 実行中...
powershell -NoProfile -ExecutionPolicy Unrestricted .\SampleScript.ps1
echo 実行完了
pause > nul
exit
```
# 解説
## PowerShell
### ダウンロード用のフォルダの作成
フォルダの作成は、
``New-Item '(作成したいフォルダのフルパス)' -ItemType Directory``
と書きます。

### FTPサーバーへのログイン情報の定義
FTPサーバーへのログインに必要なユーザーとパスワードを'cred'と名付けたオブジェクト(「クレデンシャルオブジェクト」という)に格納します。
なお、予めオブジェクト格納前にパスワードを``ConvertTo-SecureString (保護したい文字列) -AsPlainText -Force``でセキュリティで保護された文字列に変換しておきます。
※このとき、パラメータである``-AsPlainText -Force``も必ずセットで記述してください。
その後、新しいオブジェクトとして'cred'を定義し、``System.Management.Automation.PSCredential()``メソッドでユーザーやセキュリティ保護したパスワードを渡す流れになります。

### ファイルのダウンロード
FTPでもHTTPでも``Invoke-WebRequest -Uri "(ダウンロード元アドレス)" -OutFile "(ダウンロード先アドレス)"``と記述しますが、FTPでは後に上述のFTPサーバーへのログイン情報を付け加えます。
※なお、パラメータの``-Uri``は``-Url``と間違いがちなので要注意。
#### HTTP
```powershell
Invoke-WebRequest -Uri "http://home.intra/SeminarText.pdf" -OutFile "C:\Users\Desktop\DownloadFile\Seminar01\SeminarText.pdf"
```
#### FTP
```powershell
Invoke-WebRequest -Uri "192.168.x.x/SeminarMovie.mp4" -OutFile "C:\Users\Desktop\DownloadFile\Seminar01\SeminarMovie.mp4" -Credential $cred
```

## BAT
PowerShellファイル(.ps1)の実行方法はいくつかあリますが([参考](https://qiita.com/tomoko523/items/df8e384d32a377381ef9))、今回は別途作成したバッチファイル(.bat)から起動する方法を選択しました。
以下の一行がPowerShellファイルの実行部分なので、実質的にはこれだけ記述しておけば問題はありません。

```bat
powershell -NoProfile -ExecutionPolicy Unrestricted .\SampleScript.ps1
```

なお、``powershell``の後ろの各パラメータの意味等については以下のとおりです。
- ``-NoProfile`` ... 通常PowerShellファイル実行時に読み込む環境情報を、この時に限り読み込まない旨の設定
- ``-ExecutionPolicy Unrestricted`` ... デフォルトではPowerShellファイルを実行できないよう、実行ポリシー（セキュリティポリシー）が設定されていますが、それをこの時に限り``Unrestricted``(どんなPowerShellプログラムでも実行可能)に変更する旨の設定
※ 実行ポリシーを変更することでPowerShellファイルをダブルクリックするだけでもプログラムを実行できるようにすることもできますが、セキュリティーの観点から無闇に変更することはお勧めしません。

# 補足
ファイルのダウンロードをSystem.Net.WebClientクラスを直接呼び出して実行しようとした初期バージョンも参考に掲載しておきます。
なお、今回のように単純なファイルダウンロードの用途で、かつPowerShellのバージョン3.0以降であればInvoke-WebRequestを用いるのが一般的のようです。

```powershell
# FTPサーバーのUser・Pass・URLを定義
$user = 'SampleUser'
$pass = 'hogehoge'

# WebClientオブジェクトを定義
$wc = New-Object System.Net.WebClient
$wc.Credentials = New-Object System.Net.NetworkCredential($user,$pass)

# ファイルダウンロード(FTP)
$wc.DownloadFile("192.168.x.x/SeminarMovie.mp4","C:\Users\Desktop\DownloadFile\Seminar01\SeminarMovie.mp4")

```

# 参考
- [PowerShell 使い方メモ | Qiita](https://qiita.com/opengl-8080/items/bb0f5e4f1c7ce045cc57#%E5%8F%82%E8%80%83)
- [フォルダを作成する / ディレクトリを作成する : PowerShell | iPentec](https://www.ipentec.com/document/windows-powershell-create-directory)
- [Powershellを使ってFTPでデータ取得 | Qiita](https://qiita.com/arachan@github/items/896921ac232c1de97021)
- [ConvertTo-SecureString | Windows PowerShell のヘルプ](https://forsenergy.com/ja-jp/windowspowershellhelp/html/375ad5a7-1750-4061-9e8f-5888938efc31.htm)
- [PowerShell 関数への資格情報サポートの追加 - PowerShell | Microsoft Docs](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.2)
- [WebClient クラス (System.Net) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.net.webclient?view=net-6.0)
- [PowerShellでスクレイピング　前編　文字列を取得する | PowerShell Scripting Weblog](https://winscript.jp/powershell/304)
- [PowerShellで HTTPアクセスする いくつかの方法 | Qiita](https://qiita.com/kurukurupapa@github/items/c77b7be7f3c05453e75e)
- [Powershellを楽に実行してもらうには | Qiita](https://qiita.com/tomoko523/items/df8e384d32a377381ef9)
- [バッチファイルからPowershellのps1ファイルを実行する | heboDJ.net](https://hebodj.net/2020/06/13/%E3%83%90%E3%83%83%E3%83%81%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%8B%E3%82%89powershell%E3%81%AEps1%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B/)
- [実行ポリシーについて - PowerShell | Microsoft Docs](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.2)
- [PowerShellのPS1ファイルの作成と実行 | マイクロソフト系技術情報 Wiki](https://techinfoofmicrosofttech.osscons.jp/index.php?PowerShell%E3%81%AEPS1%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E4%BD%9C%E6%88%90%E3%81%A8%E5%AE%9F%E8%A1%8C)