PowerShell脚本:获取任务上次运行后新增文件并通过WinSCP实现SFTP上传
解决方案:基于上次任务运行时间筛选SFTP传输文件
针对你的需求,有两种可靠的方法实现“获取上次任务运行以来的文件”,以下是具体实现步骤和代码示例:
方法1:本地文件存储上次运行时间(新手友好)
这种方式无需读取系统事件日志,通过在本地保存一个记录上次脚本运行时间的文件来实现,简单易维护。
完整脚本示例
# 加载WinSCP .NET程序集(替换为你的WinSCP.dll实际路径) Add-Type -Path "C:\Tools\WinSCP\WinSCPnet.dll" # 定义存储上次运行时间的文件路径 $lastRunTimeFile = "C:\Scripts\LastSftpRunTime.txt" # 本地待上传文件夹路径 $localFolder = "C:\YourLocalFiles" # SFTP服务器配置 $sftpConfig = @{ HostName = "your-sftp-server.com" PortNumber = 22 UserName = "your-username" Password = "your-password" # 建议替换为SSH密钥认证 RemoteFolder = "/remote/target/path" SshFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx" } # 获取上次运行时间 if (Test-Path $lastRunTimeFile) { $lastRunTime = Get-Content $lastRunTimeFile | Get-Date } else { # 首次运行时,默认取当前时间前15分钟(匹配任务计划间隔) $lastRunTime = (Get-Date).AddMinutes(-15) } # 筛选上次运行后新增/修改的文件 $filesToTransfer = Get-ChildItem -Path $localFolder -File | Where-Object { $_.LastWriteTime -gt $lastRunTime } if ($filesToTransfer.Count -eq 0) { Write-Host "No files to transfer since last run." # 更新运行时间记录 Get-Date -Format "yyyy-MM-dd HH:mm:ss" | Set-Content $lastRunTimeFile exit } # 初始化WinSCP会话 $sessionOptions = New-Object WinSCP.SessionOptions -Property $sftpConfig $session = New-Object WinSCP.Session try { $session.Open($sessionOptions) $transferOpts = New-Object WinSCP.TransferOptions $transferOpts.TransferMode = [WinSCP.TransferMode]::Binary # 批量上传文件 foreach ($file in $filesToTransfer) { $result = $session.PutFiles($file.FullName, "$($sftpConfig.RemoteFolder)/", $false, $transferOpts) if ($result.IsSuccess) { Write-Host "Uploaded: $($file.Name)" } else { Write-Host "Failed to upload $($file.Name): $($result.Failures[0].Message)" } } } finally { $session.Dispose() } # 更新上次运行时间为当前时间 Get-Date -Format "yyyy-MM-dd HH:mm:ss" | Set-Content $lastRunTimeFile
方法2:读取任务计划事件日志(精准依赖系统记录)
通过查询Windows任务计划的操作日志,获取任务的上次启动时间,适合需要严格依赖系统任务运行记录的场景。
核心代码片段
# 替换为你的任务计划名称和路径 $taskName = "SFTP_File_Transfer" $taskPath = "\\" # 查询任务最后一次启动的事件(事件ID 100代表任务启动) $lastRunEvent = Get-WinEvent -FilterHashtable @{ LogName = "Microsoft-Windows-TaskScheduler/Operational" Id = 100 TaskPath = $taskPath TaskName = $taskName } -MaxEvents 1 | Sort-Object TimeCreated -Descending | Select-Object -First 1 # 处理无事件记录的情况(首次运行) $lastRunTime = if ($lastRunEvent) { $lastRunEvent.TimeCreated } else { (Get-Date).AddMinutes(-15) } # 后续文件筛选和WinSCP上传逻辑同方法1
注意事项
- 运行脚本的账户需要有读取
Microsoft-Windows-TaskScheduler/Operational日志的权限 - 若事件日志被清理,可能无法获取历史运行记录,需配合方法1的兜底逻辑
关键提示
- 优先推荐方法1,无需系统权限,逻辑简单,适合新手调试
- 生产环境建议使用SSH密钥认证替代密码,避免明文存储敏感信息
- 任务计划的运行账户需拥有本地文件夹、WinSCP.dll及时间记录文件的访问权限
内容的提问来源于stack exchange,提问作者grizz38
相关产品推荐
相关产品推荐

