Class: Win32::ChangeNotify

Inherits:
Ipc
  • Object
show all
Extended by:
Windows::Functions
Includes:
Windows::Constants, Windows::Functions, Windows::Structs
Defined in:
lib/win32/changenotify.rb

Overview

The Win32::ChangeNotify class encapsulates filesystem change notifications

Defined Under Namespace

Classes: ChangeNotifyStruct

Constant Summary collapse

VERSION =

The version of the win32-changenotify library

'0.6.1'
ATTRIBUTES =

Filter: Attribute changes

FILE_NOTIFY_CHANGE_ATTRIBUTES
DIR_NAME =

Filter: Directory name changes

FILE_NOTIFY_CHANGE_DIR_NAME
FILE_NAME =

Filter: File name changes

FILE_NOTIFY_CHANGE_FILE_NAME
LAST_WRITE =

Filter: Write changes

FILE_NOTIFY_CHANGE_LAST_WRITE
SECURITY =

Filter: File security changes

FILE_NOTIFY_CHANGE_SECURITY
SIZE =

Filter: File size changes

FILE_NOTIFY_CHANGE_SIZE

Constants included from Windows::Constants

Windows::Constants::FILE_ACTION_ADDED, Windows::Constants::FILE_ACTION_MODIFIED, Windows::Constants::FILE_ACTION_REMOVED, Windows::Constants::FILE_ACTION_RENAMED_NEW_NAME, Windows::Constants::FILE_ACTION_RENAMED_OLD_NAME, Windows::Constants::FILE_FLAG_BACKUP_SEMANTICS, Windows::Constants::FILE_FLAG_OVERLAPPED, Windows::Constants::FILE_LIST_DIRECTORY, Windows::Constants::FILE_NOTIFY_CHANGE_ATTRIBUTES, Windows::Constants::FILE_NOTIFY_CHANGE_CREATION, Windows::Constants::FILE_NOTIFY_CHANGE_DIR_NAME, Windows::Constants::FILE_NOTIFY_CHANGE_FILE_NAME, Windows::Constants::FILE_NOTIFY_CHANGE_LAST_ACCESS, Windows::Constants::FILE_NOTIFY_CHANGE_LAST_WRITE, Windows::Constants::FILE_NOTIFY_CHANGE_SECURITY, Windows::Constants::FILE_NOTIFY_CHANGE_SIZE, Windows::Constants::FILE_SHARE_DELETE, Windows::Constants::FILE_SHARE_READ, Windows::Constants::FILE_SHARE_WRITE, Windows::Constants::INVALID_HANDLE_VALUE, Windows::Constants::OPEN_EXISTING

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Windows::Functions

raise_windows_error, win_error

Constructor Details

#initialize(path, recursive, filter, event = nil) ⇒ ChangeNotify

Returns a new ChangeNotify object and places a monitor on path. The path argument may be a file or a directory.

If +recursive is true and path is a directory, then the monitor applies to all subdirectories of path.

The filter tells the monitor what to watch for, such as file changes, attribute changes, etc.

If the event option is specified, it must be a Win32::Event object. It is then set as the event that will be set to the signaled state when a notification has been completed.

Yields itself if a block is provided, and automatically closes itself when the block terminates.

Raises:

  • (TypeError)


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/win32/changenotify.rb', line 68

def initialize(path, recursive, filter, event=nil)
  @path      = path
  @recursive = recursive
  @filter    = filter
  @overlap   = OVERLAPPED.new

  # Because Win32API doesn't do type checking, we do it expicitly here.
  raise TypeError unless path.is_a?(String)
  raise TypeError unless [true, false].include?(recursive)
  raise TypeError unless filter.is_a?(Fixnum)

  if event
    raise TypeError unless event.respond_to?(:handle)
    @handle = event.handle
  else
    event = Win32::Event.new
    @handle = event.handle
  end

  @event = event

  @overlap[:hEvent] = @handle

  super(@handle)

  if block_given?
    begin
      yield self
    ensure
      close
    end
  end
end

Instance Attribute Details

#filterObject (readonly)

The value of the filter (OR’d constants) passed to the constructor



50
51
52
# File 'lib/win32/changenotify.rb', line 50

def filter
  @filter
end

#pathObject (readonly)

The path that was provided to the constructor



47
48
49
# File 'lib/win32/changenotify.rb', line 47

def path
  @path
end

Instance Method Details

#ipc_waitObject



109
# File 'lib/win32/changenotify.rb', line 109

alias ipc_wait wait

#recursive?Boolean

Returns whether or not the ChangeNotify object is monitoring subdirectories of the path being monitored.

Returns:

  • (Boolean)


105
106
107
# File 'lib/win32/changenotify.rb', line 105

def recursive?
  @recursive
end

#wait(seconds = INFINITE) ⇒ Object

Waits up to ‘seconds’ for a notification to occur, or infinitely if no value is specified.

Yields an array of ChangeNotifyStruct’s that contains two members: file_name and action.



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/win32/changenotify.rb', line 117

def wait(seconds = INFINITE)
  seconds *= 1000 unless seconds == INFINITE

  fni_ptr = FFI::MemoryPointer.new(FILE_NOTIFY_INFORMATION, 4096)
  rbytes  = FFI::MemoryPointer.new(:ulong)
  qbytes  = FFI::MemoryPointer.new(:ulong)

  dir_handle = get_dir_handle(@path)

  comp_key = FFI::MemoryPointer.new(:ulong)
  comp_key.write_ulong(12345)

  begin
    comp_port = CreateIoCompletionPort(dir_handle, 0, comp_key, 0)

    if comp_port == 0
      raise SystemCallError.new('CreateIoCompletionPort', FFI.errno)
    end

    bool = ReadDirectoryChangesW(
       dir_handle,
       fni_ptr,
       fni_ptr.size,
       @recursive,
       @filter,
       rbytes,
       @overlap,
       nil
    )

    raise_windows_error('ReadDirectoryChangesW') unless bool

    while true
      bool = GetQueuedCompletionStatus(
        comp_port,
        qbytes,
        comp_key,
        @overlap,
        seconds
      )

      raise_windows_error('GetQueuedCompletionStatus') unless bool

      @signaled = true
      @event.signaled = true

      break if comp_key.read_ulong == 0

      yield get_file_action(fni_ptr) if block_given?

      bool = ReadDirectoryChangesW(
        dir_handle,
        fni_ptr,
        fni_ptr.size,
        @recursive,
        @filter,
        rbytes,
        @overlap,
        nil
      )

      raise_windows_error('ReadDirectoryChangesW') unless bool
    end
  ensure
    CloseHandle(dir_handle)
  end
end