Edited at

PowerShellでNASにファイルをアップロードする

More than 3 years have passed since last update.

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


参考