win32-dirmonitor 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +3 -0
- data.tar.gz.sig +0 -0
- data/CHANGES +9 -3
- data/MANIFEST +10 -8
- data/README +52 -52
- data/Rakefile +33 -36
- data/certs/djberg96_pub.pem +21 -0
- data/examples/example_dirmonitor.rb +23 -23
- data/lib/win32-dirmonitor.rb +1 -0
- data/lib/win32/dirmonitor.rb +146 -146
- data/test/test_win32_dirmonitor.rb +103 -103
- data/win32-dirmonitor.gemspec +29 -30
- metadata +38 -14
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b7d19278a61fb675f90a483805d92d8334034862
|
4
|
+
data.tar.gz: 098bcb0d5142f1f8aa056d15036993ae56d9c908
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93097e36d0d14edb6820bf8761327651227fa9b55d38841cde4d2d39327a3286c7e683568ef7c4dac50d1389599b909dcb676f257bf42294d06fb37a3c6c5984
|
7
|
+
data.tar.gz: dd53036b71354d452ee9410d8e2cf8040a5cd70d6c094c99b869f3e568b1e61167b50658ae89f15045846e732c8ec8e659944ae2c1b19b83a7f7e99b06765609
|
checksums.yaml.gz.sig
ADDED
data.tar.gz.sig
ADDED
Binary file
|
data/CHANGES
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
-
== 1.0.
|
2
|
-
*
|
3
|
-
*
|
1
|
+
== 1.0.1 - 20-Oct-2015
|
2
|
+
* The gem is now signed.
|
3
|
+
* Fixed a deprecation warning.
|
4
|
+
* Any gem related tasks in the Rakefile now assume Rubygems 2.x.
|
5
|
+
* Added a win32-dirmonitor.rb file for convenience.
|
6
|
+
|
7
|
+
== 1.0.0 - 22-Jan-2014
|
8
|
+
* Initial release.
|
9
|
+
* This library replaces win32-changejournal.
|
data/MANIFEST
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
* CHANGES
|
2
|
-
* README
|
3
|
-
* MANIFEST
|
4
|
-
* Rakefile
|
5
|
-
* win32-dirmonitor.gemspec
|
6
|
-
*
|
7
|
-
*
|
8
|
-
*
|
1
|
+
* CHANGES
|
2
|
+
* README
|
3
|
+
* MANIFEST
|
4
|
+
* Rakefile
|
5
|
+
* win32-dirmonitor.gemspec
|
6
|
+
* cert/djberg96_pub.pem
|
7
|
+
* lib/win32-dirmonitor.rb
|
8
|
+
* lib/win32/dirmonitor.rb
|
9
|
+
* examples/example_dirmonitor.rb
|
10
|
+
* test/test_win32_dirmonitor.rb
|
data/README
CHANGED
@@ -1,52 +1,52 @@
|
|
1
|
-
== Description
|
2
|
-
A class for monitoring directories on MS Windows.
|
3
|
-
|
4
|
-
== Installation
|
5
|
-
gem install win32-dirmonitor
|
6
|
-
|
7
|
-
== Synopsis
|
8
|
-
require 'win32/dirmonitor'
|
9
|
-
include Win32
|
10
|
-
|
11
|
-
# Wait for a change in your home directory and report any changes.
|
12
|
-
|
13
|
-
monitor = Win32::DirMonitor.new(ENV['HOME'])
|
14
|
-
|
15
|
-
# Wait up to 5 minutes for a change.
|
16
|
-
monitor.wait(300){ |struct|
|
17
|
-
puts 'Something changed'
|
18
|
-
puts 'File: ' + struct.file
|
19
|
-
puts 'Action: ' + struct.action
|
20
|
-
struct.changes.each do |change|
|
21
|
-
puts "Change: " + change[0].to_s
|
22
|
-
puts "Old: " + change[1].to_s
|
23
|
-
puts "New: " + change[2].to_s
|
24
|
-
end
|
25
|
-
}
|
26
|
-
|
27
|
-
== Notes
|
28
|
-
This replaces the win32-changejournal library and supplants the
|
29
|
-
win32-changenotify library since it gives details about the changes
|
30
|
-
that occur.
|
31
|
-
|
32
|
-
== Future Plans
|
33
|
-
Allow files in subdirectories to be monitored as well.
|
34
|
-
|
35
|
-
== Known Bugs
|
36
|
-
None that I know of. Please log any bug reports on the RubyForge
|
37
|
-
project page at https://github.com/djberg96/win32-dirmonitor.
|
38
|
-
|
39
|
-
== License
|
40
|
-
Artistic 2.0
|
41
|
-
|
42
|
-
== Copyright
|
43
|
-
(C) 2014 Daniel J. Berger, All Rights Reserved
|
44
|
-
|
45
|
-
== Warranty
|
46
|
-
This library is provided "as is" and without any express or
|
47
|
-
implied warranties, including, without limitation, the implied
|
48
|
-
warranties of merchantability and fitness for a particular purpose.
|
49
|
-
|
50
|
-
== Authors
|
51
|
-
* Daniel J. Berger
|
52
|
-
* Park Heesob
|
1
|
+
== Description
|
2
|
+
A class for monitoring directories on MS Windows.
|
3
|
+
|
4
|
+
== Installation
|
5
|
+
gem install win32-dirmonitor
|
6
|
+
|
7
|
+
== Synopsis
|
8
|
+
require 'win32/dirmonitor'
|
9
|
+
include Win32
|
10
|
+
|
11
|
+
# Wait for a change in your home directory and report any changes.
|
12
|
+
|
13
|
+
monitor = Win32::DirMonitor.new(ENV['HOME'])
|
14
|
+
|
15
|
+
# Wait up to 5 minutes for a change.
|
16
|
+
monitor.wait(300){ |struct|
|
17
|
+
puts 'Something changed'
|
18
|
+
puts 'File: ' + struct.file
|
19
|
+
puts 'Action: ' + struct.action
|
20
|
+
struct.changes.each do |change|
|
21
|
+
puts "Change: " + change[0].to_s
|
22
|
+
puts "Old: " + change[1].to_s
|
23
|
+
puts "New: " + change[2].to_s
|
24
|
+
end
|
25
|
+
}
|
26
|
+
|
27
|
+
== Notes
|
28
|
+
This replaces the win32-changejournal library and supplants the
|
29
|
+
win32-changenotify library since it gives details about the changes
|
30
|
+
that occur.
|
31
|
+
|
32
|
+
== Future Plans
|
33
|
+
Allow files in subdirectories to be monitored as well.
|
34
|
+
|
35
|
+
== Known Bugs
|
36
|
+
None that I know of. Please log any bug reports on the RubyForge
|
37
|
+
project page at https://github.com/djberg96/win32-dirmonitor.
|
38
|
+
|
39
|
+
== License
|
40
|
+
Artistic 2.0
|
41
|
+
|
42
|
+
== Copyright
|
43
|
+
(C) 2014-2015 Daniel J. Berger, All Rights Reserved
|
44
|
+
|
45
|
+
== Warranty
|
46
|
+
This library is provided "as is" and without any express or
|
47
|
+
implied warranties, including, without limitation, the implied
|
48
|
+
warranties of merchantability and fitness for a particular purpose.
|
49
|
+
|
50
|
+
== Authors
|
51
|
+
* Daniel J. Berger
|
52
|
+
* Park Heesob
|
data/Rakefile
CHANGED
@@ -1,36 +1,33 @@
|
|
1
|
-
require 'rake'
|
2
|
-
require 'rake/clean'
|
3
|
-
require 'rake/testtask'
|
4
|
-
|
5
|
-
CLEAN.include("**/*.gem", "**/*.rbc", "**/*.rbx")
|
6
|
-
|
7
|
-
namespace :gem do
|
8
|
-
desc "Create the win32-dirmonitor gem"
|
9
|
-
task :create => [:clean] do
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
task :default => :test
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/clean'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
CLEAN.include("**/*.gem", "**/*.rbc", "**/*.rbx")
|
6
|
+
|
7
|
+
namespace :gem do
|
8
|
+
desc "Create the win32-dirmonitor gem"
|
9
|
+
task :create => [:clean] do
|
10
|
+
require 'rubygems/package'
|
11
|
+
spec = eval(IO.read('win32-dirmonitor.gemspec'))
|
12
|
+
spec.signing_key = File.join(Dir.home, '.ssh', 'gem-private_key.pem')
|
13
|
+
Gem::Package.build(spec)
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Install the win32-clipboard library"
|
17
|
+
task :install => [:create] do
|
18
|
+
file = Dir["*.gem"].first
|
19
|
+
sh "gem install -l #{file}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'Run the example program'
|
24
|
+
task :example do |t|
|
25
|
+
ruby '-Ilib examples/example_dirmonitor.rb'
|
26
|
+
end
|
27
|
+
|
28
|
+
Rake::TestTask.new(:test) do |t|
|
29
|
+
t.warning = true
|
30
|
+
t.verbose = true
|
31
|
+
end
|
32
|
+
|
33
|
+
task :default => :test
|
@@ -0,0 +1,21 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MREwDwYDVQQDDAhkamJl
|
3
|
+
cmc5NjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
|
4
|
+
MB4XDTE1MDkwMjIwNDkxOFoXDTE2MDkwMTIwNDkxOFowPzERMA8GA1UEAwwIZGpi
|
5
|
+
ZXJnOTYxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
|
6
|
+
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMyTkvXqRp6hLs9eoJOS
|
7
|
+
Hmi8kRYbq9Vkf15/hMxJpotYMgJVHHWrmDcC5Dye2PbnXjTkKf266Zw0PtT9h+lI
|
8
|
+
S3ts9HO+vaCFSMwFFZmnWJSpQ3CNw2RcHxjWkk9yF7imEM8Kz9ojhiDXzBetdV6M
|
9
|
+
gr0lV/alUr7TNVBDngbXEfTWscyXh1qd7xZ4EcOdsDktCe5G45N/o3662tPQvJsi
|
10
|
+
FOF0CM/KuBsa/HL1/eoEmF4B3EKIRfTHrQ3hu20Kv3RJ88QM4ec2+0dd97uX693O
|
11
|
+
zv6981fyEg+aXLkxrkViM/tz2qR2ZE0jPhHTREPYeMEgptRkTmWSKAuLVWrJEfgl
|
12
|
+
DtkCAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFEwe
|
13
|
+
nn6bfJADmuIDiMSOzedOrL+xMB0GA1UdEQQWMBSBEmRqYmVyZzk2QGdtYWlsLmNv
|
14
|
+
bTAdBgNVHRIEFjAUgRJkamJlcmc5NkBnbWFpbC5jb20wDQYJKoZIhvcNAQEFBQAD
|
15
|
+
ggEBAHmNOCWoDVD75zHFueY0viwGDVP1BNGFC+yXcb7u2GlK+nEMCORqzURbYPf7
|
16
|
+
tL+/hzmePIRz7i30UM//64GI1NLv9jl7nIwjhPpXpf7/lu2I9hOTsvwSumb5UiKC
|
17
|
+
/sqBxI3sfj9pr79Wpv4MuikX1XPik7Ncb7NPsJPw06Lvyc3Hkg5X2XpPtLtS+Gr2
|
18
|
+
wKJnmzb5rIPS1cmsqv0M9LPWflzfwoZ/SpnmhagP+g05p8bRNKjZSA2iImM/GyYZ
|
19
|
+
EJYzxdPOrx2n6NYR3Hk+vHP0U7UBSveI6+qx+ndQYaeyCn+GRX2PKS9h66YF/Q1V
|
20
|
+
tGSHgAmcLlkdGgan182qsE/4kKM=
|
21
|
+
-----END CERTIFICATE-----
|
@@ -1,23 +1,23 @@
|
|
1
|
-
########################################################################
|
2
|
-
# example_changejournal.rb
|
3
|
-
#
|
4
|
-
# A test script for general futzing. Modify as you see fit. You can
|
5
|
-
# run this test script via the 'rake example' task.
|
6
|
-
########################################################################
|
7
|
-
require 'win32/dirmonitor'
|
8
|
-
|
9
|
-
puts 'VERSION: ' + Win32::DirMonitor::VERSION
|
10
|
-
|
11
|
-
monitor = Win32::DirMonitor.new(ENV['HOME'])
|
12
|
-
|
13
|
-
# Wait up to 5 minutes for a change journals
|
14
|
-
monitor.wait(300){ |struct|
|
15
|
-
puts 'Something changed'
|
16
|
-
puts 'File: ' + struct.file
|
17
|
-
puts 'Action: ' + struct.action
|
18
|
-
struct.changes.each do |change|
|
19
|
-
puts "Change: " + change[0].to_s
|
20
|
-
puts "Old: " + change[1].to_s
|
21
|
-
puts "New: " + change[2].to_s
|
22
|
-
end
|
23
|
-
}
|
1
|
+
########################################################################
|
2
|
+
# example_changejournal.rb
|
3
|
+
#
|
4
|
+
# A test script for general futzing. Modify as you see fit. You can
|
5
|
+
# run this test script via the 'rake example' task.
|
6
|
+
########################################################################
|
7
|
+
require 'win32/dirmonitor'
|
8
|
+
|
9
|
+
puts 'VERSION: ' + Win32::DirMonitor::VERSION
|
10
|
+
|
11
|
+
monitor = Win32::DirMonitor.new(ENV['HOME'])
|
12
|
+
|
13
|
+
# Wait up to 5 minutes for a change journals
|
14
|
+
monitor.wait(300){ |struct|
|
15
|
+
puts 'Something changed'
|
16
|
+
puts 'File: ' + struct.file
|
17
|
+
puts 'Action: ' + struct.action
|
18
|
+
struct.changes.each do |change|
|
19
|
+
puts "Change: " + change[0].to_s
|
20
|
+
puts "Old: " + change[1].to_s
|
21
|
+
puts "New: " + change[2].to_s
|
22
|
+
end
|
23
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'win32/dirmonitor'
|
data/lib/win32/dirmonitor.rb
CHANGED
@@ -1,146 +1,146 @@
|
|
1
|
-
require 'socket'
|
2
|
-
require 'win32ole'
|
3
|
-
require 'timeout'
|
4
|
-
|
5
|
-
module Win32
|
6
|
-
class DirMonitor
|
7
|
-
class Error < StandardError; end
|
8
|
-
|
9
|
-
# The version of the win32-dirmonitor library
|
10
|
-
VERSION = '1.0.
|
11
|
-
|
12
|
-
# The struct yielded to the wait method
|
13
|
-
DirMonitorStruct = Struct.new(
|
14
|
-
'DirMonitorStruct',
|
15
|
-
:file,
|
16
|
-
:action,
|
17
|
-
:changes
|
18
|
-
)
|
19
|
-
|
20
|
-
# The path to be monitored.
|
21
|
-
attr_reader :path
|
22
|
-
|
23
|
-
# The host on which to monitor the path.
|
24
|
-
attr_reader :host
|
25
|
-
|
26
|
-
# Creates a new DirMonitor object which sets the path and hostname
|
27
|
-
# on which the filesystem will be monitored for changes. If no hostname
|
28
|
-
# is provided, then the current host is assumed.
|
29
|
-
#
|
30
|
-
def initialize(path, host = Socket.gethostname)
|
31
|
-
raise ArgumentError unless File.
|
32
|
-
raise TypeError unless path.is_a?(String)
|
33
|
-
raise TypeError unless host.is_a?(String)
|
34
|
-
|
35
|
-
@path = path.tr("/", "\\")
|
36
|
-
@host = host
|
37
|
-
@conn = "winmgmts:{impersonationlevel=impersonate}!//#{host}/root/cimv2"
|
38
|
-
end
|
39
|
-
|
40
|
-
# A event loop that will yield a DirMonitorStruct object whenever there
|
41
|
-
# is a change in a file on the path set in the constructor. The loop will
|
42
|
-
# timeout after the number of seconds provided, or indefinitely if no
|
43
|
-
# argument is provided.
|
44
|
-
#
|
45
|
-
# The DirMonitorStruct contains the following members:
|
46
|
-
#
|
47
|
-
# * file # The full path of the file that was changed.
|
48
|
-
# * action # Either create, delete or modify.
|
49
|
-
# * changes # If modified, includes an array of changes.
|
50
|
-
#
|
51
|
-
# If a modification occurs, the 'changes' struct member contains an
|
52
|
-
# array of arrays that describes the change. Each sub-array contains
|
53
|
-
# three members - the item that was modified, the previous value, and
|
54
|
-
# the current value.
|
55
|
-
#
|
56
|
-
# Example:
|
57
|
-
#
|
58
|
-
# mon = Win32::DirMonitor.new("C:/Users/foo")
|
59
|
-
#
|
60
|
-
# # Monitor filesystem for one minute.
|
61
|
-
# mon.wait(60){ |s| p s }
|
62
|
-
#
|
63
|
-
# # Sample struct returned after file was marked
|
64
|
-
# # hidden and read-only:
|
65
|
-
#
|
66
|
-
# #<struct Struct::DirMonitorStruct
|
67
|
-
# file="c:\\Users\\foo\\test.txt",
|
68
|
-
# action="modify",
|
69
|
-
# changes=[
|
70
|
-
# ["AccessMask", "2032127", "2032057"],
|
71
|
-
# ["Hidden", "false", "true"],
|
72
|
-
# ["Writeable", "true", "false"]
|
73
|
-
# ]
|
74
|
-
# >
|
75
|
-
#
|
76
|
-
def wait(seconds = nil)
|
77
|
-
raise TypeError unless seconds.is_a?(Numeric) if seconds
|
78
|
-
|
79
|
-
ole = WIN32OLE.connect(@conn)
|
80
|
-
drive = @path.split(':').first + ":"
|
81
|
-
folder = @path.split(':').last.gsub("\\", "\\\\\\\\")
|
82
|
-
folder << "\\\\" unless folder[-1] == "\\"
|
83
|
-
|
84
|
-
query = %Q{
|
85
|
-
select * from __instanceOperationEvent
|
86
|
-
within 2
|
87
|
-
where targetInstance isa 'CIM_DataFile'
|
88
|
-
and targetInstance.Drive='#{drive}'
|
89
|
-
and targetInstance.Path='#{folder}'
|
90
|
-
}
|
91
|
-
|
92
|
-
# Asynchronous call. This will let the user break out of it manually.
|
93
|
-
sink = WIN32OLE.new('WbemScripting.SWbemSink')
|
94
|
-
event = WIN32OLE_EVENT.new(sink)
|
95
|
-
|
96
|
-
ole.execNotificationQueryAsync(sink, query)
|
97
|
-
sleep 0.5
|
98
|
-
|
99
|
-
event.on_event("OnObjectReady"){ |object, context|
|
100
|
-
target = object.TargetInstance
|
101
|
-
struct = DirMonitorStruct.new
|
102
|
-
struct[:file] = target.Name
|
103
|
-
|
104
|
-
case object.Path_.Class.to_s
|
105
|
-
when "__InstanceCreationEvent"
|
106
|
-
struct[:action] = 'create'
|
107
|
-
when "__InstanceDeletionEvent"
|
108
|
-
struct[:action] = 'delete'
|
109
|
-
when "__InstanceModificationEvent"
|
110
|
-
previous = object.PreviousInstance
|
111
|
-
struct[:action] = 'modify'
|
112
|
-
struct[:changes] = []
|
113
|
-
|
114
|
-
target.Properties_.each{ |prop|
|
115
|
-
if prop.Value != previous.send(prop.Name)
|
116
|
-
struct[:changes] << [
|
117
|
-
prop.Name,
|
118
|
-
previous.send(prop.Name).to_s,
|
119
|
-
prop.Value.to_s
|
120
|
-
]
|
121
|
-
end
|
122
|
-
}
|
123
|
-
end
|
124
|
-
|
125
|
-
yield struct
|
126
|
-
}
|
127
|
-
|
128
|
-
# If an argument is provided, timeout after that many seconds.
|
129
|
-
if seconds
|
130
|
-
begin
|
131
|
-
Timeout.timeout(seconds){
|
132
|
-
loop do
|
133
|
-
WIN32OLE_EVENT.message_loop
|
134
|
-
end
|
135
|
-
}
|
136
|
-
rescue Timeout::Error
|
137
|
-
# Do nothing, return control to user
|
138
|
-
end
|
139
|
-
else
|
140
|
-
loop do
|
141
|
-
WIN32OLE_EVENT.message_loop
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
1
|
+
require 'socket'
|
2
|
+
require 'win32ole'
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
module Win32
|
6
|
+
class DirMonitor
|
7
|
+
class Error < StandardError; end
|
8
|
+
|
9
|
+
# The version of the win32-dirmonitor library
|
10
|
+
VERSION = '1.0.1'
|
11
|
+
|
12
|
+
# The struct yielded to the wait method
|
13
|
+
DirMonitorStruct = Struct.new(
|
14
|
+
'DirMonitorStruct',
|
15
|
+
:file,
|
16
|
+
:action,
|
17
|
+
:changes
|
18
|
+
)
|
19
|
+
|
20
|
+
# The path to be monitored.
|
21
|
+
attr_reader :path
|
22
|
+
|
23
|
+
# The host on which to monitor the path.
|
24
|
+
attr_reader :host
|
25
|
+
|
26
|
+
# Creates a new DirMonitor object which sets the path and hostname
|
27
|
+
# on which the filesystem will be monitored for changes. If no hostname
|
28
|
+
# is provided, then the current host is assumed.
|
29
|
+
#
|
30
|
+
def initialize(path, host = Socket.gethostname)
|
31
|
+
raise ArgumentError unless File.exist?(path)
|
32
|
+
raise TypeError unless path.is_a?(String)
|
33
|
+
raise TypeError unless host.is_a?(String)
|
34
|
+
|
35
|
+
@path = path.tr("/", "\\")
|
36
|
+
@host = host
|
37
|
+
@conn = "winmgmts:{impersonationlevel=impersonate}!//#{host}/root/cimv2"
|
38
|
+
end
|
39
|
+
|
40
|
+
# A event loop that will yield a DirMonitorStruct object whenever there
|
41
|
+
# is a change in a file on the path set in the constructor. The loop will
|
42
|
+
# timeout after the number of seconds provided, or indefinitely if no
|
43
|
+
# argument is provided.
|
44
|
+
#
|
45
|
+
# The DirMonitorStruct contains the following members:
|
46
|
+
#
|
47
|
+
# * file # The full path of the file that was changed.
|
48
|
+
# * action # Either create, delete or modify.
|
49
|
+
# * changes # If modified, includes an array of changes.
|
50
|
+
#
|
51
|
+
# If a modification occurs, the 'changes' struct member contains an
|
52
|
+
# array of arrays that describes the change. Each sub-array contains
|
53
|
+
# three members - the item that was modified, the previous value, and
|
54
|
+
# the current value.
|
55
|
+
#
|
56
|
+
# Example:
|
57
|
+
#
|
58
|
+
# mon = Win32::DirMonitor.new("C:/Users/foo")
|
59
|
+
#
|
60
|
+
# # Monitor filesystem for one minute.
|
61
|
+
# mon.wait(60){ |s| p s }
|
62
|
+
#
|
63
|
+
# # Sample struct returned after file was marked
|
64
|
+
# # hidden and read-only:
|
65
|
+
#
|
66
|
+
# #<struct Struct::DirMonitorStruct
|
67
|
+
# file="c:\\Users\\foo\\test.txt",
|
68
|
+
# action="modify",
|
69
|
+
# changes=[
|
70
|
+
# ["AccessMask", "2032127", "2032057"],
|
71
|
+
# ["Hidden", "false", "true"],
|
72
|
+
# ["Writeable", "true", "false"]
|
73
|
+
# ]
|
74
|
+
# >
|
75
|
+
#
|
76
|
+
def wait(seconds = nil)
|
77
|
+
raise TypeError unless seconds.is_a?(Numeric) if seconds
|
78
|
+
|
79
|
+
ole = WIN32OLE.connect(@conn)
|
80
|
+
drive = @path.split(':').first + ":"
|
81
|
+
folder = @path.split(':').last.gsub("\\", "\\\\\\\\")
|
82
|
+
folder << "\\\\" unless folder[-1] == "\\"
|
83
|
+
|
84
|
+
query = %Q{
|
85
|
+
select * from __instanceOperationEvent
|
86
|
+
within 2
|
87
|
+
where targetInstance isa 'CIM_DataFile'
|
88
|
+
and targetInstance.Drive='#{drive}'
|
89
|
+
and targetInstance.Path='#{folder}'
|
90
|
+
}
|
91
|
+
|
92
|
+
# Asynchronous call. This will let the user break out of it manually.
|
93
|
+
sink = WIN32OLE.new('WbemScripting.SWbemSink')
|
94
|
+
event = WIN32OLE_EVENT.new(sink)
|
95
|
+
|
96
|
+
ole.execNotificationQueryAsync(sink, query)
|
97
|
+
sleep 0.5
|
98
|
+
|
99
|
+
event.on_event("OnObjectReady"){ |object, context|
|
100
|
+
target = object.TargetInstance
|
101
|
+
struct = DirMonitorStruct.new
|
102
|
+
struct[:file] = target.Name
|
103
|
+
|
104
|
+
case object.Path_.Class.to_s
|
105
|
+
when "__InstanceCreationEvent"
|
106
|
+
struct[:action] = 'create'
|
107
|
+
when "__InstanceDeletionEvent"
|
108
|
+
struct[:action] = 'delete'
|
109
|
+
when "__InstanceModificationEvent"
|
110
|
+
previous = object.PreviousInstance
|
111
|
+
struct[:action] = 'modify'
|
112
|
+
struct[:changes] = []
|
113
|
+
|
114
|
+
target.Properties_.each{ |prop|
|
115
|
+
if prop.Value != previous.send(prop.Name)
|
116
|
+
struct[:changes] << [
|
117
|
+
prop.Name,
|
118
|
+
previous.send(prop.Name).to_s,
|
119
|
+
prop.Value.to_s
|
120
|
+
]
|
121
|
+
end
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
yield struct
|
126
|
+
}
|
127
|
+
|
128
|
+
# If an argument is provided, timeout after that many seconds.
|
129
|
+
if seconds
|
130
|
+
begin
|
131
|
+
Timeout.timeout(seconds){
|
132
|
+
loop do
|
133
|
+
WIN32OLE_EVENT.message_loop
|
134
|
+
end
|
135
|
+
}
|
136
|
+
rescue Timeout::Error
|
137
|
+
# Do nothing, return control to user
|
138
|
+
end
|
139
|
+
else
|
140
|
+
loop do
|
141
|
+
WIN32OLE_EVENT.message_loop
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -1,103 +1,103 @@
|
|
1
|
-
#############################################################################
|
2
|
-
# test_win32_dirmonitor.rb
|
3
|
-
#
|
4
|
-
# Test suite for the win32-dirmonitor library. You should run this
|
5
|
-
# via the 'rake test' task.
|
6
|
-
#############################################################################
|
7
|
-
require 'test-unit'
|
8
|
-
require 'win32/dirmonitor'
|
9
|
-
include Win32
|
10
|
-
|
11
|
-
class TC_Win32_DirMonitor < Test::Unit::TestCase
|
12
|
-
def self.startup
|
13
|
-
Dir.chdir(File.expand_path(File.dirname(__FILE__)))
|
14
|
-
@@file = 'win32_dirmonitor_test.txt'
|
15
|
-
end
|
16
|
-
|
17
|
-
def setup
|
18
|
-
# The thread is used to force an event to happen for the tests
|
19
|
-
@monitor = DirMonitor.new(Dir.pwd)
|
20
|
-
@thread = Thread.new{
|
21
|
-
sleep 2
|
22
|
-
File.open(@@file, 'w'){ |fh| fh.puts 'Delete me!' }
|
23
|
-
}
|
24
|
-
end
|
25
|
-
|
26
|
-
test "version constant is set to expected value" do
|
27
|
-
assert_equal('1.0.
|
28
|
-
end
|
29
|
-
|
30
|
-
test "constructor requires a path argument" do
|
31
|
-
assert_raise(ArgumentError){ DirMonitor.new }
|
32
|
-
end
|
33
|
-
|
34
|
-
test "path and host arguments must be strings" do
|
35
|
-
assert_raise(TypeError){ DirMonitor.new(1) }
|
36
|
-
assert_raise(TypeError){ DirMonitor.new(Dir.pwd, 1) }
|
37
|
-
end
|
38
|
-
|
39
|
-
test "path argument must exist" do
|
40
|
-
assert_raise(ArgumentError){ DirMonitor.new("C:/Bogus/Bogus") }
|
41
|
-
end
|
42
|
-
|
43
|
-
test "wait method yields a frozen DirMonitorStruct" do
|
44
|
-
@thread.join
|
45
|
-
@monitor.wait(2){ |s|
|
46
|
-
assert_kind_of(Struct::DirMonitorStruct, s)
|
47
|
-
assert_equal(['action', 'file', 'changes'], s.members)
|
48
|
-
assert_kind_of(Array, s.changes)
|
49
|
-
assert_kind_of(Array, s.changes.first)
|
50
|
-
assert_true(s.frozen?)
|
51
|
-
}
|
52
|
-
end
|
53
|
-
|
54
|
-
test "wait method basic functionality" do
|
55
|
-
assert_respond_to(@monitor, :wait)
|
56
|
-
end
|
57
|
-
|
58
|
-
# We provide some very short timeouts here - shouldn't slow the tests down
|
59
|
-
test "wait method accepts an optional timeout value" do
|
60
|
-
assert_nothing_raised{ @monitor.wait(0.01){ |s| } }
|
61
|
-
end
|
62
|
-
|
63
|
-
test "wait method accepts a single integer argument only" do
|
64
|
-
assert_raise(ArgumentError){ @monitor.wait(1,1) }
|
65
|
-
assert_raise(TypeError){ @monitor.wait('a') }
|
66
|
-
end
|
67
|
-
|
68
|
-
test "a custom error class is defined" do
|
69
|
-
assert_kind_of(Object, Win32::DirMonitor::Error)
|
70
|
-
end
|
71
|
-
|
72
|
-
test "path attribute basic functionality" do
|
73
|
-
assert_respond_to(@monitor, :path)
|
74
|
-
assert_nothing_raised{ @monitor.path }
|
75
|
-
assert_kind_of(String, @monitor.path)
|
76
|
-
end
|
77
|
-
|
78
|
-
test "path method returns expected value" do
|
79
|
-
assert_equal(Dir.pwd, @monitor.path.tr("\\", "/"))
|
80
|
-
end
|
81
|
-
|
82
|
-
test "host attribute basic functionality" do
|
83
|
-
assert_respond_to(@monitor, :host)
|
84
|
-
assert_nothing_raised{ @monitor.host}
|
85
|
-
assert_kind_of(String, @monitor.host)
|
86
|
-
end
|
87
|
-
|
88
|
-
test "host method returns expected value" do
|
89
|
-
assert_equal(Socket.gethostname, @monitor.host)
|
90
|
-
end
|
91
|
-
|
92
|
-
def teardown
|
93
|
-
@thread.kill if @thread.alive?
|
94
|
-
|
95
|
-
@monitor = nil
|
96
|
-
@flags = nil
|
97
|
-
@thread = nil
|
98
|
-
end
|
99
|
-
|
100
|
-
def self.shutdown
|
101
|
-
File.delete(@@file) if File.
|
102
|
-
end
|
103
|
-
end
|
1
|
+
#############################################################################
|
2
|
+
# test_win32_dirmonitor.rb
|
3
|
+
#
|
4
|
+
# Test suite for the win32-dirmonitor library. You should run this
|
5
|
+
# via the 'rake test' task.
|
6
|
+
#############################################################################
|
7
|
+
require 'test-unit'
|
8
|
+
require 'win32/dirmonitor'
|
9
|
+
include Win32
|
10
|
+
|
11
|
+
class TC_Win32_DirMonitor < Test::Unit::TestCase
|
12
|
+
def self.startup
|
13
|
+
Dir.chdir(File.expand_path(File.dirname(__FILE__)))
|
14
|
+
@@file = 'win32_dirmonitor_test.txt'
|
15
|
+
end
|
16
|
+
|
17
|
+
def setup
|
18
|
+
# The thread is used to force an event to happen for the tests
|
19
|
+
@monitor = DirMonitor.new(Dir.pwd)
|
20
|
+
@thread = Thread.new{
|
21
|
+
sleep 2
|
22
|
+
File.open(@@file, 'w'){ |fh| fh.puts 'Delete me!' }
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
test "version constant is set to expected value" do
|
27
|
+
assert_equal('1.0.1', DirMonitor::VERSION)
|
28
|
+
end
|
29
|
+
|
30
|
+
test "constructor requires a path argument" do
|
31
|
+
assert_raise(ArgumentError){ DirMonitor.new }
|
32
|
+
end
|
33
|
+
|
34
|
+
test "path and host arguments must be strings" do
|
35
|
+
assert_raise(TypeError){ DirMonitor.new(1) }
|
36
|
+
assert_raise(TypeError){ DirMonitor.new(Dir.pwd, 1) }
|
37
|
+
end
|
38
|
+
|
39
|
+
test "path argument must exist" do
|
40
|
+
assert_raise(ArgumentError){ DirMonitor.new("C:/Bogus/Bogus") }
|
41
|
+
end
|
42
|
+
|
43
|
+
test "wait method yields a frozen DirMonitorStruct" do
|
44
|
+
@thread.join
|
45
|
+
@monitor.wait(2){ |s|
|
46
|
+
assert_kind_of(Struct::DirMonitorStruct, s)
|
47
|
+
assert_equal(['action', 'file', 'changes'], s.members)
|
48
|
+
assert_kind_of(Array, s.changes)
|
49
|
+
assert_kind_of(Array, s.changes.first)
|
50
|
+
assert_true(s.frozen?)
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
test "wait method basic functionality" do
|
55
|
+
assert_respond_to(@monitor, :wait)
|
56
|
+
end
|
57
|
+
|
58
|
+
# We provide some very short timeouts here - shouldn't slow the tests down
|
59
|
+
test "wait method accepts an optional timeout value" do
|
60
|
+
assert_nothing_raised{ @monitor.wait(0.01){ |s| } }
|
61
|
+
end
|
62
|
+
|
63
|
+
test "wait method accepts a single integer argument only" do
|
64
|
+
assert_raise(ArgumentError){ @monitor.wait(1,1) }
|
65
|
+
assert_raise(TypeError){ @monitor.wait('a') }
|
66
|
+
end
|
67
|
+
|
68
|
+
test "a custom error class is defined" do
|
69
|
+
assert_kind_of(Object, Win32::DirMonitor::Error)
|
70
|
+
end
|
71
|
+
|
72
|
+
test "path attribute basic functionality" do
|
73
|
+
assert_respond_to(@monitor, :path)
|
74
|
+
assert_nothing_raised{ @monitor.path }
|
75
|
+
assert_kind_of(String, @monitor.path)
|
76
|
+
end
|
77
|
+
|
78
|
+
test "path method returns expected value" do
|
79
|
+
assert_equal(Dir.pwd, @monitor.path.tr("\\", "/"))
|
80
|
+
end
|
81
|
+
|
82
|
+
test "host attribute basic functionality" do
|
83
|
+
assert_respond_to(@monitor, :host)
|
84
|
+
assert_nothing_raised{ @monitor.host}
|
85
|
+
assert_kind_of(String, @monitor.host)
|
86
|
+
end
|
87
|
+
|
88
|
+
test "host method returns expected value" do
|
89
|
+
assert_equal(Socket.gethostname, @monitor.host)
|
90
|
+
end
|
91
|
+
|
92
|
+
def teardown
|
93
|
+
@thread.kill if @thread.alive?
|
94
|
+
|
95
|
+
@monitor = nil
|
96
|
+
@flags = nil
|
97
|
+
@thread = nil
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.shutdown
|
101
|
+
File.delete(@@file) if File.exist?(@@file)
|
102
|
+
end
|
103
|
+
end
|
data/win32-dirmonitor.gemspec
CHANGED
@@ -1,30 +1,29 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
|
3
|
-
Gem::Specification.new do |spec|
|
4
|
-
spec.name = 'win32-dirmonitor'
|
5
|
-
spec.version = '1.0.
|
6
|
-
spec.authors = ['Daniel J. Berger', 'Park Heesob']
|
7
|
-
spec.license = 'Artistic 2.0'
|
8
|
-
spec.email = 'djberg96@gmail.com'
|
9
|
-
spec.homepage = 'https://github.com/djberg96/win32-dirmonitor'
|
10
|
-
spec.summary = 'A library for monitoring files on MS Windows'
|
11
|
-
spec.test_file = 'test/test_win32_dirmonitor.rb'
|
12
|
-
spec.files = Dir['**/*'].reject{ |f| f.include?('git') }
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
'
|
18
|
-
'
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
spec.add_development_dependency('
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = 'win32-dirmonitor'
|
5
|
+
spec.version = '1.0.1'
|
6
|
+
spec.authors = ['Daniel J. Berger', 'Park Heesob']
|
7
|
+
spec.license = 'Artistic 2.0'
|
8
|
+
spec.email = 'djberg96@gmail.com'
|
9
|
+
spec.homepage = 'https://github.com/djberg96/win32-dirmonitor'
|
10
|
+
spec.summary = 'A library for monitoring files on MS Windows'
|
11
|
+
spec.test_file = 'test/test_win32_dirmonitor.rb'
|
12
|
+
spec.files = Dir['**/*'].reject{ |f| f.include?('git') }
|
13
|
+
spec.cert_chain = ['certs/djberg96_pub.pem']
|
14
|
+
|
15
|
+
spec.extra_rdoc_files = [
|
16
|
+
'README',
|
17
|
+
'CHANGES',
|
18
|
+
'MANIFEST',
|
19
|
+
]
|
20
|
+
|
21
|
+
spec.add_development_dependency('test-unit')
|
22
|
+
spec.add_development_dependency('rake')
|
23
|
+
|
24
|
+
spec.description = <<-EOF
|
25
|
+
The win32-dirmonitor library provides a way to asynchronously monitor
|
26
|
+
changes to files in a given directory, and provides detailed information
|
27
|
+
about the changes that occurred.
|
28
|
+
EOF
|
29
|
+
end
|
metadata
CHANGED
@@ -1,42 +1,64 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: win32-dirmonitor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel J. Berger
|
8
8
|
- Park Heesob
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
|
-
cert_chain:
|
12
|
-
|
11
|
+
cert_chain:
|
12
|
+
- |
|
13
|
+
-----BEGIN CERTIFICATE-----
|
14
|
+
MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MREwDwYDVQQDDAhkamJl
|
15
|
+
cmc5NjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
|
16
|
+
MB4XDTE1MDkwMjIwNDkxOFoXDTE2MDkwMTIwNDkxOFowPzERMA8GA1UEAwwIZGpi
|
17
|
+
ZXJnOTYxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
|
18
|
+
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMyTkvXqRp6hLs9eoJOS
|
19
|
+
Hmi8kRYbq9Vkf15/hMxJpotYMgJVHHWrmDcC5Dye2PbnXjTkKf266Zw0PtT9h+lI
|
20
|
+
S3ts9HO+vaCFSMwFFZmnWJSpQ3CNw2RcHxjWkk9yF7imEM8Kz9ojhiDXzBetdV6M
|
21
|
+
gr0lV/alUr7TNVBDngbXEfTWscyXh1qd7xZ4EcOdsDktCe5G45N/o3662tPQvJsi
|
22
|
+
FOF0CM/KuBsa/HL1/eoEmF4B3EKIRfTHrQ3hu20Kv3RJ88QM4ec2+0dd97uX693O
|
23
|
+
zv6981fyEg+aXLkxrkViM/tz2qR2ZE0jPhHTREPYeMEgptRkTmWSKAuLVWrJEfgl
|
24
|
+
DtkCAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFEwe
|
25
|
+
nn6bfJADmuIDiMSOzedOrL+xMB0GA1UdEQQWMBSBEmRqYmVyZzk2QGdtYWlsLmNv
|
26
|
+
bTAdBgNVHRIEFjAUgRJkamJlcmc5NkBnbWFpbC5jb20wDQYJKoZIhvcNAQEFBQAD
|
27
|
+
ggEBAHmNOCWoDVD75zHFueY0viwGDVP1BNGFC+yXcb7u2GlK+nEMCORqzURbYPf7
|
28
|
+
tL+/hzmePIRz7i30UM//64GI1NLv9jl7nIwjhPpXpf7/lu2I9hOTsvwSumb5UiKC
|
29
|
+
/sqBxI3sfj9pr79Wpv4MuikX1XPik7Ncb7NPsJPw06Lvyc3Hkg5X2XpPtLtS+Gr2
|
30
|
+
wKJnmzb5rIPS1cmsqv0M9LPWflzfwoZ/SpnmhagP+g05p8bRNKjZSA2iImM/GyYZ
|
31
|
+
EJYzxdPOrx2n6NYR3Hk+vHP0U7UBSveI6+qx+ndQYaeyCn+GRX2PKS9h66YF/Q1V
|
32
|
+
tGSHgAmcLlkdGgan182qsE/4kKM=
|
33
|
+
-----END CERTIFICATE-----
|
34
|
+
date: 2015-10-20 00:00:00.000000000 Z
|
13
35
|
dependencies:
|
14
36
|
- !ruby/object:Gem::Dependency
|
15
37
|
name: test-unit
|
16
38
|
requirement: !ruby/object:Gem::Requirement
|
17
39
|
requirements:
|
18
|
-
- -
|
40
|
+
- - ">="
|
19
41
|
- !ruby/object:Gem::Version
|
20
42
|
version: '0'
|
21
43
|
type: :development
|
22
44
|
prerelease: false
|
23
45
|
version_requirements: !ruby/object:Gem::Requirement
|
24
46
|
requirements:
|
25
|
-
- -
|
47
|
+
- - ">="
|
26
48
|
- !ruby/object:Gem::Version
|
27
49
|
version: '0'
|
28
50
|
- !ruby/object:Gem::Dependency
|
29
51
|
name: rake
|
30
52
|
requirement: !ruby/object:Gem::Requirement
|
31
53
|
requirements:
|
32
|
-
- -
|
54
|
+
- - ">="
|
33
55
|
- !ruby/object:Gem::Version
|
34
56
|
version: '0'
|
35
57
|
type: :development
|
36
58
|
prerelease: false
|
37
59
|
version_requirements: !ruby/object:Gem::Requirement
|
38
60
|
requirements:
|
39
|
-
- -
|
61
|
+
- - ">="
|
40
62
|
- !ruby/object:Gem::Version
|
41
63
|
version: '0'
|
42
64
|
description: |2
|
@@ -52,11 +74,13 @@ extra_rdoc_files:
|
|
52
74
|
- MANIFEST
|
53
75
|
files:
|
54
76
|
- CHANGES
|
55
|
-
- examples/example_dirmonitor.rb
|
56
|
-
- lib/win32/dirmonitor.rb
|
57
77
|
- MANIFEST
|
58
|
-
- Rakefile
|
59
78
|
- README
|
79
|
+
- Rakefile
|
80
|
+
- certs/djberg96_pub.pem
|
81
|
+
- examples/example_dirmonitor.rb
|
82
|
+
- lib/win32-dirmonitor.rb
|
83
|
+
- lib/win32/dirmonitor.rb
|
60
84
|
- test/test_win32_dirmonitor.rb
|
61
85
|
- win32-dirmonitor.gemspec
|
62
86
|
homepage: https://github.com/djberg96/win32-dirmonitor
|
@@ -69,17 +93,17 @@ require_paths:
|
|
69
93
|
- lib
|
70
94
|
required_ruby_version: !ruby/object:Gem::Requirement
|
71
95
|
requirements:
|
72
|
-
- -
|
96
|
+
- - ">="
|
73
97
|
- !ruby/object:Gem::Version
|
74
98
|
version: '0'
|
75
99
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
100
|
requirements:
|
77
|
-
- -
|
101
|
+
- - ">="
|
78
102
|
- !ruby/object:Gem::Version
|
79
103
|
version: '0'
|
80
104
|
requirements: []
|
81
|
-
rubyforge_project:
|
82
|
-
rubygems_version: 2.
|
105
|
+
rubyforge_project:
|
106
|
+
rubygems_version: 2.4.8
|
83
107
|
signing_key:
|
84
108
|
specification_version: 4
|
85
109
|
summary: A library for monitoring files on MS Windows
|
metadata.gz.sig
ADDED
Binary file
|