リモートマシン上のファイルをＤＬする方法（PowerShellとwinSCP.dllを使用）

## 初めに
実務にてリモートマシン上に保存されているファイルをDLする機会がありました。
ただし保存されているファイルが数千ファイル、容量は数十GB単位であり
手動DLが困難だった為スクリプト作成しDLする手法で対応しました。
スクリプト作成するにあたり、困ったことや時間を要したことがあったので
備忘録を兼ねてこの記事を作成しております。

## 作成したスクリプト
今回作成したスクリプトは以下となります。

:::note warn
秘匿情報が含まれている箇所がございましたので、その点は伏せております。
:::

<details><summary>作成スクリプト</summary>

```
#実行コマンド
# > powershell -ExecutionPolicy Bypass .\実行ファイル名.ps1

#ダウンロード元のフルパス
$remote_folder_path = "/test/"
#ダウンロードするファイルの名前（ワイルドカード使用可能）
$remote_file_name = 'DLtest1.txt'

#リネーム前のファイルをダウンロードするパス
#こちらはフルパスとなるのでフォルダ階層で指定すると「ファイルではありません。」のエラーが発生する。
$local_path="C:\samplePath\DLtest1.txt"
#リネーム後のファイルを格納するパス
#恐らくだが、こちらもフルパスとなるのでフォルダ階層で指定すると「ファイルではありません。」のエラーが発生する。
#$send_folder_path="C:\samplePath\DLFolder"

#ダウンロード元フォルダパスとファイル名を結合してダウンロードするファイルのプルパスを作成
$remote_path = $remote_folder_path + $remote_file_name

#WinSCPnet.dllへのパス
Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"

#接続設定
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{
    Protocol = [WinSCP.Protocol]::Ftp
    HostName = "IPアドレス"
    PortNumber = portNumber(ex:123)
    UserName = "userName"
    Password = "password"
    GiveUpSecurityAndAcceptAnyTlsHostCertificate = $true
    FtpMode = [WinSCP.FtpMode]::Active
    FtpSecure = "Implicit"
    #GiveUpSecurityAndAcceptAnySshHostKey = $true
    #FtpSecure = [WinSCP.FtpSecure]::Implicit

    #暗黙のSSL/TLS接続として繋ぐ。
    #SshHostKeyFingerprint = ''
}

$sftp_session = New-Object WinSCP.Session
$sftp_session.SessionLogPath = "C:\samplePath\winscp.log"
#接続
$sftp_session.Open($sessionOptions)

#バイナリモード
$sftp_transfer_options = New-Object WinSCP.TransferOptions
$sftp_transfer_options.TransferMode = [WinSCP.TransferMode]::Binary

try{
    #ダウンロードしたファイルをリモートから削除する場合はtrue
    $file_remove = $false

    #指定ディレクトリのファイルを指定ファイル名に一致するファイルを全部ダウンロード
    $sftp_transfer_result = $sftp_session.GetFiles($remote_path,$local_path,$file_remove,$sftp_transfer_options)
    $sftp_transfer_result.Check()

    #ログ出力
    foreach($transfer in $sftp_transfer_result.Transfers){
        Write-Output "Download of $($transfer.FileName) succeeded"
    }
}finally{
    $sftp_session.Dispose()
}
```
</details>


## 解説
作成スクリプトの要所について解説します。

セキュリティ的には好ましくないが、実行ポリシーはすべてのスクリプトの実行を許可で設定しました。
```
powershell -ExecutionPolicy Bypass .\実行ファイル名.ps1
```

リモートマシンのFW制約として、21番・22番ポートを公開しない条件があった
暗黙のSSL/TLS接続してDLする手法で解決しました。
その他のオプションについては下記のリファレンスが参考になります。
https://winscp.net/eng/docs/library
```
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{
    Protocol = [WinSCP.Protocol]::Ftp
    HostName = "IPアドレス"
    PortNumber = portNumber(ex:123)
    UserName = "userName"
    Password = "password"
    GiveUpSecurityAndAcceptAnyTlsHostCertificate = $true
    FtpMode = [WinSCP.FtpMode]::Active
    FtpSecure = "Implicit"
    #GiveUpSecurityAndAcceptAnySshHostKey = $true
    #FtpSecure = [WinSCP.FtpSecure]::Implicit

    #暗黙のSSL/TLS接続として繋ぐ。
    #SshHostKeyFingerprint = ''
}
```

バイナリモードでファイル転送するための設定となります。
```
$sftp_transfer_options = New-Object WinSCP.TransferOptions
$sftp_transfer_options.TransferMode = [WinSCP.TransferMode]::Binary
```

ダウンロードしたファイルをリモートマシンから削除したい場合は下記オプションをtrueで設定で対応できました。
```
$file_remove = $false
```

# 記事更新予定
今回はCLIでwinSCPを使用しておりましたが上記コマンドがGUIではどこに対応しているか追記予定です。