win32-eventlog 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +139 -0
- data/MANIFEST +22 -0
- data/README +63 -0
- data/doc/tutorial.txt +140 -0
- data/lib/win32/eventlog.rb +754 -0
- data/lib/win32/mc.rb +104 -0
- data/lib/win32/test.rb +8 -0
- data/test/foo.mc +24 -0
- data/test/tc_eventlog.rb +228 -0
- data/test/tc_mc.rb +49 -0
- data/test/ts_all.rb +7 -0
- metadata +68 -0
data/lib/win32/mc.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
module Win32
|
2
|
+
class MCError < StandardError; end
|
3
|
+
class MC
|
4
|
+
VERSION = '0.1.2'
|
5
|
+
|
6
|
+
attr_accessor :mc_file, :res_file, :dll_file
|
7
|
+
|
8
|
+
# Accepts three file names as arguments and returns an MC object. The
|
9
|
+
# +mc_file+ is the name of the .mc file to be used to ultimately
|
10
|
+
# generate the .dll file.
|
11
|
+
#
|
12
|
+
# If +res_file+ or +dll_file+ are not specified, then the basename
|
13
|
+
# of +mc_file+ is used to generate their names, with .res and .dll
|
14
|
+
# extensions, respectively.
|
15
|
+
#
|
16
|
+
def initialize(mc_file, res_file=nil, dll_file=nil)
|
17
|
+
@mc_file = mc_file
|
18
|
+
|
19
|
+
if res_file
|
20
|
+
@res_file = res_file
|
21
|
+
else
|
22
|
+
@res_file = File.basename(mc_file, '.mc') + '.res'
|
23
|
+
end
|
24
|
+
|
25
|
+
if dll_file
|
26
|
+
@dll_file = dll_file
|
27
|
+
else
|
28
|
+
@dll_file = File.basename(mc_file, '.mc') + '.dll'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Uses the message compiler (mc) program to generate the .h and .rc
|
33
|
+
# files based on the .mc (message category) file. This method must
|
34
|
+
# be called before MC#create_res_file or MC#create_dll_file.
|
35
|
+
#
|
36
|
+
def create_header
|
37
|
+
system("mc #{@mc_file}")
|
38
|
+
end
|
39
|
+
|
40
|
+
# Creates the .res (resource) file from the .rc file generated by the
|
41
|
+
# MC#create_header method. Raises an MCError if the .rc file is not
|
42
|
+
# found.
|
43
|
+
#
|
44
|
+
def create_res_file
|
45
|
+
rc_file = File.basename(@mc_file, '.mc') + '.rc'
|
46
|
+
unless File.exists?(rc_file)
|
47
|
+
raise MCError, "No .rc file found: #{@rc_file}"
|
48
|
+
end
|
49
|
+
system("rc -r -fo #{@res_file} #{rc_file}")
|
50
|
+
end
|
51
|
+
|
52
|
+
# Creates the .dll file from the .res file generated by the
|
53
|
+
# MC#create_res_file method. Raises an MCError if the .res file is not
|
54
|
+
# found.
|
55
|
+
#
|
56
|
+
def create_dll_file
|
57
|
+
unless File.exists?(@res_file)
|
58
|
+
raise MCError, "No .res file found: #{@res_file}"
|
59
|
+
end
|
60
|
+
system("link -dll -noentry -out:#{@dll_file} #{@res_file}")
|
61
|
+
end
|
62
|
+
|
63
|
+
# A shortcut for MC#create_header + MC#create_res_file +
|
64
|
+
# MC#create_dll_file.
|
65
|
+
#
|
66
|
+
def create_all
|
67
|
+
create_header
|
68
|
+
create_res_file
|
69
|
+
create_dll_file
|
70
|
+
end
|
71
|
+
|
72
|
+
# Delete .h, .rc and .res files created from the corresponding
|
73
|
+
# .mc file (but *not* the .dll file). This also deletes all MSG*.bin
|
74
|
+
# files in the current directory.
|
75
|
+
#
|
76
|
+
def clean
|
77
|
+
base = File.basename(@mc_file, '.mc')
|
78
|
+
%w/.h .rc .res/.each do |ext|
|
79
|
+
file = base + ext
|
80
|
+
File.delete(file) if File.exists?(file)
|
81
|
+
end
|
82
|
+
Dir["MSG*.bin"].each do |binfile|
|
83
|
+
File.delete(binfile)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
if $0 == __FILE__
|
90
|
+
include Win32
|
91
|
+
|
92
|
+
mc_file = ARGV[0]
|
93
|
+
|
94
|
+
unless mc_file
|
95
|
+
msg = "Usage: ruby mc.rb 'filename.mc'"
|
96
|
+
raise MCError, msg
|
97
|
+
end
|
98
|
+
|
99
|
+
m = MC.new(mc_file)
|
100
|
+
m.create_header
|
101
|
+
m.create_res_file
|
102
|
+
m.create_dll_file
|
103
|
+
puts "MC finished"
|
104
|
+
end
|
data/lib/win32/test.rb
ADDED
data/test/foo.mc
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
MessageId=0x1
|
2
|
+
SymbolicName=CATEGORY_HELLO
|
3
|
+
Language=English
|
4
|
+
Foohello
|
5
|
+
.
|
6
|
+
|
7
|
+
MessageId=0x2
|
8
|
+
SymbolicName=CATEGORY_WORLD
|
9
|
+
Language=English
|
10
|
+
Fooworld
|
11
|
+
.
|
12
|
+
|
13
|
+
MessageId=0x3
|
14
|
+
SymbolicName=FOO_ERROR
|
15
|
+
Language=English
|
16
|
+
Foo error: %1
|
17
|
+
.
|
18
|
+
|
19
|
+
MessageId=0x4
|
20
|
+
SymbolicName=FOO_WARN
|
21
|
+
Language=English
|
22
|
+
Foo warning: %1
|
23
|
+
.
|
24
|
+
|
data/test/tc_eventlog.rb
ADDED
@@ -0,0 +1,228 @@
|
|
1
|
+
###################################################
|
2
|
+
# tc_eventlog.rb
|
3
|
+
#
|
4
|
+
# Test case for the win32-eventlog package.
|
5
|
+
###################################################
|
6
|
+
Dir.chdir('..') if File.basename(Dir.pwd) == 'test'
|
7
|
+
$LOAD_PATH.unshift Dir.pwd
|
8
|
+
$LOAD_PATH.unshift Dir.pwd + '/lib'
|
9
|
+
Dir.chdir('test') rescue nil
|
10
|
+
|
11
|
+
require 'test/unit'
|
12
|
+
require 'win32/eventlog'
|
13
|
+
require 'socket'
|
14
|
+
include Win32
|
15
|
+
|
16
|
+
print "\nRelax - this will take a few moments\n\n"
|
17
|
+
|
18
|
+
class TC_EventLog < Test::Unit::TestCase
|
19
|
+
def setup
|
20
|
+
@log = EventLog.new('Application')
|
21
|
+
@logfile = 'temp.evt'
|
22
|
+
@bakfile = 'C:\event_log.bak'
|
23
|
+
@hostname = Socket.gethostname
|
24
|
+
@records = []
|
25
|
+
@last = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_version
|
29
|
+
assert_equal('0.4.2', EventLog::VERSION)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Use the alias to validate it as well.
|
33
|
+
def test_constructor
|
34
|
+
assert_respond_to(EventLog, :open)
|
35
|
+
assert_nothing_raised{ EventLog.open }
|
36
|
+
assert_nothing_raised{ EventLog.open{ |log| } }
|
37
|
+
assert_nothing_raised{ EventLog.open('System') }
|
38
|
+
assert_nothing_raised{ EventLog.open('System', @hostname) }
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_constructor_expected_errors
|
42
|
+
assert_raises(EventLogError){ EventLog.new('System', @hostname, 'foo') }
|
43
|
+
assert_raises(TypeError){ EventLog.open(1) }
|
44
|
+
assert_raises(TypeError){ EventLog.open('System', 1) }
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_constructor_instance_variables
|
48
|
+
assert_nothing_raised{ @log = EventLog.new('Application', @hostname) }
|
49
|
+
assert_equal(@hostname, @log.server)
|
50
|
+
assert_equal('Application', @log.source)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_open_backup
|
54
|
+
assert_respond_to(EventLog, :open_backup)
|
55
|
+
assert_nothing_raised{ EventLog.new('Application').backup(@bakfile) }
|
56
|
+
assert_nothing_raised{ @log = EventLog.open_backup(@bakfile) }
|
57
|
+
assert_kind_of(EventLog, @log)
|
58
|
+
assert_nothing_raised{ @log.read{ break } }
|
59
|
+
assert_nothing_raised{ @log.close }
|
60
|
+
end
|
61
|
+
|
62
|
+
# Ensure that an Array is returned in non-block form and that none of the
|
63
|
+
# descriptions are nil.
|
64
|
+
#
|
65
|
+
# The test for descriptions was added as a result of ruby-talk:116528.
|
66
|
+
# Thanks go to Joey Gibson for the spot. The test for unique record
|
67
|
+
# numbers was added to ensure no dups.
|
68
|
+
#
|
69
|
+
def test_class_read_verification
|
70
|
+
assert_nothing_raised{ @array = EventLog.read }
|
71
|
+
assert_kind_of(Array, @array)
|
72
|
+
|
73
|
+
record_numbers = []
|
74
|
+
@array.each{ |log|
|
75
|
+
assert_not_nil(log.description)
|
76
|
+
assert_equal(false, record_numbers.include?(log.record_number))
|
77
|
+
record_numbers << log.record_number
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
# I've added explicit breaks because an event log could be rather large.
|
82
|
+
#
|
83
|
+
def test_class_read_basic
|
84
|
+
assert_nothing_raised{ EventLog.read{ break } }
|
85
|
+
assert_nothing_raised{ EventLog.read("Application"){ break } }
|
86
|
+
assert_nothing_raised{ EventLog.read("Application", nil){ break } }
|
87
|
+
assert_nothing_raised{ EventLog.read("Application", nil, nil){ break } }
|
88
|
+
assert_nothing_raised{ EventLog.read("Application", nil, nil, 10){ break } }
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_class_read_expected_errors
|
92
|
+
assert_raises(ArgumentError){
|
93
|
+
EventLog.read("Application", nil, nil, nil, nil){}
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_read
|
98
|
+
flags = EventLog::FORWARDS_READ | EventLog::SEQUENTIAL_READ
|
99
|
+
assert_respond_to(@log, :read)
|
100
|
+
assert_nothing_raised{ @log.read{ break } }
|
101
|
+
assert_nothing_raised{ @log.read(flags){ break } }
|
102
|
+
assert_nothing_raised{ @log.read(flags, 500){ break } }
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_read_expected_errors
|
106
|
+
flags = EventLog::FORWARDS_READ | EventLog::SEQUENTIAL_READ
|
107
|
+
assert_raises(ArgumentError){ @log.read(flags, 500, 'foo') }
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_seek_read
|
111
|
+
flags = EventLog::SEEK_READ | EventLog::FORWARDS_READ
|
112
|
+
assert_nothing_raised{ @last = @log.total_records }
|
113
|
+
assert_nothing_raised{
|
114
|
+
@records = EventLog.read(nil, nil, flags, @last - 10)
|
115
|
+
}
|
116
|
+
assert_equal(11, @records.length)
|
117
|
+
assert_equal(@last, @records.last.record_number)
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_seek_read_backwards
|
121
|
+
flags = EventLog::SEEK_READ | EventLog::BACKWARDS_READ
|
122
|
+
assert_nothing_raised{ @records = EventLog.read(nil, nil, flags, 10) }
|
123
|
+
assert_equal(10, @records.length)
|
124
|
+
assert_equal(10, @records.first.record_number)
|
125
|
+
assert_equal(1, @records.last.record_number)
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_server
|
129
|
+
assert_respond_to(@log, :server)
|
130
|
+
assert_raises(NoMethodError){ @log.server = 'foo' }
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_source
|
134
|
+
assert_respond_to(@log, :source)
|
135
|
+
assert_kind_of(String, @log.source)
|
136
|
+
assert_raises(NoMethodError){ @log.source = 'foo' }
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_file
|
140
|
+
assert_respond_to(@log, :file)
|
141
|
+
assert_nil(@log.file)
|
142
|
+
assert_raises(NoMethodError){ @log.file = 'foo' }
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_backup
|
146
|
+
assert_respond_to(@log, :backup)
|
147
|
+
assert_nothing_raised{ @log.backup(@bakfile) }
|
148
|
+
assert(File.exists?(@bakfile))
|
149
|
+
assert_raises(EventLogError){ @log.backup(@bakfile) }
|
150
|
+
end
|
151
|
+
|
152
|
+
# Since I don't want to actually clear anyone's event log, I can't really
|
153
|
+
# verify that it works.
|
154
|
+
#
|
155
|
+
def test_clear
|
156
|
+
assert_respond_to(@log, :clear)
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_full
|
160
|
+
assert_respond_to(@log, :full?)
|
161
|
+
assert_nothing_raised{ @log.full? }
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_close
|
165
|
+
assert_respond_to(@log, :close)
|
166
|
+
assert_nothing_raised{ @log.close }
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_oldest_record_number
|
170
|
+
assert_respond_to(@log, :oldest_record_number)
|
171
|
+
assert_kind_of(Fixnum, @log.oldest_record_number)
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_total_records
|
175
|
+
assert_respond_to(@log, :total_records)
|
176
|
+
assert_kind_of(Fixnum, @log.total_records)
|
177
|
+
end
|
178
|
+
|
179
|
+
# We can't test that this method actually executes properly since it goes
|
180
|
+
# into an endless loop.
|
181
|
+
#
|
182
|
+
def test_tail
|
183
|
+
assert_respond_to(@log, :tail)
|
184
|
+
assert_raises(EventLogError){ @log.tail } # requires block
|
185
|
+
end
|
186
|
+
|
187
|
+
# We can't test that this method actually executes properly since it goes
|
188
|
+
# into an endless loop.
|
189
|
+
#
|
190
|
+
def test_notify_change
|
191
|
+
assert_respond_to(@log, :notify_change)
|
192
|
+
assert_raises(EventLogError){ @log.notify_change } # requires block
|
193
|
+
end
|
194
|
+
|
195
|
+
# I can't really do more in depth testing for this method since there
|
196
|
+
# isn't an event source I can reliably and safely write to.
|
197
|
+
#
|
198
|
+
def test_report_event
|
199
|
+
assert_respond_to(@log, :report_event)
|
200
|
+
assert_respond_to(@log, :write) # alias
|
201
|
+
assert_raises(ArgumentError){ @log.report_event }
|
202
|
+
end
|
203
|
+
|
204
|
+
def test_read_event_constants
|
205
|
+
assert_not_nil(EventLog::FORWARDS_READ)
|
206
|
+
assert_not_nil(EventLog::BACKWARDS_READ)
|
207
|
+
assert_not_nil(EventLog::SEEK_READ)
|
208
|
+
assert_not_nil(EventLog::SEQUENTIAL_READ)
|
209
|
+
end
|
210
|
+
|
211
|
+
def test_event_type_constants
|
212
|
+
assert_not_nil(EventLog::SUCCESS)
|
213
|
+
assert_not_nil(EventLog::ERROR)
|
214
|
+
assert_not_nil(EventLog::WARN)
|
215
|
+
assert_not_nil(EventLog::INFO)
|
216
|
+
assert_not_nil(EventLog::AUDIT_SUCCESS)
|
217
|
+
assert_not_nil(EventLog::AUDIT_FAILURE)
|
218
|
+
end
|
219
|
+
|
220
|
+
def teardown
|
221
|
+
@log.close rescue nil
|
222
|
+
File.delete(@bakfile) rescue nil
|
223
|
+
@logfile = nil
|
224
|
+
@hostname = nil
|
225
|
+
@records = nil
|
226
|
+
@last = nil
|
227
|
+
end
|
228
|
+
end
|
data/test/tc_mc.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
############################################################################
|
2
|
+
# tc_mc.rb
|
3
|
+
#
|
4
|
+
# Test suite for the win32-mc package. The tests need to run in a specific
|
5
|
+
# order, hence the numerics added to the method names.
|
6
|
+
############################################################################
|
7
|
+
Dir.chdir('..') if File.basename(Dir.pwd) == 'test'
|
8
|
+
$LOAD_PATH.unshift Dir.pwd
|
9
|
+
$LOAD_PATH.unshift Dir.pwd + '/lib'
|
10
|
+
Dir.chdir('test') rescue nil
|
11
|
+
|
12
|
+
require 'test/unit'
|
13
|
+
require 'win32/mc'
|
14
|
+
include Win32
|
15
|
+
|
16
|
+
class TC_Win32_MC < Test::Unit::TestCase
|
17
|
+
def setup
|
18
|
+
@mc = MC.new('foo.mc')
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_01_version
|
22
|
+
assert_equal('0.1.2', MC::VERSION)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_02_create_header
|
26
|
+
assert_respond_to(@mc, :create_header)
|
27
|
+
assert_nothing_raised{ @mc.create_header }
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_03_create_res_file
|
31
|
+
assert_respond_to(@mc, :create_res_file)
|
32
|
+
assert_nothing_raised{ @mc.create_res_file }
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_04_create_dll_file
|
36
|
+
assert_respond_to(@mc, :create_dll_file)
|
37
|
+
assert_nothing_raised{ @mc.create_dll_file }
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_05_clean
|
41
|
+
assert_respond_to(@mc, :clean)
|
42
|
+
assert_nothing_raised{ @mc.clean }
|
43
|
+
end
|
44
|
+
|
45
|
+
def teardown
|
46
|
+
@mc = nil
|
47
|
+
File.delete('foo.dll') rescue nil
|
48
|
+
end
|
49
|
+
end
|
data/test/ts_all.rb
ADDED
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.0
|
3
|
+
specification_version: 1
|
4
|
+
name: win32-eventlog
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.4.2
|
7
|
+
date: 2006-08-06 00:00:00 -06:00
|
8
|
+
summary: Interface for the MS Windows Event Log.
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: djberg96@gmail.com
|
12
|
+
homepage: http://www.rubyforge.org/projects/win32utils
|
13
|
+
rubyforge_project:
|
14
|
+
description: Interface for the MS Windows Event Log.
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Daniel J. Berger
|
31
|
+
files:
|
32
|
+
- lib/win32/eventlog.rb
|
33
|
+
- lib/win32/mc.rb
|
34
|
+
- lib/win32/test.rb
|
35
|
+
- test/CVS
|
36
|
+
- test/foo.mc
|
37
|
+
- test/tc_eventlog.rb
|
38
|
+
- test/tc_mc.rb
|
39
|
+
- test/ts_all.rb
|
40
|
+
- CHANGES
|
41
|
+
- CVS
|
42
|
+
- MANIFEST
|
43
|
+
- README
|
44
|
+
- doc/tutorial.txt
|
45
|
+
test_files:
|
46
|
+
- test/ts_all.rb
|
47
|
+
rdoc_options: []
|
48
|
+
|
49
|
+
extra_rdoc_files:
|
50
|
+
- README
|
51
|
+
- CHANGES
|
52
|
+
- doc/tutorial.txt
|
53
|
+
executables: []
|
54
|
+
|
55
|
+
extensions: []
|
56
|
+
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
dependencies:
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: windows-pr
|
62
|
+
version_requirement:
|
63
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.5.0
|
68
|
+
version:
|