Windows 11环境下监控文件夹新增指定格式文件并自动创建系列关联定时提醒的实现方案咨询
Windows 11环境下监控文件夹新增指定格式文件并自动创建系列关联定时提醒的实现方案咨询
嘿,这个需求确实有点超出Task Scheduler原生功能的覆盖范围,但咱们完全可以用PowerShell脚本+Task Scheduler的组合来实现,不用你写复杂的代码,我一步步给你拆解清楚:
整体思路
核心分为三个模块:
- 实时监控目标文件夹及其子文件夹,捕捉
.xyz文件的创建事件(忽略修改操作) - 针对每个新增文件,自动生成6个对应时间点的定时提醒任务
- 当提醒到期时,检查文件是否存在(包括处理重命名场景),触发声音提醒、唤醒设备,提供 snooze 功能,只有打开文件才能关闭提醒
第一步:编写文件监控脚本(FileWatcher.ps1)
这个脚本会一直运行,监控FolderA及其子文件夹的新.xyz文件,一旦检测到就触发提醒创建逻辑:
# 设置监控的根文件夹路径 $watchRootPath = "C:\实际路径\FolderA" # 初始化文件监控器 $watcher = New-Object System.IO.FileSystemWatcher $watcher.Path = $watchRootPath $watcher.IncludeSubdirectories = $true $watcher.Filter = "*.xyz" # 只监控文件名创建事件,忽略修改、删除等操作 $watcher.NotifyFilter = [System.IO.NotifyFilters]::FileName # 定义文件创建时的处理逻辑 $onFileCreated = { $fullFilePath = $Event.SourceEventArgs.FullPath $fileName = $Event.SourceEventArgs.Name $creationDate = (Get-Item $fullFilePath).CreationTime # 调用创建提醒的函数(后面会定义这个函数) Create-SeriesReminders -FilePath $fullFilePath -FileName $fileName -CreationDate $creationDate } # 绑定文件创建事件到处理逻辑 Register-ObjectEvent $watcher "Created" -Action $onFileCreated # 保持脚本持续运行(不然监控器会退出) while ($true) { Start-Sleep -Seconds 1 }
第二步:编写创建系列提醒的函数
把下面的代码添加到上面的FileWatcher.ps1末尾,它会根据你指定的时间规则生成Task Scheduler定时任务:
function Create-SeriesReminders { param( [string]$FilePath, [string]$FileName, [DateTime]$CreationDate ) # 定义你的提醒规则:天数偏移、触发时间、提醒消息 $reminderRules = @( @{DaysOffset=2; TriggerTime="13:15"; Message="Review $FileName!"}, @{DaysOffset=6; TriggerTime="13:15"; Message="Check progress on $FileName!"}, @{DaysOffset=14; TriggerTime="13:15"; Message="Follow up $FileName!"}, @{DaysOffset=30; TriggerTime="13:25"; Message="Summarize $FileName!"}, @{DaysOffset=62; TriggerTime="13:25"; Message="Archive check for $FileName!"}, @{DaysOffset=126; TriggerTime="13:25"; Message="Final review of $FileName!"} ) foreach ($rule in $reminderRules) { # 计算提醒的触发日期和时间 $triggerDate = $CreationDate.AddDays($rule.DaysOffset) $triggerTime = [DateTime]::Parse($rule.TriggerTime) $triggerDateTime = $triggerDate.Date.AddHours($triggerTime.Hour).AddMinutes($triggerTime.Minute) # 生成唯一的任务名,避免重复冲突 $taskName = "FileReminder_$($FileName.Replace('.xyz',''))_$($rule.DaysOffset)Days" # 创建Task Scheduler任务:支持唤醒设备、以系统权限运行 schtasks /create ` /tn $taskName ` /tr "powershell.exe -ExecutionPolicy Bypass -File 'C:\实际路径\ReminderTrigger.ps1' -FilePath '$FilePath' -Message '$($rule.Message)'" ` /sc once ` /st $triggerTime.ToString("HH:mm") ` /sd $triggerDate.ToString("MM/dd/yyyy") ` /ru "SYSTEM" ` /f ` /waketorun } }
第三步:编写提醒触发逻辑脚本(ReminderTrigger.ps1)
这个脚本是每个定时任务到期时运行的核心,负责检查文件、播放声音、显示提醒窗口,处理 snooze 和关闭逻辑:
param( [string]$FilePath, [string]$Message ) # 1. 检查文件是否存在(处理重命名场景) $targetFile = $null # 先尝试按原路径查找 if (Test-Path $FilePath) { $targetFile = Get-Item $FilePath } else { # 原路径找不到时,用文件唯一ID(NTFS FileID)搜索,重命名/同分区移动都能找到 $originalFile = Get-Item $FilePath -ErrorAction SilentlyContinue if ($originalFile) { $targetFile = Get-ChildItem "C:\实际路径\FolderA" -Recurse -Filter "*.xyz" | Where-Object { $_.FileId -eq $originalFile.FileId } | Select-Object -First 1 } } if ($targetFile) { # 2. 播放指定的提醒声音 $soundFilePath = "C:\实际路径\你的提醒声音.wav" if (Test-Path $soundFilePath) { (New-Object System.Media.SoundPlayer $soundFilePath).PlaySync() } # 3. 显示提醒窗口(带Snooze和打开文件按钮) Add-Type -AssemblyName System.Windows.Forms $form = New-Object System.Windows.Forms.Form $form.Text = "文件提醒" $form.Size = New-Object System.Drawing.Size(450, 220) $form.StartPosition = "CenterScreen" $form.TopMost = $true $form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedDialog $form.MaximizeBox = $false # 提醒消息标签 $msgLabel = New-Object System.Windows.Forms.Label $msgLabel.Text = $Message $msgLabel.Location = New-Object System.Drawing.Point(20, 30) $msgLabel.Size = New-Object System.Drawing.Size(410, 60) $msgLabel.Font = New-Object System.Drawing.Font("Arial", 11) $form.Controls.Add($msgLabel) # Snooze按钮(8分钟后再次提醒) $snoozeBtn = New-Object System.Windows.Forms.Button $snoozeBtn.Text = "稍后提醒(8分钟)" $snoozeBtn.Location = New-Object System.Drawing.Point(30, 120) $snoozeBtn.Size = New-Object System.Drawing.Size(160, 35) $snoozeBtn.Add_Click({ $form.Close() # 创建8分钟后的临时提醒任务 $snoozeTime = (Get-Date).AddMinutes(8) $snoozeTaskName = "Snooze_$([Guid]::NewGuid())" schtasks /create ` /tn $snoozeTaskName ` /tr "powershell.exe -ExecutionPolicy Bypass -File 'C:\实际路径\ReminderTrigger.ps1' -FilePath '$($targetFile.FullName)' -Message '$Message'" ` /sc once ` /st $snoozeTime.ToString("HH:mm") ` /sd $snoozeTime.ToString("MM/dd/yyyy") ` /ru "SYSTEM" ` /f ` /waketorun }) $form.Controls.Add($snoozeBtn) # 打开文件按钮(点击后关闭提醒并删除相关任务) $openFileBtn = New-Object System.Windows.Forms.Button $openFileBtn.Text = "打开文件以关闭提醒" $openFileBtn.Location = New-Object System.Drawing.Point(230, 120) $openFileBtn.Size = New-Object System.Drawing.Size(180, 35) $openFileBtn.Add_Click({ # 打开目标文件 Start-Process $targetFile.FullName $form.Close() # 删除当前提醒任务和所有相关的snooze任务 $currentTask = Get-WmiObject Win32_ScheduledTask | Where-Object { $_.Command -like "*$Message*" -and $_.Command -like "*$FilePath*" } if ($currentTask) { schtasks /delete /tn $currentTask.Name /f } $snoozeTasks = Get-WmiObject Win32_ScheduledTask | Where-Object { $_.Command -like "*Snooze_*" -and $_.Command -like "*$Message*" } foreach ($task in $snoozeTasks) { schtasks /delete /tn $task.Name /f } }) $form.Controls.Add($openFileBtn) $form.ShowDialog() | Out-Null } else { # 文件不存在,自动删除当前提醒任务 $currentTask = Get-WmiObject Win32_ScheduledTask | Where-Object { $_.Command -like "*$Message*" -and $_.Command -like "*$FilePath*" } if ($currentTask) { schtasks /delete /tn $currentTask.Name /f } }
第四步:配置开机自动运行监控脚本
因为监控脚本需要一直运行才能捕捉文件创建事件,我们可以把它做成开机自启的后台任务:
- 打开Task Scheduler,点击「创建任务」
- 常规选项卡:勾选「不管用户是否登录都运行」,勾选「隐藏」
- 触发器选项卡:新建触发器,选择「登录时」
- 操作选项卡:新建操作,选择「启动程序」,程序/脚本填
powershell.exe,添加参数填-ExecutionPolicy Bypass -File "C:\实际路径\FileWatcher.ps1" - 条件选项卡:勾选「唤醒计算机运行此任务」(如果需要)
- 确定保存,重启电脑后脚本就会后台运行了
关键注意事项
- 把所有脚本中的
C:\实际路径\替换成你自己的真实文件夹/文件路径 - 确保PowerShell执行权限:以管理员身份运行PowerShell,执行
Set-ExecutionPolicy RemoteSigned(按Y确认) - 测试时可以先手动运行
FileWatcher.ps1,然后在FolderA下创建一个.xyz文件,检查Task Scheduler中是否生成了6个提醒任务 - 声音文件建议用
.wav格式,其他格式可能需要额外处理
备注:内容来源于stack exchange,提问作者longtry




