有办法在监视文件系统时判断文件已经创建完毕吗??
目前使用的是这段代码来监视文件系统的,可是发现的问题是,当创建一个比较大的新文件时似乎没法判断文件是否已经创建完毕,,请问有什么好办法么?#cs ----------------------------------------------------------------------------AutoIt Version: 3.3.6.1
Author: zorphnog (M. Mims)
Modified: Jackchen
Script Function:
Monitors the user defined directories for file activity.
#ce ----------------------------------------------------------------------------
Global $bMonitoring = False
AutoItSetOption("GUIOnEventMode", 1)
$gFileMon = GUICreate("Directory Monitor", 731, 385, 194, 126)
GUISetOnEvent($GUI_EVENT_CLOSE, "_OnEvent_Close")
GUICtrlCreateGroup("Monitored Directories", 8, 0, 713, 105)
$btAdd = GUICtrlCreateButton("Add", 16, 24, 75, 25, 0)
GUICtrlSetOnEvent(-1, "_OnEvent_Add")
$btRemove = GUICtrlCreateButton("Remove", 16, 56, 75, 25, 0)
GUICtrlSetOnEvent(-1, "_OnEvent_Remove")
GUICtrlSetState(-1, $GUI_DISABLE)
$lbDirectories = GUICtrlCreateList("", 104, 16, 506, 71)
$btMonitor = GUICtrlCreateButton("Start Monitor", 632, 24, 75, 25, 0)
GUICtrlSetOnEvent(-1, "_OnEvent_Monitor")
GUICtrlSetState(-1, $GUI_DISABLE)
$btClear = GUICtrlCreateButton("Clear", 632, 56, 75, 25, 0)
GUICtrlSetOnEvent(-1, "_OnEvent_Clear")
GUICtrlCreateGroup("", -99, -99, 1, 1)
$lvNotifications = GUICtrlCreateListView("Action|Time|File", 8, 112, 714, 262)
GUICtrlSendMsg(-1, 0x101E, 0, Int(.1 * 710))
GUICtrlSendMsg(-1, 0x101E, 1, Int(.2 * 710))
GUICtrlSendMsg(-1, 0x101E, 2, Int(.7 * 710) - 20)
GUISetState(@SW_SHOW)
While 1
If Not $bMonitoring And _GUICtrlListBox_GetCurSel($lbDirectories) <> -1 And GUICtrlGetState($btRemove) = $GUI_SHOW + $GUI_DISABLE Then
GUICtrlSetState($btRemove, $GUI_ENABLE)
EndIf
Sleep(20)
WEnd
Func _ReportChanges($Action, $FilePath)
Local $hTime
$hTime = _Date_Time_GetSystemTime()
_GUICtrlListView_InsertItem($lvNotifications, $Action, 0)
_GUICtrlListView_AddSubItem($lvNotifications, 0, _Date_Time_SystemTimeToDateTimeStr($hTime), 1)
_GUICtrlListView_AddSubItem($lvNotifications, 0, $FilePath, 2)
EndFunc ;==>_ReportChanges
Func _OnEvent_Add()
Local $sDir, $nMax, $i
$sDir = FileSelectFolder("Select directory to monitor", "")
If $sDir <> "" Then
If StringRight($sDir, 1) <> "\" Then $sDir &= "\"
$nMax = _GUICtrlListBox_GetCount($lbDirectories) - 1
For $i = 0 To $nMax
If _GUICtrlListBox_GetText($lbDirectories, $i) = $sDir Then Return
Next
_GUICtrlListBox_AddString($lbDirectories, $sDir)
GUICtrlSetState($btMonitor, $GUI_ENABLE)
EndIf
EndFunc ;==>_OnEvent_Add
Func _OnEvent_Clear()
_GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($lvNotifications))
EndFunc ;==>_OnEvent_Clear
Func _OnEvent_Close()
If $bMonitoring Then _MonitorDirectory()
Exit
EndFunc ;==>_OnEvent_Close
Func _OnEvent_Monitor()
If Not $bMonitoring Then
$bMonitoring = True
GUICtrlSetData($btMonitor, "Stop Monitor")
GUICtrlSetState($btAdd, $GUI_DISABLE)
GUICtrlSetState($btRemove, $GUI_DISABLE)
GUICtrlSetState($lbDirectories, $GUI_DISABLE)
$n = _GUICtrlListBox_GetCount($lbDirectories)
Local $Dirs[$n]
For $i = 0 To $n - 1
$Dirs[$i] = _GUICtrlListBox_GetText($lbDirectories, $i)
Next
_MonitorDirectory($Dirs)
Else
$bMonitoring = False
GUICtrlSetState($lbDirectories, $GUI_ENABLE)
GUICtrlSetState($btAdd, $GUI_ENABLE)
GUICtrlSetData($btMonitor, "Start Monitor")
_MonitorDirectory()
EndIf
EndFunc ;==>_OnEvent_Monitor
Func _OnEvent_Remove()
_GUICtrlListBox_DeleteString($lbDirectories, _GUICtrlListBox_GetCurSel($lbDirectories))
If _GUICtrlListBox_GetCount($lbDirectories) = 0 Then
GUICtrlSetState($btMonitor, $GUI_DISABLE)
EndIf
EndFunc ;==>_OnEvent_Remove
;~ =========================== FUNCTION _MonitorDirectory() ==============================
#cs
Description: Monitors the user defined directories for file activity.
Original: http://www.autoitscript.com/forum/index.php?showtopic=69044&hl=folderspy&st=0
Modified: Jack Chen
Syntax: _MonitorDirectory($Dirs = "", $Subtree = True, $TimerMs = 250, $Function = "_ReportChanges")
Parameters:
$Dirs - Optional: Zero-based array of valid directories to be monitored.
$Subtree - Optional: Subtrees will be monitored if $Subtree = True.
$TimerMs - Optional: Timer to register changes in milliseconds.
$Function - Optional: Function to launch when changes are registered. e.g. _ReportChanges
Syntax of your function must be e.g._ReportChanges($Action, $FilePath)
Possible actions: Created, Deleted, Modified, Rename-, Rename+, Unknown
Remarks: Call _MonitorDirectory() without parameters to stop monitoring all directories.
THIS SHOULD BE DONE BEFORE EXITING SCRIPT AT LEAST.
#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")
$hBuffer = DllStructCreate("byte")
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
$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)
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)
Return $aResult
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
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 = "Created"
Case 0x2 ; $FILE_ACTION_REMOVED
$Action = "Deleted"
Case 0x3 ; $FILE_ACTION_MODIFIED
$Action = "Modified"
Case 0x4 ; $FILE_ACTION_RENAMED_OLD_NAME
$Action = "Rename-"
Case 0x5 ; $FILE_ACTION_RENAMED_NEW_NAME
$Action = "Rename+"
Case Else
$Action = "Unknown"
EndSwitch
$FilePath = $sDir & DllStructGetData($hFileName, "FileName")
Call($sFunction, $Action, $FilePath) ; Launch the specified function
$nNext = DllStructGetData($hFileNameInfo, "NextEntryOffset")
$nOffset += $nNext
WEnd
EndFunc ;==>_ParseFileMessages
;~ ===========================End of FUNCTION _MonitorDirectory() ============================== 好长的代码啊 试试读取文件如果不让读就是没写完 我现在用了_WinAPI_FileInUse函数判断文件是否在使用,如果使用就sleep500 While _WinAPI_FileInUse($FilePath) =1
sleep(500)
_FileWriteLog(@ScriptDir & "\Filelog.log","文件正在使用中>>Sleep500")
Wend但是我发现这个函数也不是百分之百准确,当我从网络复制文件时,发现有时明明正在复制文件,可是函数却反回了0..不知哪位大侠有什么更好的办法呀?
页:
[1]