Автор Тема: RDC UDF - Мониторинг папок на предмет изменений  (Прочитано 5574 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379
  • Репутация: 2694
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
AutoIt: 3.3.6.1
Версия: 1.0

Категория: Файловая система

Описание: Хочу предложить свой способ использования API ReadDirectoryChangesW в AutoIt. Основная проблема здесь в том, что в полной мере работать с этой функцией без создания потока не получится. Для решения этой проблемы я написал простой DLL, который берет на себя всю работу с потоками. В результате AutoIt скрипту остается только принимать и обрабатывать данные, которые поступают из соответствующего потока. Для того, чтобы оценить все возможности библиотеки, посмотрите полноценный пример с GUI, который находится внутри архива. Для более подробной информации смотрите описание для каждой функции в самой библиотеке.

Ниже приведены основные характеристики библиотеки.
  • Возможность создания нескольких потоков (не лимитировано) для мониторинга разных папок.
  • Поддержка горячего (небезопасного) отключение съемных устройств, таких как USB флэш-диск, и т.д.
  • Поддержка UNC и сетевых дисков.
  • Поддержка 32- и 64-разрядных процессов (RDC.dll и RDC_x64.dll).
  • Простота использования функций библиотеки.
  • Полноценные примеры, включая GUI.

Список функций:
(нажмите для показа/скрытия)

Файл(ы): RDC.zip (x86 и x64)

Пример1 (режим цикла):
(нажмите для показа/скрытия)

Пример2 (режим уведомлений):
(нажмите для показа/скрытия)

Пример3 (режим уведомлений, расширенный):
(нажмите для показа/скрытия)

Пример4 (GUI):
(нажмите для показа/скрытия)

Скриншот:


Источник: RDC UDF (официальный форум)
Автор: Yashied
« Последнее редактирование: Июнь 08, 2015, 22:15:14 от Garrett, Причина: Проверка и исправление битых ссылок »


Думай, прежде чем говорить.

Русское сообщество AutoIt

RDC UDF - Мониторинг папок на предмет изменений
« Отправлен: Январь 26, 2015, 13:30:51 »

Оффлайн inververs [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 2135
  • Репутация: 460
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.12.0
Суппер! А на каком языке dll? можно посмотреть исходник?

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379

  • Автор темы
  • Репутация: 2694
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
А на каком языке dll?

PB 4.50

#RDC_WIN_ID = "A0397257-BD4F-41BB-914D-4E3923332BB9"

Structure Params
    *Buffer
    *Directory
    *Window
    WM.l
    Subtree.l
    Filter.l
    ID.l
    *WP
EndStructure

Structure Buffer
    *Raw
    Length.l
    Ready.l
    Wait.l
    Error.l
EndStructure

Structure DBH
    Size.l
    DeviceType.l
    Reserved.l
EndStructure

Structure DBV Extends DBH
    Mask.l
    Flags.w
EndStructure

Global Dim Thread(100, 4)

; (i, 0) - Thread ID
; (i, 1) - Pointer to the "Params" memory
; (i, 2) - Handle to the directory
; (i, 3) - Drive number ((-1), 0-25)

Import "kernel32.lib"
    GetVolumePathNameW.l(FileName, VolumePathName, BufferLength.l)
    ReadDirectoryChangesW.l(Directory, Buffer, BufferLength.l, WatchSubtree.l, NotifyFilter.l, BytesReturned, Overlapped, CompletionRoutine)
EndImport

Prototype.l GetFinalPathNameByHandleW(File, FilePath, FilePathLength.l, Flags.l)

Procedure.l GetDriveNumber(Path)
    Drive.s{1024}
    If GetVolumePathNameW(Path, @Drive, 1024)
        ProcedureReturn PathGetDriveNumber_(@Drive)
    Else
        ProcedureReturn -1
    EndIf
EndProcedure

Procedure.l GetDriveNumberByHandle(File)
    If Not OpenLibrary(0, "kernel32.dll")
        ProcedureReturn -1
    EndIf
    Path.s{4096}
    GetFinalPathNameByHandleW.GetFinalPathNameByHandleW = GetFunction(0, "GetFinalPathNameByHandleW")
    If GetFinalPathNameByHandleW(File, @Path, 4096 - 1, 0)
        Drive.l = PathGetDriveNumber_(@Path)
    Else
        Drive.l = -1
    EndIf
    CloseLibrary(0)
    ProcedureReturn Drive
EndProcedure

Procedure ReadDirectory(*Params.Params)
    *Buffer.Buffer = *Params\Buffer
    *Buffer\Ready = 0
    *Buffer\Error = 0
    While *Buffer\Wait
        Delay(10)
    Wend
    Length = 0
    Repeat
        Result = ReadDirectoryChangesW(*Params\Directory, *Buffer\Raw, *Buffer\Length, *Params\Subtree, *Params\Filter, @Length, #Null, #Null)
        If (Not Result) Or (Not Length)
            Error = GetLastError_()
            Select Error
                Case #ERROR_BAD_NET_RESP
                    ; Nothing
                Default
                    If Error
                        *Buffer\Error = Error
                    Else
                        *Buffer\Error = #ERROR_NOTIFY_ENUM_DIR
                    EndIf
                    PostMessage_(*Params\Window, *Params\WM, *Params\WP, *Params\ID)
                    Break
            EndSelect
        EndIf
        *Buffer\Ready = 1
        If *Params\Window
            PostMessage_(*Params\Window, *Params\WM, *Params\WP, *Params\ID)
        EndIf
        While *Buffer\Ready
            ; Nothing
        Wend
    ForEver
    Repeat
        Delay(1000)
    ForEver
EndProcedure

Procedure WinCallback(hWnd, uMsg, wParam, lParam)
    Select uMsg
        Case #WM_DEVICECHANGE
            Select wParam
                Case #DBT_DEVICEREMOVECOMPLETE
                    *DBH.DBH = lParam
                    Select *DBH\DeviceType
                        Case #DBT_DEVTYP_VOLUME
                            *DBV.DBV = lParam
                            For i = 0 To 25
                                If (*DBV\Mask >> i) & 1
                                    For j = 0 To ArraySize(Thread()) - 1
                                        If (Thread(j, 0)) And (Thread(j, 3) = i)
                                            If Not KillThread(Thread(j, 0))
                                                ; Nothing
                                            EndIf
                                            *Params.Params = Thread(j, 1)
                                            *Params\Directory = 0
                                            CloseHandle_(Thread(j, 2))
                                            Thread(j, 0) = CreateThread(@ReadDirectory(), Thread(j, 1))
                                            Thread(j, 2) = 0
                                            Thread(j, 3) =-1
                                            If Not Thread(j, 0)
                                                ; Nothing
                                            EndIf
                                        EndIf
                                    Next
                                    Break
                                EndIf
                            Next
                    EndSelect
            EndSelect
    EndSelect
    ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

DeclareDLL.l RDC_Delete(ID.l)

ProcedureDLL AttachProcess(Instance)
    If OpenWindow(0, #PB_Ignore, #PB_Ignore, #PB_Ignore, #PB_Ignore, #RDC_WIN_ID, #PB_Window_Invisible)
        SetWindowCallback(@WinCallback())
    EndIf
EndProcedure

ProcedureDLL DetachProcess(Instance)
    For i = 0 To ArraySize(Thread()) - 1
        RDC_Delete(i)
    Next
    SetWindowCallback(0)
    CloseWindow(0)
EndProcedure

ProcedureDLL.l RDC_Create(Path, Subtree.l, Filter.l, Buffer, Window, WM.l, WP)
    hDir = CreateFile_(Path, #FILE_LIST_DIRECTORY, #FILE_SHARE_READ | #FILE_SHARE_WRITE, #Null, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS, #Null)
    If Not hDir
        ProcedureReturn -1
    EndIf
    ID = 0
    Length = ArraySize(Thread())
    While 1
        If ID = Length
            ReDim Thread(Length + 100, ArraySize(Thread(), 2))
            Break
        EndIf
        If Not Thread(ID, 0)
            Break
        EndIf
        ID + 1
    Wend
    *Params.Params = AllocateMemory(SizeOf(Params))
    *Params\Buffer = Buffer
    *Params\Directory = hDir
    *Params\Window = Window
    *Params\WM = WM
    *Params\Subtree = Subtree
    *Params\Filter = Filter
    *Params\ID = ID
    *Params\WP = WP
    Thread(ID, 0) = CreateThread(@ReadDirectory(), *Params)
    Thread(ID, 1) = *Params
    Thread(ID, 2) = hDir
;   If OSVersion() >= #PB_OS_Windows_Vista
;       Thread(ID, 3) = GetDriveNumberByHandle(hDir)
;   Else
        Thread(ID, 3) = GetDriveNumber(Path)
;   EndIf
    If Not Thread(ID, 0)
        RDC_Delete(ID)
        ProcedureReturn -1
    EndIf
    ProcedureReturn ID
EndProcedure

ProcedureDLL.l RDC_Delete(ID.l)
    If (ID < 0) Or (ID > ArraySize(Thread())) Or (Not Thread(ID, 0))
        ProcedureReturn 0
    EndIf
    KillThread(Thread(ID, 0))
    FreeMemory(Thread(ID, 1))
    If Thread(ID, 2)
        CloseHandle_(Thread(ID, 2))
    EndIf
    Thread(ID, 0) = 0
    ProcedureReturn 1
EndProcedure
« Последнее редактирование: Январь 26, 2015, 15:11:19 от Yashied »

Оффлайн gloss [?]

  • asdasdasd, %username%
  • Новичок
  • *
  • Сообщений: 155
  • Репутация: 5
  • Пол: Мужской
  • Ленивое кодило
    • Награды
  • Версия AutoIt: 3.3.12.0
Можно ли установить исключения для некоторых папок?
В качестве папки выбираем диск С и лезем в интернет с любого браузера и получается такое чудо:
(нажмите для показа/скрытия)
Было бы очень кстати пропускать все, что происходит в C:\Users\Doctor\AppData\Roaming\Opera Software
Спасибо.

Русское сообщество AutoIt

Re: RDC UDF - Мониторинг папок на предмет изменений
« Ответ #3 Отправлен: Февраль 14, 2015, 13:52:02 »

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7816
  • Репутация: 2284
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
gloss  [?]
Цитировать
Можно ли установить исключения для некоторых папок?
Их можно фильтровать на выходе, типа:
Код: AutoIt [Выделить]
If _RDC_GetDirectory($ID[$i]) <> @AppDataDir & '\Opera Software' Then
;Заносим папку в список
EndIf



Правила, Поиск, Супер тема


AutoIt is simple, subtle, elegant.


«Не оказываю тех. поддержку через ПМ/ICQ, и по электронной почте - для этого есть форум. (C)»
«Законы Мэрфи неоспоримы!»


Мои работы

Оффлайн gloss [?]

  • asdasdasd, %username%
  • Новичок
  • *
  • Сообщений: 155
  • Репутация: 5
  • Пол: Мужской
  • Ленивое кодило
    • Награды
  • Версия AutoIt: 3.3.12.0
Эхх.. Моих знаний не хватает чтобы додумать куда это пристроить и что еще нужно дописать. Нет понимания как это работает. :(

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7816
  • Репутация: 2284
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
gloss  [?]
Цитировать
Нет понимания как это работает
В примере с GUI найти:
Код: AutoIt [Выделить]
Global Const $GUI_NAME = 'RDC UDF Example'

заменить на:
Код: AutoIt [Выделить]
Global Const $aExcludes = StringSplit(@ProgramFilesDir & '|' & @AppDataDir & '\Opera Software', '|')
Global Const $GUI_NAME = 'RDC UDF Example'

далее найти:
Код: AutoIt [Выделить]
                For $i = 1 To $aData[0][0]
                    $LV[$ID][6] &= $aData[$i][1] & '*\' & $aData[$i][0] & '*' & _WinAPI_GetDateFormat() & ' ' & _WinAPI_GetTimeFormat(0, 0, $TIME_NOSECONDS) & '|'
                Next

и заменить на:
Код: AutoIt [Выделить]
                Local $sRoot = _RDC_GetDirectory($lParam)
               
                For $i = 1 To $aData[0][0]
                    For $j = 1 To $aExcludes[0]
                        If $sRoot & $aData[$i][0] = $aExcludes[$j] Or StringInStr($sRoot & $aData[$i][0], $aExcludes[$j] & '\', 2) Then
                            Return 0
                        EndIf
                    Next
                   
                    $LV[$ID][6] &= $aData[$i][1] & '*\' & $aData[$i][0] & '*' & _WinAPI_GetDateFormat() & ' ' & _WinAPI_GetTimeFormat(0, 0, $TIME_NOSECONDS) & '|'
                Next


Список исключений указывается в первой строчке замены.

Оффлайн gloss [?]

  • asdasdasd, %username%
  • Новичок
  • *
  • Сообщений: 155
  • Репутация: 5
  • Пол: Мужской
  • Ленивое кодило
    • Награды
  • Версия AutoIt: 3.3.12.0
CreatoR
Долго не мог понять как Список исключений указывается в первой строчке замены.
Все же дошло :) И еще раз большое спасибо!
Код: AutoIt [Выделить]
Global Const $aExcludes = StringSplit(@LocalAppDataDir & '|' & @AppDataDir & '\Opera Software' & '|' & @CRLF & _
                                        @LocalAppDataDir & '|' & @AppDataDir & '\Notepad++', '|')


Русское сообщество AutoIt

Re: RDC UDF - Мониторинг папок на предмет изменений
« Ответ #7 Отправлен: Февраль 14, 2015, 18:35:26 »

Оффлайн Vlasssov [?]

  • Осваивающий
  • **
  • Сообщений: 421
  • Репутация: 25
  • Пол: Мужской
  • Гопломах
    • Награды
  • Версия AutoIt: 3.3.14.0
Вопрос: а пользователей, которые добавили, удалили или произвели модификацию файлов, как-то отловить можно?

Оффлайн SlavaS [?]

  • Новичок
  • *
  • Сообщений: 35
  • Репутация: 5
    • Награды
  • Версия AutoIt: 3.3.12.0
Тоже очень интересует данный вопрос. :)

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379

  • Автор темы
  • Репутация: 2694
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
Друзья, я предоставил UDF, а не программу. Вопрос про пользователей выходит за рамки данной темы. В любом случае пользователей отследить можно...

Оффлайн Vlasssov [?]

  • Осваивающий
  • **
  • Сообщений: 421
  • Репутация: 25
  • Пол: Мужской
  • Гопломах
    • Награды
  • Версия AutoIt: 3.3.14.0
Друзья, я предоставил UDF, а не программу. Вопрос про пользователей выходит за рамки данной темы. В любом случае пользователей отследить можно...
Может отдельную тему, обсудить...  :laugh:

Оффлайн pirpitum [?]

  • Новичок
  • *
  • Сообщений: 5
  • Репутация: 0
    • Награды
здравствуйте, написал с помощью библиотеки программу для отслеживания изменений в текстовом файле в расшаренной папке, пока она была расшарена на 2003 сервере проблем не было. После замены на 2008 сервер перестало работать, отслеживание "засыпает". Если файл открыть блокнотом продолжает какое-то время работать.

Русское сообщество AutoIt

Re: RDC UDF - Мониторинг папок на предмет изменений
« Ответ #12 Отправлен: Август 09, 2017, 04:53:56 »

 

Похожие темы

  Тема / Автор Ответов Последний ответ
2 Ответов
8143 Просмотров
Последний ответ Октябрь 22, 2009, 17:44:02
от Yashied
33 Ответов
17857 Просмотров
Последний ответ Сентябрь 06, 2010, 12:32:16
от Alexey
38 Ответов
31246 Просмотров
Последний ответ Декабрь 09, 2015, 19:32:13
от Yashied
1 Ответов
2082 Просмотров
Последний ответ Март 05, 2012, 10:22:06
от joiner
5 Ответов
4038 Просмотров
Последний ответ Апрель 17, 2012, 18:45:25
от madmasles
2 Ответов
2813 Просмотров
Последний ответ Сентябрь 19, 2012, 20:52:30
от zlo-kazan
1 Ответов
1691 Просмотров
Последний ответ Сентябрь 11, 2014, 09:34:35
от oesoes
6 Ответов
2784 Просмотров
Последний ответ Май 13, 2015, 11:58:30
от C2H5OH
6 Ответов
2104 Просмотров
Последний ответ Ноябрь 08, 2015, 13:33:14
от joiner
7 Ответов
462 Просмотров
Последний ответ Август 06, 2017, 14:07:43
от ra4o