找回密码
 加入
搜索
查看: 5333|回复: 7

[系统综合] 会的请帮忙写个监控文件夹功能-非常感谢【已解决】

  [复制链接]
发表于 2011-3-8 15:52:56 | 显示全部楼层 |阅读模式
本帖最后由 leon460 于 2011-3-10 11:29 编辑

实现功能:监控某个文件夹,如果有新的txt文件产生,则copy此新增的txt文件到另一目录;如果旧的txt文件大小新增,也copy此旧txt文件

谢谢大家
发表于 2011-3-8 16:13:09 | 显示全部楼层
发表于 2011-3-8 17:41:06 | 显示全部楼层
不如用sync 更方便.
 楼主| 发表于 2011-3-10 11:20:47 | 显示全部楼层

【已解决】

本帖最后由 leon460 于 2011-3-10 11:26 编辑
;~ 示例
OnAutoItExitRegister("_Exit")
Global $aDirs[2]
$aDirs[0] = @SystemDir
$aDirs[1] = "D:\mydata\desktop"
_MonitorDirectory($aDirs, True, 100, "_ReportFileChanges")
While 1
        Sleep(20)
WEnd

;~ 检测到文件系统变化时将执行此函数
Func _ReportFileChanges($Action, $FilePath)
        ;~ 你自己的脚本代码 ...
        ;MsgBox(0,"",$FilePath)
        ;~ ...
        ConsoleWrite($Action & ": " & $FilePath & @CRLF)
        TrayTip("发现文件系统变化", $Action & ": " & $FilePath, 5, 1)
EndFunc   ;==>_ReportFileChanges

;~ 退出脚本前必须停止所有监视
Func _Exit()
        _MonitorDirectory()
        Exit
EndFunc   ;==>_Exit



;~ =========================== 函数 _MonitorDirectory() ==============================
#cs
        说明:        监视自定义的文件夹中的文件变化(文件或文件夹的新建、修改、删除等)。
        参考:        http://www.autoitscript.com/forum/index.php?showtopic=69044&hl=folderspy&st=0
        修改:        Jack Chen
        语法:        _MonitorDirectory($Dirs = "", $Subtree = True, $TimerMs = 250, $Function = "_ReportChanges")
        参数:
                                        $Dirs                   - 要监视的文件夹(数组)
                                        $Subtree           - 若 $Subtree = True 则监视子文件夹
                                        $TimerMs       - 检查文件系统变化的时间间隔(毫秒)
                                        $Function      - 当发现文件系统变化时执行的函数,又如:_ReportChanges
                        函数语法须如: _ReportChanges($Action, $FilePath)
                                        $Action可能的值: 新建, 删除, 修改, 重命名-, 重命名+, 未知
        注:                    不带任何参数调用_MonitorDirectory() 则可停止监视所有文件夹,在退出脚本前必须停止所有监视。
#ce

Func _MonitorDirectory($Dirs = "", $Subtree = True, $TimerMs = 250, $Function = "_ReportChanges")
        Local Static $nMax, $hBuffer, $hEvents, $aSubtree, $sFunction
        If IsArray($Dirs) Then
                $nMax = UBound($Dirs)
        ElseIf $nMax < 1 Then
                Return
        EndIf
        Local Static $aDirHandles[$nMax], $aOverlapped[$nMax], $aDirs[$nMax]
        If IsArray($Dirs) Then
                $aDirs = $Dirs
                $aSubtree = $Subtree
                $sFunction = $Function
;~                 $hBuffer = DllStructCreate("byte[4096]")
                $hBuffer = DllStructCreate("byte[65536]")
                For $i = 0 To $nMax - 1
                        If StringRight($aDirs[$i], 1) <> "" Then $aDirs[$i] &= ""
;~         http://msdn.microsoft.com/en-us/library/aa363858%28VS.85%29.aspx
                        $aResult = DllCall("kernel32.dll", "hwnd", "CreateFile", "Str", $aDirs[$i], "Int", 0x1, "Int", BitOR(0x1, 0x4, 0x2), "ptr", 0, "int", 0x3, "int", BitOR(0x2000000, 0x40000000), "int", 0)
                        $aDirHandles[$i] = $aResult[0]
                        $aOverlapped[$i] = DllStructCreate("ulong_ptr Internal;ulong_ptr InternalHigh;dword Offset;dword OffsetHigh;handle hEvent")
                        For $j = 1 To 5
                                DllStructSetData($aOverlapped, $j, 0)
                        Next
                        _SetReadDirectory($aDirHandles[$i], $hBuffer, $aOverlapped[$i], True, $aSubtree)
                Next
                $hEvents = DllStructCreate("hwnd hEvent[" & UBound($aOverlapped) & "]")
                For $j = 1 To UBound($aOverlapped)
                        DllStructSetData($hEvents, "hEvent", DllStructGetData($aOverlapped[$j - 1], "hEvent"), $j)
                Next
                AdlibRegister("_GetChanges", $TimerMs)
        ElseIf $Dirs = "ReadDirChanges" Then
                _GetDirectoryChanges($aDirHandles, $hBuffer, $aOverlapped, $hEvents, $aDirs, $aSubtree, $sFunction)
        ElseIf $Dirs = "" Then
                AdlibUnRegister("_GetChanges")
;~         Close Handle
                For $i = 0 To $nMax - 1
                        DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $aDirHandles[$i])
                        DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $aOverlapped[$i])
                Next
                DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hEvents)
                $nMax = 0
                $hBuffer = ""
                $hEvents = ""
                $aDirHandles = ""
                $aOverlapped = ""
                $aDirs = ""
                $aSubtree = ""
                $sFunction = ""
        EndIf
EndFunc   ;==>_MonitorDirectory

Func _SetReadDirectory($hDir, $hBuffer, $hOverlapped, $bInitial, $bSubtree)
        Local $hEvent, $pBuffer, $nBufferLength, $pOverlapped
        $pBuffer = DllStructGetPtr($hBuffer)
        $nBufferLength = DllStructGetSize($hBuffer)
        $pOverlapped = DllStructGetPtr($hOverlapped)
        If $bInitial Then
                $hEvent = DllCall("kernel32.dll", "hwnd", "CreateEvent", "UInt", 0, "Int", True, "Int", False, "UInt", 0)
                DllStructSetData($hOverlapped, "hEvent", $hEvent[0])
        EndIf
;~         http://msdn.microsoft.com/en-us/library/aa365465%28VS.85%29.aspx
        $aResult = DllCall("kernel32.dll", "Int", "ReadDirectoryChangesW", "hwnd", $hDir, "ptr", $pBuffer, "dword", $nBufferLength, "int", $bSubtree, "dword", BitOR(0x1, 0x2, 0x4, 0x8, 0x10, 0x40, 0x100), "Uint", 0, "Uint", $pOverlapped, "Uint", 0)
;~ BitOR(0x1, 0x2, 0x4, 0x8, 0x10, 0x40, 0x100) 的说明:
;~ 0x1 - 监视文件新建/删除/重命名, 0x2 - 监视文件夹新建/删除, 0x4 - 监视属性, 0x8 - 监视文件大小变化,
;~ 0x10 - 监视文件最后修改时间, 0x40 - 监视文件创建时间, 0x100 - 监视安全描述
;~ 若只要监视文件名、文件夹名变化(不监视修改),可改成 BitOR(0x1, 0x2),
;~ 若只要监视文件名变化(忽略文件夹),则可直接改成0x1(不用BitOR了)
        Return $aResult[0]
EndFunc   ;==>_SetReadDirectory

Func _GetChanges()
        _MonitorDirectory("ReadDirChanges")
EndFunc   ;==>_GetChanges

Func _GetDirectoryChanges($aDirHandles, $hBuffer, $aOverlapped, $hEvents, $aDirs, $aSubtree, $sFunction)
        Local $aMsg, $i, $nBytes = 0
        $aMsg = DllCall("User32.dll", "dword", "MsgWaitForMultipleObjectsEx", "dword", UBound($aOverlapped), "ptr", DllStructGetPtr($hEvents), "dword", -1, "dword", 0x4FF, "dword", 0x6)
        $i = $aMsg[0]
        Switch $i
                Case 0 To UBound($aDirHandles) - 1
                        DllCall("Kernel32.dll", "Uint", "ResetEvent", "uint", DllStructGetData($aOverlapped[$i], "hEvent"))
                        _ParseFileMessages($hBuffer, $aDirs[$i], $sFunction)
                        _SetReadDirectory($aDirHandles[$i], $hBuffer, $aOverlapped[$i], False, $aSubtree)
                        Return $nBytes
        EndSwitch
        Return 0
EndFunc   ;==>_GetDirectoryChanges

Func _ParseFileMessages($hBuffer, $sDir, $sFunction)
        Local $hFileNameInfo, $pBuffer, $FilePath
        Local $nFileNameInfoOffset = 12, $nOffset = 0, $nNext = 1
        $pBuffer = DllStructGetPtr($hBuffer)
        While $nNext <> 0
                $hFileNameInfo = DllStructCreate("dword NextEntryOffset;dword Action;dword FileNameLength", $pBuffer + $nOffset)
                $hFileName = DllStructCreate("wchar FileName[" & DllStructGetData($hFileNameInfo, "FileNameLength") / 2 & "]", $pBuffer + $nOffset + $nFileNameInfoOffset)
                Switch DllStructGetData($hFileNameInfo, "Action")
                        Case 0x1 ; $FILE_ACTION_ADDED
                                $Action = "新建"
                        Case 0x2 ; $FILE_ACTION_REMOVED
                                $Action = "删除"
                        Case 0x3 ; $FILE_ACTION_MODIFIED
                                $Action = "修改"
                        Case 0x4 ; $FILE_ACTION_RENAMED_OLD_NAME
                                $Action = "重命名-"
                        Case 0x5 ; $FILE_ACTION_RENAMED_NEW_NAME
                                $Action = "重命名+"
                        Case Else
                                $Action = "未知"
                EndSwitch

                $FilePath = $sDir & DllStructGetData($hFileName, "FileName")
                Call($sFunction, $Action, $FilePath) ; Launch the specified function
                $nNext = DllStructGetData($hFileNameInfo, "NextEntryOffset")
                $nOffset += $nNext
        WEnd
EndFunc   ;==>_ParseFileMessages
;~ ===========================以上为函数_MonitorDirectory() ==============================
发表于 2011-4-10 00:12:53 | 显示全部楼层
_MonitorDirectory($aDirs, True, 100, "_ReportFileChanges"):参数设为false了

我要监控一个文件夹,里面全是日志文件,有改动,或是新建.
Func _ReportFileChanges($Action, $FilePath)
        ;~ 你自己的脚本代码 ...   
        ConsoleWrite($Action & ": " & $FilePath & @CRLF)
        TrayTip("发现文件系统变化", $Action & ": " & $FilePath, 5, 1)
EndFunc   ;==>_ReportFileChanges

问:为什么我改动一个文件,上面的代码会执行两次??
发表于 2011-4-11 17:37:08 | 显示全部楼层
新手学习学习
发表于 2011-12-27 12:49:01 | 显示全部楼层
我目前不太明白图片怎么发送呢?总不能用模拟操作的方式吧
发表于 2012-5-14 14:45:42 | 显示全部楼层
不错的代码!顶一个!
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-11-15 10:18 , Processed in 0.082471 second(s), 24 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表