LinuxからWindowsにバッチでファイルを定期的に移動する方法(逆もできるよ！)

# やりたいこと
ファイルをバックアップするときなど、LinuxからWindowsへ、WindowsからLinuxへファイルをコピーや
移動したい場合があります。

いろいろ方法はあると思うのですが、WinSCPでは.NET Assemblyが公開されているので使ってみることにしました。

# 必要なもの
* [WinSCP](http://winscp.net/eng/docs/library)
* [WinSCP .NET Assembly](http://winscp.net/eng/docs/library)

# 説明
C#で作ろうかと思ったのですが、簡単にかけるPowerShellで作りました。
こちらの例では、Linuxのサーバ(sessionOptions.HostNameに指定)にあるファイルをWindowsのPC(PowerShellが動いているPC)に移動してます。

なお、パスワード(sessionOptions.Password)がコメントアウトしてあるのはpagentを用いてSSH鍵認証を行っているためです。必要であればパスワードを書いてください。

ほぼWinSCPのサイトにあるサンプルのままですけど(^_^)

```ps1:backup.ps1
try
{
	# Load Windows Form
	[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
	
    # Load WinSCP .NET assembly (パスは環境によって変更してください)
    [Reflection.Assembly]::LoadFrom("C:\Program Files\WinSCP\WinSCPnet.dll") | Out-Null
 
    # Setup session options
    $sessionOptions = New-Object WinSCP.SessionOptions
    $sessionOptions.Protocol = [WinSCP.Protocol]::Sftp
    $sessionOptions.HostName = "【接続先ホスト名】"
    $sessionOptions.UserName = "【ユーザ名】"
    #$sessionOptions.Password = "【パスワード】"
    $sessionOptions.SshHostKeyFingerprint = "【フィンガープリント 例: ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx】"
 
    $session = New-Object WinSCP.Session
 
    try
    {
        # Connect
        $session.Open($sessionOptions)
 
        # Upload files バイナリモードを設定
        $transferOptions = New-Object WinSCP.TransferOptions
        $transferOptions.TransferMode = [WinSCP.TransferMode]::Binary
        
        #リモートマシンの"/tmp/backup/*"を"C:\tmp\backup\"に「移動」。 ３つめの引数を$FALSEにするとコピー
        $transferResult = $session.GetFiles("/tmp/backup/*","C:\tmp\backup\", $TRUE, $transferOptions)
 
        # Throw on any error
        $transferResult.Check()
 
        # Print results
        foreach ($transfer in $transferResult.Transfers)
        {
            Write-Host ("Download of {0} succeeded" -f $transfer.FileName)
        }
    }
    finally
    {
        # Disconnect, clean up
        $session.Dispose()
    }
 	
    exit 0
}
catch [Exception]
{
    #エラーが出たらダイアログを出して気がついてもらう
   	[System.Windows.Forms.MessageBox]::Show($_.Exception.Message, "バックアップエラー！",[Windows.Forms.MessageBoxButtons]::OK,[Windows.Forms.MessageBoxIcon]::Error);
    exit 1
}
```

# 後日追記
PowerShellをVersion3にしたところ、[Reflection.Assembly]::LoadFrom("C:\Program Files\WinSCP\WinSCPnet.dll") でエラーが出るようになった。

>ファイルまたはアセンブリ 'file:///C:\Program Files\WinSCP\WinSCPnet.dll'、またはその依存関係の 1 つが読み込
めませんでした。操作はサポートされません。 (HRESULT からの例外:0x80131515)

さっぱり原因がわかりませんでしたが、WinSCPのフォーラムで意外な解決策が提示されてました。 [Topic "Powershell : Could not load file or assembly winscp.dll"](http://winscp.net/forum /viewtopic.php?t=12006)

>[Reflection.Assembly]::LoadFrom("C:\Program Files\WinSCP\WinSCPnet.dll")

を

>[Reflection.Assembly]::LoadFrom("\\\C:\Program Files\WinSCP\WinSCPnet.dll")

に・・・ファイルパスの前に"\\\"追加したら動きました。

# もっと後日追記(2018/07/20)
久々にPCを入れ替えたら実行されなくなっていた。いろいろ調べた結果、dllファイルの「ブロック解除」が必要でした。

* [[Powershell]DLL読み込みで「操作はサポートされていません」エラーは「ブロック解除」する](https://sevenb.jp/wordpress/ura/2016/07/14/powershelldll%e8%aa%ad%e3%81%bf%e8%be%bc%e3%81%bf%e3%81%a7%e3%80%8c%e6%93%8d%e4%bd%9c%e3%81%af%e3%82%b5%e3%83%9d%e3%83%bc%e3%83%88%e3%81%95%e3%82%8c%e3%81%a6%e3%81%84%e3%81%be%e3%81%9b%e3%82%93/)