PowerShellからNASにファイルコピーするのにPowerShellのバージョン差分でハマったのでメモ。
PowerShell3.0(Windows8)だけで動けば良い場合
SMBでコピーする場合はGuest認証でも認証フェーズが必要なので、自分でクレデンシャルを生成してNew-PSDriveに渡してやることでPSドライブにマウントができるようになるので、後はCopy-Itemとかでコピーすればよい。サンプルコードこんなかんじ。
# ローカルファイル
$localFile = "test.log"
# アップロード先
$uploadServer = "\\xxx.xxx.xxx.xxx\hoge"
$uploadDir = "fuga"
$uploadFile = "test.log"
# アップロード用のゲスト認証Credentialを生成する
$uploadUser = "Guest"
$uploadPass = "Guest"
$secStr = ConvertTo-SecureString $uploadPass -AsPlainText -Force
$cred = New-Object System.Management.Automation.PsCredential($uploadUser, $secStr)
# PSドライブにマウントする
$psDriveName = "TestDrive"
if(Get-PSDrive | where {$_.Name -eq $psDriveName}){
# エラー終了などで既に存在する場合は一旦アンマウントする
Remove-PSDrive -Name $psDriveName
}
$uploadDrive = New-PSDrive -Name $psDriveName -PSProvider FileSystem -Root $uploadServer -Credential $cred
# アップロードする
$uploadUri = "" + $psDriveName + ":" + $uploadDir + "\" + $uploadFile
Copy-Item $localFile $uploadUri
# PSドライブをアンマウントする
Remove-PSDrive -Name $psDriveName
PowerShell2.0(Windows7)でも動かないといけない場合
PowerShell2.0だと、New-PSDriveにCredentialが渡せなくて同じ方法だと資格情報のエラーになってしまいます。調べたところBitsTransferというのを使えばPowerShell2.0でも3.0でも動いた。OSのキャッシュ状態によってネットワークドライブが見えなかったりすることがあるようなので、前後で明示的にnet use使うとよいっぽい。
サンプルコードこんなかんじ。
# ローカルファイル
$localFile = "test.log"
# アップロード先
$uploadServer = "\\xxx.xxx.xxx.xxx\hoge"
$uploadDir = "fuga"
$uploadFile = "test.log"
$uploadUri = "" + $uploadServer + "\" + $uploadDir + "\" + $uploadFile
# アップロード用のゲスト認証Credentialを生成する
$uploadUser = "Guest"
$uploadPass = "Guest"
$secStr = ConvertTo-SecureString $uploadPass -AsPlainText -Force
$cred = New-Object System.Management.Automation.PsCredential($uploadUser, $secStr)
# ネットワークドライブを登録する
net use $uploadServer $uploadPass /user:$uploadUser
# アップロードする
Import-Module -Name BitsTransfer
Start-BitsTransfer -Source $localFile -Destination $uploadUri -Credential $cred
# ネットワークドライブを削除する
net use /delete $uploadServer