Пример #1
0
    def _loop_asynchronous(self, callback):
        buf = win32file.AllocateReadBuffer(8192)
        overlapped = pywintypes.OVERLAPPED()
        overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None)

        while not self._stopped:

            win32file.ReadDirectoryChangesW(self._hdir, buf, self._recurse,
                                            self._filter, overlapped)

            ##
            ## This will block until notification OR timeout.
            ##
            rc = win32event.WaitForSingleObject(overlapped.hEvent,
                                                self._timeout)
            if rc == win32event.WAIT_OBJECT_0:
                ## got event: determine data length ..
                n = win32file.GetOverlappedResult(self._hdir, overlapped, True)
                if n:
                    ## retrieve data
                    results = win32file.FILE_NOTIFY_INFORMATION(buf, n)
                    r = [(DirWatcher._ACTIONS.get(x[0], "UNKNOWN"), x[1])
                         for x in results]
                    if len(r) > 0:
                        callback(r)
                else:
                    # directory handled was closed
                    self._stopped = True
            else:
                ## timeout
                pass
 def _watcherThreadOverlapped(self, dn, dh, changes):
     flags = win32con.FILE_NOTIFY_CHANGE_FILE_NAME
     buf = win32file.AllocateReadBuffer(8192)
     overlapped = pywintypes.OVERLAPPED()
     overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None)
     while 1:
         win32file.ReadDirectoryChangesW(
             dh,
             buf,
             False,  #sub-tree
             flags,
             overlapped)
         # Wait for our event, or for 5 seconds.
         rc = win32event.WaitForSingleObject(overlapped.hEvent, 5000)
         if rc == win32event.WAIT_OBJECT_0:
             # got some data!  Must use GetOverlappedResult to find out
             # how much is valid!  0 generally means the handle has
             # been closed.  Blocking is OK here, as the event has
             # already been set.
             nbytes = win32file.GetOverlappedResult(dh, overlapped, True)
             if nbytes:
                 bits = win32file.FILE_NOTIFY_INFORMATION(buf, nbytes)
                 changes.extend(bits)
             else:
                 # This is "normal" exit - our 'tearDown' closes the
                 # handle.
                 # print "looks like dir handle was closed!"
                 return
         else:
             print("ERROR: Watcher thread timed-out!")
             return  # kill the thread!
Пример #3
0
 def _read_watch(self, watch):
     if win32event.WaitForSingleObject(watch.event, 0) \
             == win32event.WAIT_TIMEOUT:
         nbytes = 0
     else:
         nbytes = win32file.GetOverlappedResult(watch.handle,
                                                watch.overlapped, False)
     return win32file.FILE_NOTIFY_INFORMATION(watch.buffer, nbytes)
Пример #4
0
 def read(self):
     if win32event.WaitForSingleObject(self.event, 0) \
             == win32event.WAIT_TIMEOUT:
         result = []
     else:
         nbytes = win32file.GetOverlappedResult(self.handle,
                                                self.overlapped, False)
         result = win32file.FILE_NOTIFY_INFORMATION(self.buffer, nbytes)
         self._start()
     return result
Пример #5
0
def process_events(watch, num):
    for action, name in win32file.FILE_NOTIFY_INFORMATION(watch._buf.raw, num):
        action = action_map.get(action)
        if action is not None and (action & watch.flags):
            yield FSEvent(watch, action, name)
    try:
        read_changes(watch)
    except pywintypes.error as e:
        if e.args[0] == 5:
            close_watch(watch)
            yield FSEvent(watch, FSEvent.DeleteSelf)
        else:
            raise FSMonitorWindowsError(*e.args)
Пример #6
0
    def run(self):
        hDir = win32file.CreateFileW(
            self._watch_path,
            FILE_LIST_DIRECTORY,
            win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE,
            None,
            win32con.OPEN_EXISTING,
            win32con.FILE_FLAG_BACKUP_SEMANTICS |
            win32con.FILE_FLAG_OVERLAPPED,
            None
        )
        while self._windows_sucks_flag:
            buf = win32file.AllocateReadBuffer(1024)
            win32file.ReadDirectoryChangesW(
                hDir,
                buf,
                True,
                win32con.FILE_NOTIFY_CHANGE_FILE_NAME |
                win32con.FILE_NOTIFY_CHANGE_DIR_NAME |
                win32con.FILE_NOTIFY_CHANGE_SIZE |
                win32con.FILE_NOTIFY_CHANGE_LAST_WRITE,
                self._overlapped
            )
            result_stack = {}
            rc = win32event.WaitForMultipleObjects((self._wait_stop,
                                                    self._overlapped.hEvent),
                                                   0, win32event.INFINITE)
            if rc == win32event.WAIT_OBJECT_0:
                # Stop event
                break

            data = win32file.GetOverlappedResult(hDir, self._overlapped, True)
            # lets read the data and store it in the results
            results = win32file.FILE_NOTIFY_INFORMATION(buf, data)

            for action, afile in results:
                if action in ACTIONS:
                    full_filename = os.path.join(self._watch_path, afile)
                    result_stack.setdefault(full_filename,
                                            []).append(ACTIONS.get(action))
            keys = list(result_stack.keys())
            while len(keys):
                key = keys.pop(0)
                event = result_stack.pop(key)
                if (ADDED in event) and (DELETED in event):
                    event = [e for e in event if e not in (ADDED, DELETED)]
                noticed = []
                for each_event in event:
                    if each_event not in noticed:
                        self._callback(each_event, full_filename)
                        noticed.append(each_event)
Пример #7
0
 def process_events(watch, num):
     for action, name in win32file.FILE_NOTIFY_INFORMATION(
             watch._buf.raw, num):
         if action is not None and (
                 action & win32con.FILE_NOTIFY_CHANGE_FILE_NAME
                 | win32con.FILE_NOTIFY_CHANGE_LAST_WRITE):
             yield FSEvent(watch, action, name)
     try:
         read_changes(watch)
     except pywintypes.error, e:
         if e.args[0] == 5:
             close_watch(watch)
             yield FSEvent(watch, FSEvent.DeleteSelf)
         else:
             raise FSMonitorWindowsError(*e.args)
Пример #8
0
def monitor_dir_async(file_path, handle_function, run, key):
    dir_handle = get_dir_handle(file_path, True)
    buffer = win32file.AllocateReadBuffer(BUF_SIZE)
    overlapped = pywintypes.OVERLAPPED()
    overlapped.hEvent = win32event.CreateEvent(None, False, 0, None)
    while run.value:
        read_dir_changes(dir_handle, buffer, overlapped)
        rc = win32event.WaitForSingleObject(overlapped.hEvent, ASYNC_TIMEOUT)
        if rc == win32event.WAIT_OBJECT_0:
            bufer_size = win32file.GetOverlappedResult(dir_handle, overlapped,
                                                       True)
            results = win32file.FILE_NOTIFY_INFORMATION(buffer, bufer_size)
            handle_function(results, file_path, key)
        elif rc == win32event.WAIT_TIMEOUT:
            pass
    win32api.CloseHandle(overlapped.hEvent)
    dir_handle.close()
Пример #9
0
    def _read_events(self):
        """Reads the events from the system and formats as ``DirWatcherEvent``.

        :returns: List of ``(DirWatcherEvent, <path>)``
        """
        result = []

        while self._changed:
            info = self._changed.popleft()

            try:
                size = win32file.GetOverlappedResult(info.file,
                                                     info.overlapped,
                                                     False)
            except win32file.error as exc:
                win32event.ResetEvent(info.overlapped.hEvent)
                _LOGGER.warning(
                    'Failed to get directory changes for \'%s\': %s',
                    info.path, exc)

                if exc.winerror == winerror.ERROR_ACCESS_DENIED:
                    self._preempt_watch(info, result)
                continue

            notifications = win32file.FILE_NOTIFY_INFORMATION(info.buffer,
                                                              size)

            for action, path in notifications:
                action_name = _ACTION_NAMES.get(action)
                path = os.path.join(info.path, path)
                if action_name is None:
                    _LOGGER.error('Received unknown action (%s, \'%s\')',
                                  action, path)
                    continue

                _LOGGER.debug('Received event (%s, \'%s\')', action_name, path)

                event = _EVENTS.get(action_name)
                if event is not None:
                    result.append((event, path))

            win32event.ResetEvent(info.overlapped.hEvent)
            if not self._read_dir(info):
                self._preempt_watch(info, result)

        return result
Пример #10
0
def main():
    flags = win32con.FILE_NOTIFY_CHANGE_FILE_NAME
    dh = win32file.CreateFile(
        "C:\\", 0x0001, win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE
        | win32con.FILE_SHARE_DELETE, None, win32con.OPEN_EXISTING,
        win32con.FILE_FLAG_BACKUP_SEMANTICS | win32con.FILE_FLAG_OVERLAPPED,
        None)
    overlapped = pywintypes.OVERLAPPED()
    overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None)
    buf = win32file.AllocateReadBuffer(8192)

    changes = []
    iterations = 0
    timedout = False

    while True:
        iterations += 1
        print(iterations)

        if timedout == False:  # This is to ensure the directory handle only has one instance of ReadDirectoryChangesW at a time.
            # If this isn't here and ReadDirectoryChangesW stacks up without being used, it will break after 60-64 iterations if
            # using a mapped network folder and the directory handle will need to be closed (dh.close()) and reopened.
            win32file.ReadDirectoryChangesW(dh, buf, True, flags, overlapped)

        rc = win32event.MsgWaitForMultipleObjects([overlapped.hEvent], False,
                                                  5000,
                                                  win32event.QS_ALLEVENTS)
        # rc = win32event.WaitForSingleObject(overlapped.hEvent, 5000)                  # Also acceptable
        # rc = win32event.WaitForMultipleObjects([overlapped.hEvent], False, 5000)      # Also acceptable
        if rc == win32event.WAIT_TIMEOUT:
            timedout = True
            print('timed out')
        if rc == win32event.WAIT_OBJECT_0:  # can replace win32event.WAIT_OBJECT_0 with the integer 0 (and win32event.WAIT_OBJECT_0+1 with 1)
            timedout = False  # since we got a result, reset the timedout variable so ReadDirectoryChangesW can be run again
            result = win32file.GetOverlappedResult(dh, overlapped, True)
            if result:
                bufferData = win32file.FILE_NOTIFY_INFORMATION(buf, result)
                changes.extend(bufferData)
                print(bufferData)
                for x in bufferData:
                    if x[1] == 'break':  # for testing, create a file named "break" in the watched folder and the script will stop and print the list of files
                        print("\nFinal result!")
                        return changes
            else:
                print('dir handle closed')
Пример #11
0
    def run_win32(self):
        """Generate notifications using pywin32"""

        hdir = win32file.CreateFile(
                self._path,
                0x0001,
                win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE,
                None,
                win32con.OPEN_EXISTING,
                win32con.FILE_FLAG_BACKUP_SEMANTICS |
                win32con.FILE_FLAG_OVERLAPPED,
                None)

        flags = (win32con.FILE_NOTIFY_CHANGE_FILE_NAME |
                 win32con.FILE_NOTIFY_CHANGE_DIR_NAME |
                 win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES |
                 win32con.FILE_NOTIFY_CHANGE_SIZE |
                 win32con.FILE_NOTIFY_CHANGE_LAST_WRITE |
                 win32con.FILE_NOTIFY_CHANGE_SECURITY)

        buf = win32file.AllocateReadBuffer(8192)
        overlapped = pywintypes.OVERLAPPED()
        overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None)

        handler = Handler()
        while self._running:
            win32file.ReadDirectoryChangesW(hdir, buf, True, flags, overlapped)

            rc = win32event.WaitForSingleObject(overlapped.hEvent,
                                                self._timeout)
            if rc != win32event.WAIT_OBJECT_0:
                continue
            nbytes = win32file.GetOverlappedResult(hdir, overlapped, True)
            if not nbytes:
                continue
            results = win32file.FILE_NOTIFY_INFORMATION(buf, nbytes)
            for action, path in results:
                if not self._running:
                    break
                path = path.replace('\\', '/')
                if (not path.startswith('.git/') and
                        '/.git/' not in path and os.path.isfile(path)):
                    handler.handle(path)
Пример #12
0
    async def polling_task(self):
        while True:
            for item in self._watch_list:
                try:
                    length = win32file.GetOverlappedResult(item[2], item[3], 0)
                except pywintypes.error as e:
                    if e.args[0] == 996:
                        # Overlapped I/O event is not in a signaled state
                        continue
                    else:
                        raise e
                else:
                    for action, name in win32file.FILE_NOTIFY_INFORMATION(
                            item[-1], length):
                        target = os.path.join(item[1], name)
                        if action == FILE_ACTION_MODIFIED and not os.path.isfile(
                                target):
                            # Ignore directory modify event
                            continue
                        elif action == FILE_ACTION_MODIFIED and os.path.isfile(
                                target):
                            dir_node = self._get_dir_node(item[1])
                            if name not in dir_node:
                                # Auto insert file create event
                                self._event_queue.put_nowait(
                                    (target, item[0], FILE_ACTION_ADDED))
                                dir_node[name] = None
                        elif action == FILE_ACTION_REMOVED:
                            path = target
                            remove_root = target
                            while not os.path.exists(path):
                                # Get remove root
                                remove_root = path
                                path = os.path.dirname(path)

                            if self._get_dir_node(remove_root):
                                # Insert remove sub dirs/files event
                                def _handle_sub_dir(path):
                                    dir_node = self._get_dir_node(path)
                                    for it in dir_node:
                                        if isinstance(dir_node[it], dict):
                                            if dir_node[it]:
                                                _handle_sub_dir(
                                                    os.path.join(path, it))
                                            self._event_queue.put_nowait((
                                                os.path.join(path, it),
                                                EnumWatchType.WATCH_DIRECTORY,
                                                action,
                                            ))
                                        else:
                                            self._event_queue.put_nowait((
                                                os.path.join(path, it),
                                                EnumWatchType.WATCH_FILE,
                                                action,
                                            ))

                                _handle_sub_dir(remove_root)
                                self._event_queue.put_nowait((
                                    remove_root,
                                    EnumWatchType.WATCH_DIRECTORY,
                                    action,
                                ))
                                parent_dir_node = self._get_dir_node(
                                    os.path.dirname(remove_root))
                                parent_dir_node.pop(
                                    os.path.split(remove_root)[-1])
                                continue

                        self._event_queue.put_nowait((target, item[0], action))
                        if action == FILE_ACTION_ADDED and os.path.isdir(
                                target):
                            # Handle mkdir -p
                            def _handle_sub_dir(path):
                                dir_node = self._get_dir_node(path, True)
                                for it in os.listdir(path):
                                    if it in dir_node:
                                        continue
                                    subpath = os.path.join(path, it)
                                    if os.path.isdir(subpath):
                                        watch_type = EnumWatchType.WATCH_DIRECTORY
                                        dir_node[it] = {}
                                    else:
                                        watch_type = EnumWatchType.WATCH_FILE
                                        dir_node[it] = None

                                    self._event_queue.put_nowait(
                                        (subpath, watch_type, action))

                                    if os.path.isdir(subpath):
                                        _handle_sub_dir(subpath)

                            dir_node = self._get_dir_node(item[1])
                            dir_node[name] = {}
                            _handle_sub_dir(target)
                        elif action == FILE_ACTION_ADDED and os.path.isfile(
                                target):
                            # Auto fire modify event
                            self._event_queue.put_nowait(
                                (target, item[0], FILE_ACTION_MODIFIED))
                            dir_node = self._get_dir_node(
                                os.path.dirname(target))
                            dir_node[os.path.split(target)[-1]] = None

                    # Continue to listen
                    self._add_dir_watch(item[2], item[4], item[3])
                    self._add_file_watch(item[2], item[4], item[3])

            await asyncio.sleep(0.005)
Пример #13
0
import os, sys

import pywintypes
import win32file
import win32event
import win32con
import ntsecuritycon

overlapped = pywintypes.OVERLAPPED()
overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None)

hDir = win32file.CreateFile(
    "c:/temp", ntsecuritycon.FILE_LIST_DIRECTORY, win32file.FILE_SHARE_READ
    | win32file.FILE_SHARE_WRITE | win32file.FILE_SHARE_DELETE, None,
    win32con.OPEN_EXISTING,
    win32con.FILE_FLAG_BACKUP_SEMANTICS | win32con.FILE_FLAG_OVERLAPPED, None)
buffer = win32file.AllocateReadBuffer(8192)
while True:
    print "#0", win32file.ReadDirectoryChangesW(
        hDir, buffer, True, win32con.FILE_NOTIFY_CHANGE_FILE_NAME, overlapped)
    print "#1"
    rc = win32event.WaitForSingleObject(overlapped.hEvent, 1000)
    print "#2", rc
    if rc == win32event.WAIT_OBJECT_0:
        n_bytes = win32file.GetOverlappedResult(hDir, overlapped, True)
        if n_bytes:
            print win32file.FILE_NOTIFY_INFORMATION(buffer, n_bytes)
        else:
            break