はじめに
WinSCPはGUIでファイル転送が可能なアプリケーションである。
一方で.Netのアセンブリが提供されており、
プログラムから呼び出すことができる。
※アセンブリはWinSCPの実行ファイルが格納されているフォルダにWinSCPnet.dll
として格納されている。
これを利用して、PowerShell上でWinSCPでSCPプロトコルを用いた転送スクリプトを作成する。
スクリプト
#パラメータ定義
param(
[string]$HostName = "<デフォルトIPアドレス>",
[string]$UserName = "(デフォルトユーザ名)",
[string]$Password = "<デフォルトパスワード>",
[Parameter(Mandatory=$True)]
[ValidateSet("Get","Put")]
$transferType = "",
[Parameter(Position=0)]
[string]$sourcePath = "",
[Parameter(Position=1)]
[string]$destPath = ""
)
try
{
#ライブラリの読み込み
Add-Type -Path "<WinSCPnet.dllのパス>"
if([string]::IsNullOrEmpty($sourcePath)){
$sourcePath = Read-Host "取得先のリモートホストのパスを入力"
$sourcePath = $sourcePath.Trim('"',"'")
}
if([string]::IsNullOrEmpty($destPath)){
$destPath = Read-Host "保存先のディレクトリを入力"
$destPath = $destPath.Trim('"',"'")
}
#ディレクトリパスの末尾に"\"記号が無い場合追加
if( ! ($destPath.EndsWith("\") ) ){
$destPath += "\"
}
#セッション情報の設定
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{
Protocol = [WinSCP.Protocol]::Scp
HostName = $HostName
UserName = $UserName
Password = $Password
GiveUpSecurityAndAcceptAnySshHostKey = $True
}
#セッションを張る
$session = New-Object WinSCP.Session
$session.Open($sessionOptions)
try
{
#put/getで分岐
if( $transferType -eq "Get" ){#Get
#リモートホストからファイルを取得する。
$transferResult = $session.GetFiles($sourcePath, $destPath, $false)
}else{#Put
$fileName = Split-Path $sourcePath -Leaf
$transferResult = $session.PutFiles($sourcePath, "${destPath}${fileName}", $false)
}
$transferResult.Check()
#結果出力
foreach($transfer in $transferResult.Transfers) {
Write-Host "Source: $($transfer.FileName),succeeded"
Write-Host "Destination:$($transfer.Destination) "
}
}
finally
{
$session.Dispose()
}
}
catch
{
Write-Host "Error:$($_.Exception.Message)"
exit 1
}
書式
script [-HostName <System.String>] [-UserName <System.String>] [-Password <System.String>] -transferType <Get> | <Put> [[-sourcePath <System.String>] [-destPath <System.String>]]
制作時備忘
-
転送後の終了処理で
Session.Dispose
の場合オブジェクトを破棄する(リソースを開放)
Session.Close
を用いた場合、オブジェクトの再利用が可能。 -
WinSCPのGUIアプリで設定した「サイト」の情報は利用できない模様。
公式リファレンスを見ても「サイト」からセッションオプションの値を取得する方法は特に載っていなかった... -
SCPではputFileやgetFileメソッドはサポートされていない。
転送を行う際は単一のファイルの場合でもputFile
ではなく、putfiles
を使う。Getの場合も同様 -
ディレクトリのパスを指定する際に末尾にパス区切り文字がないとファイル名として認識されてしまうため、区切り文字を明示する必要有(最初この仕様に気づかず転送に成功したもののファイルが無いという現象が多発しました)
-
ファイル転送部分はtry-finallyで記述しエラーが発生した場合でも必ずオブジェクトが破棄されるようにしておく。
余談
今回のスクリプトまだちょっとプロトタイプ的な感じが強いです。
WinSCP自体は様々な転送プロトコルに対応しているので、
異なるプロトコルを画一された方法で利用できるという点は便利ですね。
参考