win32-dirmonitor 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|