Edit:
HostName
PortNumber
UserName
Password
SshHostKeyFingerprint
$localPath
$remotePath
$archivePath
# Load WinSCP .NET assembly (must be in same folder as this script or in PATH)
Add-Type -Path "WinSCPnet.dll"
# === Session settings ===
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{
Protocol = [WinSCP.Protocol]::Sftp
HostName = "hostname.server.tld"
PortNumber = 22
UserName = "username"
Password = "password"
SshHostKeyFingerprint = "ssh-rsa 4096 FingerprintFingerprintFingerprint"
}
$localPath = "C:\Nieuw"
$remotePath = "/in"
$archivePath = "C:\Archief"
$logFolder = "C:\WinSCP"
# === Logging function with weekly rotation and cleanup ===
function Write-Log {
param([string]$message)
$now = Get-Date
$year = $now.Year
$week = [math]::Floor(($now.DayOfYear - 1) / 7) + 1
$currentLogFile = Join-Path $logFolder ("SftpWatcher_{0}-W{1}.log" -f $year, $week)
$timestamp = $now.ToString("yyyy-MM-dd HH:mm:ss")
$entry = "$timestamp - $message"
Add-Content -Path $currentLogFile -Value $entry
Write-Host $entry
# Cleanup old log files (>30 days)
Get-ChildItem -Path $logFolder -Filter "SftpWatcher_*.log" | Where-Object {
$_.LastWriteTime -lt (Get-Date).AddDays(-90)
} | Remove-Item -Force
}
# === Upload and move function ===
function Upload-File {
param([string]$filePath)
$name = [System.IO.Path]::GetFileName($filePath)
if (!(Test-Path $filePath)) {
Write-Log "Skipped (not found): $filePath"
return
}
try {
$session = New-Object WinSCP.Session
$session.Open($sessionOptions)
Write-Log "Uploading $name ..."
$transferResult = $session.PutFiles($filePath, "$remotePath/$name")
$transferResult.Check()
Write-Log "Uploaded $name successfully."
# Move file to archive folder
$destFile = Join-Path $archivePath $name
Move-Item -Path $filePath -Destination $destFile -Force
Write-Log "Moved $name to archive folder."
}
catch {
Write-Log ("Error uploading " + $filePath + ": " + $_.ToString())
}
finally {
if ($session -ne $null) {
$session.Dispose()
Write-Log "Disconnected."
}
}
}
# === Initial sync at startup ===
Write-Log "SFTP Watcher starting. Checking existing files in $localPath ..."
Get-ChildItem -Path $localPath -Filter "*.*" -File | ForEach-Object {
Upload-File $_.FullName
}
# === Folder watcher for new files ===
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $localPath
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $false
$watcher.EnableRaisingEvents = $true
$createdEvent = Register-ObjectEvent $watcher Created -Action {
$file = $Event.SourceEventArgs.FullPath
Write-Log "New .eee file detected: $file"
Start-Sleep -Seconds 5 # wait if file is still being written
Upload-File $file
}
Write-Log "SFTP Watcher is now monitoring $localPath."
# === Keep-alive loop with graceful exit ===
try {
while ($true) {
Start-Sleep -Seconds 10
}
}
finally {
# Cleanup watcher and events
if ($createdEvent) { Unregister-Event -SourceIdentifier $createdEvent.Name }
if ($watcher) { $watcher.Dispose() }
Write-Log "SFTP Watcher service stopped."
}
Install service using Non-Sucking Service Manager:
nssm.exe install WinSCPFolderWatcher
Path: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Startup directory: C:\WinSCP
Arguments: -NoProfile -ExecutionPolicy Bypass -File "C:\WinSCP\SftpWatcher.ps1"