- Сообщения
- 5,379
- Репутация
- 2,724
AutoIt: 3.3.6.1
Версия: 1.0
Категория: Файловая система
Описание: Хочу предложить свой способ использования API ReadDirectoryChangesW в AutoIt. Основная проблема здесь в том, что в полной мере работать с этой функцией без создания потока не получится. Для решения этой проблемы я написал простой DLL, который берет на себя всю работу с потоками. В результате AutoIt скрипту остается только принимать и обрабатывать данные, которые поступают из соответствующего потока. Для того, чтобы оценить все возможности библиотеки, посмотрите полноценный пример с GUI, который находится внутри архива. Для более подробной информации смотрите описание для каждой функции в самой библиотеке.
Ниже приведены основные характеристики библиотеки.
Список функций:
Файл(ы): RDC.zip (x86 и x64)
Пример1 (режим цикла):
Пример2 (режим уведомлений):
Пример3 (режим уведомлений, расширенный):
Пример4 (GUI):
Скриншот:
Источник: RDC UDF (официальный форум)
Автор: Yashied
Версия: 1.0
Категория: Файловая система
Описание: Хочу предложить свой способ использования API ReadDirectoryChangesW в AutoIt. Основная проблема здесь в том, что в полной мере работать с этой функцией без создания потока не получится. Для решения этой проблемы я написал простой DLL, который берет на себя всю работу с потоками. В результате AutoIt скрипту остается только принимать и обрабатывать данные, которые поступают из соответствующего потока. Для того, чтобы оценить все возможности библиотеки, посмотрите полноценный пример с GUI, который находится внутри архива. Для более подробной информации смотрите описание для каждой функции в самой библиотеке.
Ниже приведены основные характеристики библиотеки.
- Возможность создания нескольких потоков (не лимитировано) для мониторинга разных папок.
- Поддержка горячего (небезопасного) отключение съемных устройств, таких как USB флэш-диск, и т.д.
- Поддержка UNC и сетевых дисков.
- Поддержка 32- и 64-разрядных процессов (RDC.dll и RDC_x64.dll).
- Простота использования функций библиотеки.
- Полноценные примеры, включая GUI.
Список функций:
_RDC_CloseDll
_RDC_Create
_RDC_Delete
_RDC_Destroy
_RDC_EnumRDC
_RDC_GetCount
_RDC_GetData
_RDC_GetDirectory
_RDC_GetRDCInfo
_RDC_OpenDll
_RDC_Resume
Файл(ы): RDC.zip (x86 и x64)
Пример1 (режим цикла):
Код:
#Include <APIConstants.au3>
#Include <RDC.au3>
Opt('MustDeclareVars', 1)
Opt('TrayAutoPause', 0)
_RDC_OpenDll()
If @Error Then
ConsoleWrite('Error: _RDC_OpenDll() - ' & @Error & @CR)
Exit
EndIf
Global $aDir[3], $ID[3], $aData
For $i = 0 To 2
$aDir[$i] = @ScriptDir & '\~TEST' & ($i + 1) & '~'
If Not FileExists($aDir[$i]) Then
DirCreate($aDir[$i])
EndIf
Next
For $i = 0 To 2
$ID[$i] = _RDC_Create($aDir[$i], 1, BitOR($FILE_NOTIFY_CHANGE_FILE_NAME, $FILE_NOTIFY_CHANGE_DIR_NAME, $FILE_NOTIFY_CHANGE_SIZE))
If @Error Then
ConsoleWrite('Error: _RDC_Create() - ' & @Error & ', ' & @Extended & @CR)
Exit
EndIf
Next
While 1
For $i = 0 To 2
If $ID[$i] = -1 Then
ContinueLoop
EndIf
$aData = _RDC_GetData($ID[$i])
If @Error Then
ConsoleWrite('Error: _RDC_GetData() - ' & @Error & ', ' & @Extended & ', ' & _RDC_GetDirectory($ID[$i]) & @CR)
; Delete thread to avoid receiving this error!
_RDC_Delete($ID[$i])
$ID[$i] = -1
ContinueLoop
EndIf
For $j = 1 To $aData[0][0]
ConsoleWrite($aData[$j][1] & ' - ' & _RDC_GetDirectory($ID[$i]) & '\' & $aData[$j][0] & @CR)
Next
Next
Sleep(10)
WEnd
Пример2 (режим уведомлений):
Код:
#Include <APIConstants.au3>
#Include <RDC.au3>
Opt('MustDeclareVars', 1)
Opt('TrayAutoPause', 0)
_RDC_OpenDll()
If @Error Then
ConsoleWrite('Error: _RDC_OpenDll() - ' & @Error & @CR)
Exit
EndIf
Global $hWnd = GUICreate('')
Global $aDir[3]
For $i = 0 To 2
$aDir[$i] = @ScriptDir & '\~TEST' & ($i + 1) & '~'
If Not FileExists($aDir[$i]) Then
DirCreate($aDir[$i])
EndIf
Next
GUIRegisterMsg($WM_RDC, 'WM_RDC')
For $i = 0 To 2
_RDC_Create($aDir[$i], 1, BitOR($FILE_NOTIFY_CHANGE_FILE_NAME, $FILE_NOTIFY_CHANGE_DIR_NAME, $FILE_NOTIFY_CHANGE_SIZE), 0, $hWnd)
If @Error Then
ConsoleWrite('Error: _RDC_Create() - ' & @Error & ', ' & @Extended & @CR)
Exit
EndIf
Next
While 1
Sleep(1000)
WEnd
Func WM_RDC($hWnd, $iMsg, $wParam, $lParam)
#forceref $hWnd, $iMsg, $wParam
Local $aData = _RDC_GetData($lParam)
If @Error Then
; Do something because notifications will not come from this thread!
ConsoleWrite('Error: _RDC_GetData() - ' & @Error & ', ' & @Extended & ', ' & _RDC_GetDirectory($lParam) & @CR)
_RDC_Delete($lParam)
Return 0
EndIf
For $i = 1 To $aData[0][0]
ConsoleWrite($aData[$i][1] & ' - ' & _RDC_GetDirectory($lParam) & '\' & $aData[$i][0] & @CR)
Next
Return 0
EndFunc ;==>WM_RDC
Пример3 (режим уведомлений, расширенный):
Код:
#Include <APIConstants.au3>
#Include <RDC.au3>
Opt('MustDeclareVars', 1)
Opt('TrayAutoPause', 0)
Global Const $sDir = @ScriptDir & '\~TEST~'
_RDC_OpenDll()
If @Error Then
ConsoleWrite('Error: _RDC_OpenDll() - ' & @Error & @CR)
Exit
EndIf
Global $hWnd = GUICreate('')
Global $sEvents = ''
If Not FileExists($sDir) Then
DirCreate($sDir)
EndIf
GUIRegisterMsg($WM_RDC, 'WM_RDC')
_RDC_Create($sDir, 1, BitOR($FILE_NOTIFY_CHANGE_FILE_NAME, $FILE_NOTIFY_CHANGE_DIR_NAME, $FILE_NOTIFY_CHANGE_SIZE), 0, $hWnd)
If @Error Then
ConsoleWrite('Error: _RDC_Create() - ' & @Error & ', ' & @Extended & @CR)
Exit
EndIf
While 1
Sleep(1000)
WEnd
Func _IsDirectory($sPath)
If StringInStr(FileGetAttrib($sPath), 'D') Then
Return 1
Else
Return 0
EndIf
EndFunc ;==>_IsDirectory
Func _RetrieveDirectoryChanges()
AdlibUnRegister('_RetrieveDirectoryChanges')
Local $aData, $aText, $aPrev[2] = [0, ''], $sPrev = ''
$aData = StringSplit($sEvents, '|', 2)
$sEvents = ''
If Not IsArray($aData) Then
Return
EndIf
For $i = 0 To UBound($aData)
If $i < UBound($aData) Then
If $aData[$i] = $sPrev Then
ContinueLoop
EndIf
$sPrev = $aData[$i]
$aText = StringSplit($aData[$i], '?', 2)
If IsArray($aText) Then
;~ ConsoleWrite($aText[0] & ' - ' & $aText[1] & @CR)
;~ ContinueLoop
Switch Number($aText[0])
Case 1 ; FILE_ACTION_ADDED
Switch Number($aPrev[0])
Case 2
If StringRegExpReplace($aPrev[1], '^.*\\', '') = StringRegExpReplace($aText[1], '^.*\\', '') Then
If $aPrev[1] = $aText[1] Then
;~ If _IsDirectory($aText[1]) Then
;~ ; Nothing
;~ Else
;~ ; Nothing
;~ EndIf
$aPrev[0] = 0
ContinueLoop
Else
If _IsDirectory($aText[1]) Then
ConsoleWrite('DIRECTORY MOVED: ' & $aPrev[1] & ' ---> ' & $aText[1] & @CR)
Else
ConsoleWrite('FILE MOVED: ' & $aPrev[1] & ' ---> ' & $aText[1] & @CR)
EndIf
$aPrev[0] = 0
ContinueLoop
EndIf
EndIf
EndSwitch
Case 2 ; FILE_ACTION_REMOVED
; Nothing
Case 3 ; FILE_ACTION_MODIFIED
Switch Number($aPrev[0])
Case 1
;~ If True Then
If $aPrev[1] = $aText[1] Then
If _IsDirectory($aText[1]) Then
; Nothing
Else
ConsoleWrite('FILE ADDED: ' & $aText[1] & @CR)
EndIf
$aPrev[0] = 0
ContinueLoop
EndIf
;~ EndIf
Case 2
If StringRegExpReplace($aPrev[1], '^.*\\', '') = StringRegExpReplace($aText[1], '^.*\\', '') Then
;~ If True Then
If _IsDirectory($aText[1]) Then
; Nothing
Else
ConsoleWrite('FILE DELETED: ' & $aText[1] & @CR)
ConsoleWrite('FILE MOVED: ' & $aPrev[1] & ' ---> ' & $aText[1] & @CR)
EndIf
$aPrev[0] = 0
ContinueLoop
;~ EndIf
EndIf
EndSwitch
Case 4 ; FILE_ACTION_RENAMED_OLD_NAME
; Nothing
Case 5 ; FILE_ACTION_RENAMED_NEW_NAME
Switch Number($aPrev[0])
Case 4
If StringRegExpReplace($aPrev[1], '\\[^\\]*\Z', '') = StringRegExpReplace($aText[1], '\\[^\\]*\Z', '') Then
;~ If True Then
If _IsDirectory($aText[1]) Then
ConsoleWrite('DIRECTORY RENAMED: ' & $aPrev[1] & ' ---> ' & $aText[1] & @CR)
Else
ConsoleWrite('FILE RENAMED: ' & $aPrev[1] & ' ---> ' & $aText[1] & @CR)
EndIf
$aPrev[0] = 0
ContinueLoop
;~ EndIf
EndIf
EndSwitch
EndSwitch
EndIf
EndIf
Switch Number($aPrev[0])
Case 1 ; FILE_ACTION_ADDED
If _IsDirectory($aPrev[1]) Then
ConsoleWrite('DIRECTORY ADDED: ' & $aPrev[1] & @CR)
Else
ConsoleWrite('FILE ADDED: ' & $aPrev[1] & @CR)
EndIf
Case 2 ; FILE_ACTION_REMOVED
;~ If True Then
ConsoleWrite('FILE OR DIRECTORY DELETED: ' & $aPrev[1] & @CR)
;~ EndIf
Case 3 ; FILE_ACTION_MODIFIED
If _IsDirectory($aPrev[1]) Then
; Nothing
Else
ConsoleWrite('FILE MODIFIED: ' & $aPrev[1] & @CR)
EndIf
EndSwitch
$aPrev = $aText
Next
ConsoleWrite('---------------------------------------------' & @CR)
EndFunc ;==>_RetrieveDirectoryChanges
Func WM_RDC($hWnd, $iMsg, $wParam, $lParam)
#forceref $hWnd, $iMsg, $wParam
Local $aData = _RDC_GetData($lParam)
If @Error Then
; Do something because notifications will not come from this thread!
ConsoleWrite('Error: _RDC_GetData() - ' & @Error & ', ' & @Extended & ', ' & _RDC_GetDirectory($lParam) & @CR)
_RDC_Delete($lParam)
Return 0
EndIf
For $i = 1 To $aData[0][0]
If $sEvents Then
$sEvents &= '|'
EndIf
$sEvents &= $aData[$i][1] & '?' & _RDC_GetDirectory($lParam) & '\' & $aData[$i][0]
Next
AdlibRegister('_RetrieveDirectoryChanges', 250)
Return 0
EndFunc ;==>WM_RDC
Пример4 (GUI):
См. GUI.zip внутри архива.
Скриншот:
Источник: RDC UDF (официальный форум)
Автор: Yashied