- Сообщения
 - 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
	            
	
 И еще раз большое спасибо!