Skip to content

Instantly share code, notes, and snippets.

@CookieBox26
Created December 6, 2025 04:56
Show Gist options
  • Select an option

  • Save CookieBox26/906e75e5c227c58043fa1aec6990656c to your computer and use it in GitHub Desktop.

Select an option

Save CookieBox26/906e75e5c227c58043fa1aec6990656c to your computer and use it in GitHub Desktop.
WinSCP の .NET アセンブリを使用して FTPS ディレクトリ同期する PowerShell スクリプト
<#
PowerShell: WinSCP を使って FTPS (explicit) で同期するスクリプト
#>
param(
[string] $accountName = "{FTPアカウント}",
[string] $HostName = "{FTPサーバ名}",
[string] $LocalPath = (Join-Path $PSScriptRoot "site"),
[string] $RemotePath = "/home/{FTPアカウント}/www",
[string] $LogFile = (Join-Path $PSScriptRoot "log.txt")
)
# ----- WinSCP .NET アセンブリ読み込み -----
$assemblyPath = "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"
if (-not (Test-Path $AssemblyPath)) { throw "WinSCPnet.dll not found: $AssemblyPath" }
Add-Type -Path $AssemblyPath
# ----- Credential 入力 -----
$pass = Read-Host "Enter password for $accountName" -AsSecureString # パスワード入力を促す
$cred = New-Object System.Management.Automation.PSCredential($accountName, $pass)
# ----- セッションオプション設定 -----
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{
Protocol = [WinSCP.Protocol]::Ftp
HostName = $HostName
UserName = $cred.UserName
FtpSecure = [WinSCP.FtpSecure]::Explicit
}
# ----- 同期の設定 -----
$direction = [WinSCP.SynchronizationMode]::Remote # 同期の向き: ローカルからリモートに送る
$remove = $false # 送り側にないファイルを削除するか: しない
$mirror = $false # 送り側のタイムスタンプのほうが古いとき上書きするか: しない
$to = New-Object WinSCP.TransferOptions
$criteria = [WinSCP.SynchronizationCriteria]::Time
$session = New-Object WinSCP.Session
$session.SessionLogPath = $LogFile
try {
# パスワードを取り出して接続
$sessionOptions.Password = $cred.GetNetworkCredential().Password
$session.Open($sessionOptions)
$sessionOptions.Password = $null # 接続したら削除
$cred = $null # 接続したら削除
# --- 1) プレビュー ---
$diffs = $session.CompareDirectories(
$direction, $LocalPath, $RemotePath, $remove, $mirror, $criteria, $to
)
if ($diffs.Count -eq 0) { Write-Host "No changes."; return }
Write-Host "Planned changes:"
foreach ($d in $diffs) {
$path = if ($d.Local) { $d.Local.FileName } else { $d.Remote.FileName }
Write-Host (" [{0}] {1}" -f $d.Action, $path)
}
# --- 2) 確認 ---
$ans = Read-Host "Proceed with actual sync? [y/N]"
if ($ans -notmatch '^(y|yes)$') { Write-Host "Aborted."; return }
# --- 3) 同期 ---
$result = $session.SynchronizeDirectories(
$direction, $LocalPath, $RemotePath, $remove, $mirror, $criteria, $to
)
$result.Check()
Write-Host "Synchronized:"
foreach ($u in $result.Uploads) { Write-Host (" [Upload] {0} -> {1}" -f $u.FileName, $u.Destination) }
foreach ($d in $result.Downloads) { Write-Host (" [Download] {0} -> {1}" -f $d.FileName, $d.Destination) }
foreach ($r in $result.Removals) { Write-Host (" [Remove] {0}" -f $r.FileName) }
} catch {
Write-Error $_.Exception.Message
} finally {
if ($session) { $session.Dispose() }
Read-Host "Press Enter to exit"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment