ruby-wmi 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,16 @@
1
+ == 0.2.2 / 2008-01-11
2
+
3
+ * 1 major enhancemenet
4
+ * supports privileges
5
+ <code>
6
+ events = WMI::Win32_NTLogEvent.find(
7
+ :all, :privileges => [WMI::Privilege::Security],
8
+ :conditions => {:logfile => 'Security', :eventcode => '517'} )
9
+ </code>
10
+ * minor enhancements
11
+ * added error handling for invalid queries and class name typos
12
+ * better documentation
13
+
1
14
  == 0.2.1 / 2007-07-19
2
15
 
3
16
  * minor enhancements
@@ -4,11 +4,10 @@ README.txt
4
4
  Rakefile
5
5
  lib/ruby-wmi.rb
6
6
  lib/ruby-wmi/base.rb
7
- lib/ruby-wmi/cim.rb
7
+ lib/ruby-wmi/constants.rb
8
8
  lib/ruby-wmi/core_ext.rb
9
9
  lib/ruby-wmi/core_ext/time_ext.rb
10
10
  lib/ruby-wmi/core_ext/win32ole_ext.rb
11
- lib/ruby-wmi/win32.rb
12
11
  samples/disk.rb
13
12
  samples/logoff.rb
14
13
  samples/memory.rb
data/README.txt CHANGED
@@ -1,24 +1,40 @@
1
1
  ruby-wmi
2
2
  by Gordon Thiesfeld
3
3
  http://ruby-wmi.rubyforge.org/
4
+ gthiesfeld@gmail.com
4
5
 
5
6
  == DESCRIPTION:
6
-
7
- ruby-wmi is an ActiveRecord style interface for Microsoft's Windows Management Instrumentation provider.
7
+
8
+ ruby-wmi is an ActiveRecord style interface for Microsoft's Windows
9
+ Management Instrumentation provider.
10
+
11
+ Many of the methods in WMI::Base are borrowed directly, or with some
12
+ modification from ActiveRecord.
13
+ http://api.rubyonrails.org/classes/ActiveRecord/Base.html
14
+
15
+ The major tool in this library is the #find method. For more
16
+ information, see WMI::Base.
17
+
18
+ There is also a WMI.sublasses method included for reflection.
8
19
 
9
20
  == SYNOPSIS:
10
21
 
11
- # The following code sample kills all processes of a given name, except the oldest (in this case, Notepad)
22
+ # The following code sample kills all processes of a given name
23
+ # (in this case, Notepad), except the oldest.
12
24
 
13
25
  require 'ruby-wmi'
14
26
 
15
- processes = Win32::Process.find(:all, :conditions => { :name => 'Notepad.exe' })
16
- morituri = processes.sort_by{|p| p.CreationDate } #those who are about to die
17
- morituri.shift
27
+ procs = WMI::Win32_Process.find(:all,
28
+ :conditions => { :name => 'Notepad.exe' }
29
+ )
30
+ morituri = procs.sort_by{|p| p.CreationDate } #those who are about to die
31
+ morituri.shift
18
32
  morituri.each{|p| p.terminate }
19
33
 
20
34
  == REQUIREMENTS:
21
35
 
36
+ Windows 2000 or newer
37
+ Ruby 1.8
22
38
 
23
39
  == INSTALL:
24
40
 
data/Rakefile CHANGED
@@ -4,15 +4,59 @@ require 'rubygems'
4
4
  require 'hoe'
5
5
  require './lib/ruby-wmi.rb'
6
6
 
7
- Hoe.new('ruby-wmi', Ruby_wmi::VERSION) do |p|
7
+ class Hoe
8
+ attr_accessor :download_url
9
+ attr_accessor :title
10
+ attr_accessor :tagline
11
+
12
+ alias_method :old_define_tasks, :define_tasks
13
+ def define_tasks
14
+ old_define_tasks
15
+
16
+ desc "Generate webpage"
17
+ task :generate_web do
18
+ require 'uv'
19
+ require 'erubis'
20
+
21
+ @samples = Dir['samples/*.rb'].map do |file|
22
+ html = Uv.parse( File.read(file), "xhtml", "ruby", false, "lazy")
23
+ [file, html]
24
+ end
25
+
26
+ input = File.read('web/templates/index.html.erb')
27
+ eruby = Erubis::Eruby.new(input) # create Eruby object
28
+ File.open('web/public/index.html', 'w+'){|f| f.puts eruby.result(binding()) }
29
+ end
30
+ end
31
+ end
32
+
33
+ Hoe.new('ruby-wmi', RubyWMI::VERSION) do |p|
8
34
  p.rubyforge_name = 'ruby-wmi'
35
+ p.tagline = 'WMI queries, easier'
36
+ p.title = "#{p.name} -- #{p.tagline}"
9
37
  p.author = 'Gordon Thiesfeld'
10
38
  p.email = 'gthiesfeld@gmail.com'
11
39
  p.summary = "ruby-wmi is an ActiveRecord style interface for Microsoft\'s Windows Management Instrumentation provider."
12
- # p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
13
- # p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
40
+ p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
41
+ p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
14
42
  p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
15
43
  p.need_tar = false
44
+ p.spec_extras = {
45
+ :requirements => ['allison', '>= 2.0.2'],
46
+ :rdoc_options => ['--title' , p.title ,
47
+ '--main' , 'README.txt' ,
48
+ '--line-numbers', '--template', File.join(Gem::GemPathSearcher.new.find('allison').full_gem_path,'lib','allison')]
49
+ }
50
+ p.download_url = 'http://rubyforge.org/projects/ruby-wmi/'
51
+
16
52
  end
17
53
 
54
+
55
+
56
+ # pscp -r -load rubyforge web/public/images vertiginal@rubyforge.org:/var/www/gforge-projects/ruby-wmi/images
57
+ # needed tasks
58
+ # * rdoc fixed.
59
+ # * clobber_webpage
60
+ # * publish_website
61
+
18
62
  # vim: syntax=Ruby
@@ -1,11 +1,10 @@
1
- class Ruby_wmi
2
- VERSION = '0.2.1'
1
+ class RubyWMI
2
+ VERSION = '0.2.2'
3
3
  end
4
4
 
5
5
  $:.unshift(File.dirname(__FILE__)) unless
6
6
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
7
7
 
8
8
  require 'ruby-wmi/core_ext'
9
+ require 'ruby-wmi/constants'
9
10
  require 'ruby-wmi/base'
10
- require 'ruby-wmi/cim'
11
- require 'ruby-wmi/win32'
@@ -2,43 +2,84 @@ require 'win32ole'
2
2
 
3
3
  module WMI
4
4
 
5
- def subclasses(options ={})
6
- Base.set_connection(options)
7
- b = Base.connection
8
- b.SubclassesOf.map { |subclass| class_name = subclass.Path_.Class }
9
- end
10
-
11
- alias :subclasses_of :subclasses
5
+ # Generic WMI exception class.
6
+ class WMIError < StandardError
7
+ end
8
+
9
+ # Invalid Class exception class.
10
+ class InvalidClass < WMIError
11
+ end
12
+
13
+ # Invalid Query exception class.
14
+ class InvalidQuery < WMIError
15
+ end
16
+
17
+ # Returns an array conating all the WMI subclasses
18
+ # on a sytem. Defaults to localhost
19
+ #
20
+ # WMI.subclasses
21
+ # => ["Win32_PrivilegesStatus", "Win32_TSNetworkAdapterSettingError", ...]
22
+ #
23
+ # For a more human readable version of subclasses when using options:
24
+ #
25
+ # WMI.subclasses_of(:host => some_computer)
26
+ # => ["Win32_PrivilegesStatus", "Win32_TSNetworkAdapterSettingError", ...]
27
+ def subclasses(options ={})
28
+ Base.set_connection(options)
29
+ b = Base.send(:connection)
30
+ b.SubclassesOf.map { |subclass| class_name = subclass.Path_.Class }
31
+ end
32
+
33
+
34
+ alias :subclasses_of :subclasses
35
+
36
+ extend self
12
37
 
13
- def const_missing(name)
14
- self.const_set(name, Class.new(self::Base))
15
- end
16
- extend self
17
-
18
38
  class Base
19
-
39
+ # Many of the methods in Base are borrowed directly, or with some modification from ActiveRecord
40
+ # http://api.rubyonrails.org/classes/ActiveRecord/Base.html
41
+
20
42
  class << self
21
- def subclass_name
22
- self.name.split('::').last
23
- end
24
43
 
25
- def connection
26
- c = WIN32OLE.new("WbemScripting.SWbemLocator")
27
- c.ConnectServer(@host,@klass,@credentials[:user],@credentials[:passwd])
28
- end
29
-
30
- def set_connection(options)
31
- @host = options[:host] || nil
32
- @klass = options[:class] || 'root/cimv2'
33
- @credentials = options[:credentials] || {:user => nil,:passwd => nil}
34
- end
35
-
44
+ # #find_by_wql currently only works when called through #find
45
+ # it may stay like that too. I haven't decided.
36
46
  def find_by_wql(query)
37
47
  d = connection.ExecQuery(query)
38
- d.count # needed to check for errors. Weird, but it works.
48
+ begin
49
+ d.count # needed to check for errors. Weird, but it works.
50
+ rescue => error
51
+ case error.to_s
52
+ when /Invalid class/i : raise InvalidClass
53
+ when /Invalid query/i : raise InvalidQuery
54
+ end
55
+ end
39
56
  d.to_a
40
57
  end
41
58
 
59
+ # WMI::Win32ComputerSystem.find(:all)
60
+ # returns an array of Win32ComputerSystem objects
61
+ #
62
+ # WMI::Win32ComputerSystem.find(:first)
63
+ # returns a Win32ComputerSystem object
64
+ #
65
+ # options:
66
+ #
67
+ # :conditions
68
+ #
69
+ # Conditions can either be specified as a string, array, or hash representing the WHERE-part of an SQL statement.
70
+ # The array form is to be used when the condition input is tainted and requires sanitization. The string form can
71
+ # be used for statements that don't involve tainted data. The hash form works much like the array form, except
72
+ # only equality and range is possible. Examples:
73
+ #
74
+ # Win32ComputerSystem.find(:all, :conditions => {:drivetype => 3} ) # Hash
75
+ # Win32ComputerSystem.find(:all, :conditions => [:drivetype, 3] ) # Array
76
+ # Win32ComputerSystem.find(:all, :conditions => 'drivetype = 3' ) # String
77
+ #
78
+ # :host - computername, defaults to localhost
79
+ # :class - swebm class , defaults to 'root\\cimv2'
80
+ # :privileges - see WMI::Privilege for a list of privileges
81
+ # :user - username (domain\\username)
82
+ # :password - password
42
83
  def find(arg=:all, options={})
43
84
  set_connection options
44
85
  case arg
@@ -46,7 +87,7 @@ module WMI
46
87
  when :first; find_first(options)
47
88
  end
48
89
  end
49
-
90
+
50
91
  def find_first(options={})
51
92
  find_all(options).first
52
93
  end
@@ -54,7 +95,26 @@ module WMI
54
95
  def find_all(options={})
55
96
  find_by_wql(construct_finder_sql(options))
56
97
  end
57
-
98
+
99
+ def set_connection(options)
100
+ @host = options[:host]
101
+ @klass = options[:class] || 'root\\cimv2'
102
+ @user,@password = options[:user], options[:password]
103
+ @privileges = options[:privileges]
104
+ end
105
+
106
+ private
107
+
108
+ def subclass_name
109
+ self.name.split('::').last
110
+ end
111
+
112
+ def connection
113
+ @c ||= WIN32OLE.new("WbemScripting.SWbemLocator")
114
+ @privileges.each { |priv| @c.security_.privileges.add(priv, true) } if @privileges
115
+ @c.ConnectServer(@host,@klass,@user,@password)
116
+ end
117
+
58
118
  def construct_finder_sql(options)
59
119
  #~ scope = scope(:find)
60
120
  sql = "SELECT #{options[:select] || '*'} "
@@ -71,7 +131,7 @@ module WMI
71
131
 
72
132
  sql
73
133
  end
74
-
134
+
75
135
  def add_conditions!(sql, conditions, scope = :auto)
76
136
  #~ scope = scope(:find) if :auto == scope
77
137
  segments = []
@@ -79,10 +139,10 @@ module WMI
79
139
  #~ segments << conditions unless conditions.nil?
80
140
  #~ segments << type_condition unless descends_from_active_record?
81
141
  segments.compact!
82
- sql << "WHERE (#{segments.join(") AND (")}) " unless segments.empty?
142
+ sql << "WHERE #{segments.join(") AND (")} " unless segments.empty?
83
143
  sql.gsub!("\\","\\\\\\")
84
144
  end
85
-
145
+
86
146
  # Accepts an array, hash, or string of sql conditions and sanitizes
87
147
  # them into a valid SQL fragment.
88
148
  # ["name='%s' and group_id='%s'", "foo'bar", 4] returns "name='foo''bar' and group_id='4'"
@@ -108,7 +168,13 @@ module WMI
108
168
  end.join(' AND ')
109
169
 
110
170
  #~ replace_bind_variables(conditions, attrs.values)
111
- end
171
+ end
112
172
  end
113
173
  end
174
+
175
+ private
176
+
177
+ def const_missing(name)
178
+ self.const_set(name, Class.new(self::Base))
179
+ end
114
180
  end
@@ -0,0 +1,94 @@
1
+ module WMI
2
+ module Privilege
3
+ # Required to create a primary token.
4
+ CreateToken = 1
5
+
6
+ # Required to assign the primary token of a process.
7
+ PrimaryToken = 2
8
+
9
+ # Required to lock physical pages in memory.
10
+ LockMemory = 3
11
+
12
+ # Required to increase the quota assigned to a process.
13
+ IncreaseQuota = 4
14
+
15
+ # Required to create a machine account.
16
+ MachineAccount = 5
17
+
18
+ # Identifies its holder as part of the trusted computer base. Some trusted, protected
19
+ # subsystems are granted this privilege.
20
+ Tcb = 6
21
+
22
+ # Required to perform a number of security-related functions, such as controlling and
23
+ # viewing audit messages. This privilege identifies its holder as a security operator.
24
+ #
25
+ Security = 7
26
+
27
+ # Required to take ownership of an object without being granted discretionary access.
28
+ # This privilege allows the owner value to be set only to those values that the holder
29
+ # may legitimately assign as the owner of an object.
30
+ TakeOwnership = 8
31
+
32
+ # Required to load or unload a device driver.
33
+ LoadDriver = 9
34
+
35
+ # Required to gather profiling information for the entire system.
36
+ SystemProfile = 10
37
+
38
+ # Required to modify the system time.
39
+ Systemtime = 11
40
+
41
+ # Required to gather profiling information for a single process.
42
+ ProfileSingleProcess = 12
43
+
44
+ # Required to increase the base priority of a process.
45
+ IncreaseBasePriority = 13
46
+
47
+ # Required to create a paging file.
48
+ CreatePagefile = 14
49
+
50
+ # Required to create a permanent object.
51
+ CreatePermanent = 15
52
+
53
+ # Required to perform backup operations.
54
+ Backup = 16
55
+
56
+ # Required to perform restore operations. This privilege enables you to set any valid
57
+ # user or group security identifier (SID) as the owner of an object.
58
+ Restore = 17
59
+
60
+ # Required to shut down a local system.
61
+ Shutdown = 18
62
+
63
+ # Required to debug a process.
64
+ Debug = 19
65
+
66
+ # Required to generate audit-log entries.
67
+ Audit = 20
68
+
69
+ # Required to modify the nonvolatile RAM of systems that use this type of memory to store
70
+ # configuration information.
71
+ SystemEnvironment = 21
72
+
73
+ # Required to receive notifications of changes to files or directories. This privilege
74
+ # also causes the system to skip all traversal access checks. It is enabled by default
75
+ # for all users.
76
+ ChangeNotify = 22
77
+
78
+ # Required to shut down a system using a network request.
79
+ RemoteShutdown = 23
80
+
81
+ # Required to remove a computer from a docking station.
82
+ Undock = 24
83
+
84
+ # Required to synchronize directory service data.
85
+ SyncAgent = 25
86
+
87
+ # Required to enable computer and user accounts to be trusted for delegation.
88
+ EnableDelegation = 26
89
+
90
+ # Required to perform volume maintenance tasks. Windows 2000, Windows NT 4.0, and Windows
91
+ # Me/98/95: This privilege is not available.
92
+ ManageVolume = 27
93
+ end
94
+ end
@@ -6,9 +6,6 @@ properties = ['Description','MaxCapacity','MemoryDevices','MemoryErrorCorrection
6
6
  mem = WMI::Win32_PhysicalMemoryArray.find(:all, :host => 'server1')
7
7
  mem.each{|i| puts properties.map{|p| "#{p}: #{i[p]}"}}
8
8
 
9
- mem2 = WMI::Win32_PhysicalMemoryArray.find(:all, {:host => 'server2', :credentials =>
10
- {:user => 'domain\\gordon', :passwd => 'password'}
11
- }
12
- )
9
+ mem2 = WMI::Win32_PhysicalMemoryArray.find(:all, {:host => 'server2', :user => 'domain\\gordon', :passwd => 'password'} )
13
10
  mem2.each{|i| puts properties.map{|p| "#{p}: #{i[p]}"}}
14
11
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-wmi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gordon Thiesfeld
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-01-10 00:00:00 -06:00
12
+ date: 2008-01-14 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -21,7 +21,7 @@ dependencies:
21
21
  - !ruby/object:Gem::Version
22
22
  version: 1.4.0
23
23
  version:
24
- description: The author was too lazy to write a description
24
+ description: "ruby-wmi is an ActiveRecord style interface for Microsoft's Windows Management Instrumentation provider. Many of the methods in WMI::Base are borrowed directly, or with some modification from ActiveRecord. http://api.rubyonrails.org/classes/ActiveRecord/Base.html The major tool in this library is the #find method. For more information, see WMI::Base. There is also a WMI.sublasses method included for reflection."
25
25
  email: gthiesfeld@gmail.com
26
26
  executables: []
27
27
 
@@ -38,21 +38,25 @@ files:
38
38
  - Rakefile
39
39
  - lib/ruby-wmi.rb
40
40
  - lib/ruby-wmi/base.rb
41
- - lib/ruby-wmi/cim.rb
41
+ - lib/ruby-wmi/constants.rb
42
42
  - lib/ruby-wmi/core_ext.rb
43
43
  - lib/ruby-wmi/core_ext/time_ext.rb
44
44
  - lib/ruby-wmi/core_ext/win32ole_ext.rb
45
- - lib/ruby-wmi/win32.rb
46
45
  - samples/disk.rb
47
46
  - samples/logoff.rb
48
47
  - samples/memory.rb
49
48
  - test/test_ruby-wmi.rb
50
49
  has_rdoc: true
51
- homepage: http://www.zenspider.com/ZSS/Products/ruby-wmi/
50
+ homepage: " by Gordon Thiesfeld"
52
51
  post_install_message:
53
52
  rdoc_options:
53
+ - --title
54
+ - ruby-wmi -- WMI queries, easier
54
55
  - --main
55
56
  - README.txt
57
+ - --line-numbers
58
+ - --template
59
+ - c:/ruby/ruby186/lib/ruby/gems/1.8/gems/allison-2.0.2/lib/allison
56
60
  require_paths:
57
61
  - lib
58
62
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -67,8 +71,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
71
  - !ruby/object:Gem::Version
68
72
  version: "0"
69
73
  version:
70
- requirements: []
71
-
74
+ requirements:
75
+ - allison
76
+ - ">= 2.0.2"
72
77
  rubyforge_project: ruby-wmi
73
78
  rubygems_version: 1.0.1
74
79
  signing_key:
@@ -1,12 +0,0 @@
1
- module CIM
2
- extend WMI
3
-
4
- class Base < WMI::Base
5
- class << self
6
- def subclass_name
7
- self.name.gsub('::', '_')
8
- end
9
- end
10
- end
11
-
12
- end
@@ -1,11 +0,0 @@
1
- module Win32
2
- extend WMI
3
-
4
- class Base < WMI::Base
5
- class << self
6
- def subclass_name
7
- self.name.gsub('::', '_')
8
- end
9
- end
10
- end
11
- end