PowerShell文件监控脚本中字符串检测IF语句失效求助
PowerShell文件监控脚本字符串检测问题修复
核心问题分析
- 文件创建事件触发过早:
FileSystemWatcher的Created事件在文件刚开始创建时就会触发,此时文件可能还处于写入状态,无法被正常读取,导致Select-String返回空结果。 - 脚本语法错误:存在一行无效代码
$changetype: '$name'"`,会中断Action块的执行逻辑。 - 字符串检测逻辑不够鲁棒:未处理文件读取失败的场景,也未针对文件编码做适配。
修复后的脚本
# 指定监控目录与文件过滤规则 $folder = 'C:\Some\File\Location\' $filter = '*.*' # 初始化文件系统监控器 $fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property @{ IncludeSubdirectories = $false NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite' } # 注册文件创建事件 $onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action { $name = $Event.SourceEventArgs.Name $changeType = $Event.SourceEventArgs.ChangeType $timeStamp = $Event.TimeGenerated Write-Host "The file '$name' was $changeType at $timeStamp" -ForegroundColor Red $path = $Event.SourceEventArgs.FullPath $string = "997" $result = $null # 循环等待文件可用,最多尝试10次,每次间隔1秒 for ($i=0; $i -lt 10; $i++) { try { # 尝试读取文件,根据实际情况调整编码(如UTF8、Default等) $result = Select-String -Path $path -Pattern $string -CaseSensitive -ErrorAction Stop break } catch { Write-Host "文件暂时不可用,等待重试... ($i/10)" Start-Sleep -Seconds 1 } } if ($result) { Write-Host "文件包含字符串 '$string',执行复制、移动与邮件通知操作" -ForegroundColor Green $destination = 'C:\Some\NEW\File\Location\' $filedestination = 'C:\Some\NEW\File\Location\Workable%20Link\' $copylocation = 'C:\Some\NEW\COPY\File\Location\' $filepath = Join-Path -Path $filedestination -ChildPath $name # 使用Join-Path替代字符串拼接,避免路径问题 # 执行复制与移动操作 Copy-Item -Path $path -Destination $copylocation -Verbose Move-Item -Path $path -Destination $destination -Verbose # 邮件通知函数(需确保以下变量已提前定义或传入) function SendNotification { param( [string]$ExchangeServer, [string]$Username, [string]$Pass, [string]$FromAddress, [string]$ToAddress, [string]$ReportName, [string]$Partner, [string]$Dte, [string]$Filepath ) $Msg = New-Object Net.Mail.MailMessage $Smtp = New-Object Net.Mail.SmtpClient($ExchangeServer) $Smtp.Port = 25 $Smtp.EnableSsl = $true $Smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Pass) $Msg.From = $FromAddress $Msg.To.Add($ToAddress) $Msg.Subject = "$ReportName $Dte" $Msg.Body = @" <html> <head></head> <body> <p>合作伙伴 <b>$Partner</b> 的 $ReportName 已处理完成。</p> <p>点击下方链接查看文件:</p> <p><a href="file:///$Filepath">$Filepath</a></p> </body> </html> "@ $Msg.IsBodyHTML = $true $Smtp.Send($Msg) } # 定义邮件所需变量(根据实际情况修改) $emailParams = @{ ExchangeServer = "your-exchange-server.com" Username = "your-username" Pass = "your-password" FromAddress = "sender@example.com" ToAddress = "recipient@example.com" ReportName = "报表" Partner = "合作方名称" Dte = Get-Date -Format "yyyy-MM-dd" Filepath = $filepath } # 发送邮件 SendNotification @emailParams Start-Sleep -Seconds 1 } else { Write-Host "文件不包含字符串 '$string'。" -ForegroundColor Yellow } } # 保持脚本运行 while ($onCreated) { Start-Sleep -Milliseconds 100 }
关键修改说明
- 等待文件可用:添加循环重试逻辑,最多尝试10次读取文件,避免因文件未写入完成导致的读取失败。
- 修复语法错误:移除无效的
$changetype: '$name'"`代码行。 - 路径处理优化:使用
Join-Path替代字符串拼接路径,避免因路径分隔符导致的错误。 - 函数参数化:将邮件通知函数改为参数化形式,避免变量作用域问题,同时提高代码可维护性。
- 编码适配:如果文件使用特殊编码,可在
Select-String中添加-Encoding参数(如-Encoding UTF8)。
内容的提问来源于stack exchange,提问作者Phil M
相关产品推荐
相关产品推荐

