vmopt 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,13 @@
1
+ #encoding: utf-8
2
+ #功能:操作注册表,注册硬件信息
3
+ module Registry
4
+ class << self
5
+ def hklm_read(key, value)
6
+ require 'win32/registry'
7
+ reg = Win32::Registry::HKEY_LOCAL_MACHINE.open(key)
8
+ rval = reg[value]
9
+ reg.close
10
+ rval
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ #encoding: utf-8
2
+ #功能:wmi模块,用于查询本地设备信息
3
+ module WMI
4
+ class << self
5
+ def connect(uri = wmi_resource_uri)
6
+ require 'win32ole'
7
+ WIN32OLE.codepage = WIN32OLE::CP_UTF8
8
+ WIN32OLE.connect(uri)
9
+ end
10
+
11
+ def wmi_resource_uri( host = '.' )
12
+ "winmgmts:{impersonationLevel=impersonate}!//#{host}/root/cimv2"
13
+ end
14
+
15
+ def execquery(query)
16
+ connect().execquery(query)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module Vmopt
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,295 @@
1
+ #encoding: utf-8
2
+ #功能:提供查询网卡详细信息的接口
3
+ #
4
+ $LOAD_PATH.unshift(File.join(__FILE__, '../..', '..'))
5
+ require "vmopt/utils/ip"
6
+ require "vmopt/utils/registry"
7
+ require "vmopt/utils/wmi"
8
+
9
+ module WinNetError
10
+ class NoInterfaceError < RuntimeError; end #没有给网络借口
11
+ class CMDexecFailedError < RuntimeError; end #命令执行出错
12
+ class NotFindFileError < RuntimeError; end #查不到对应文件
13
+ class NoSavePathError < RuntimeError;end #没有路径可保存
14
+ class InvalidParamError < RuntimeError;end #参数错误
15
+ end
16
+
17
+ class WinNet
18
+ # The WMI query used to return ip information
19
+ #
20
+ # @return [String]
21
+ #
22
+ # @api private
23
+ #WMI_IP_INFO_QUERY = 'SELECT Description, ServiceName, IPAddress, IPConnectionMetric, InterfaceIndex, Index, IPSubnet, MACAddress, MTU, SettingID FROM Win32_NetworkAdapterConfiguration WHERE IPConnectionMetric IS NOT NULL AND IPEnabled = TRUE'
24
+ WMI_IP_INFO_QUERY = 'SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPConnectionMetric IS NOT NULL AND IPEnabled = TRUE'
25
+
26
+
27
+ # Mapping fact names to WMI properties of the Win32_NetworkAdapterConfiguration
28
+ #
29
+ # @api private
30
+ WINDOWS_LABEL_WMI_MAP = {
31
+ :ipaddress => 'IPAddress',
32
+ :ipaddress6 => 'IPAddress',
33
+ :macaddress => 'MACAddress',
34
+ :netmask => 'IPSubnet'
35
+ }
36
+
37
+ #net connect status map
38
+ WINDOWS_CON_STATUS_MAP = {
39
+ 0 => "Disconnected",
40
+ 1 => "Connecting",
41
+ 2 => "Connected",
42
+ 3 => "Disconnecting",
43
+ 4 => "Hardware not present",
44
+ 5 => "Hardware disabled",
45
+ 6 => "Hardware malfunction",
46
+ 7 => "Media disconnected",
47
+ 8 => "Authenticating",
48
+ 9 => "Authentication succeeded",
49
+ 10 => "Authentication failed",
50
+ 11 => "Invalid address",
51
+ 12 => "Credentials required"
52
+ }
53
+
54
+ def self.to_s
55
+ 'windows'
56
+ end
57
+
58
+ # Windows doesn't display netmask in hex.
59
+ #
60
+ # @return [Boolean] false by default
61
+ #
62
+ # @api private
63
+ def self.convert_netmask_from_hex?
64
+ false
65
+ end
66
+
67
+ # Retrieves a list of unique interfaces names.
68
+ #
69
+ # @return [Array<String>]
70
+ #
71
+ # @api private
72
+ def self.interfaces
73
+ interface_names = []
74
+
75
+ WMI.execquery("SELECT * FROM Win32_NetworkAdapter").each do |nic|
76
+ interface_names << nic.NetConnectionId unless nic.NetConnectionId.nil? or nic.NetConnectionId.empty?
77
+ end
78
+
79
+ interface_names.uniq
80
+ end
81
+
82
+ # Retrieves netadapter
83
+ #
84
+ # @return [Array<win32ole>]
85
+ #
86
+ # @api private
87
+ def self.network_adapter
88
+ nics = []
89
+ WMI.execquery("SELECT * FROM Win32_NetworkAdapter WHERE NetConnectionID IS NOT NULL" ).each do |nic|
90
+ nics << nic
91
+ end
92
+ nics
93
+
94
+ end
95
+
96
+ def self.netconnstatus
97
+ stat={}
98
+ network_adapter.each do |interface|
99
+ stat[interface.netConnectionId] = WINDOWS_CON_STATUS_MAP[interface.netConnectionStatus]
100
+ end
101
+ stat
102
+ end
103
+
104
+ # Get the value of an interface and label. For example, you may want to find
105
+ # the MTU for eth0.
106
+ #
107
+ # @param [String] interface the name of the interface returned by the {#interfaces} method.
108
+ # @param [String] label the type of value to return, e.g. ipaddress
109
+ # @return [String] the value, or nil if not defined
110
+ #
111
+ # @api private
112
+ def self.value_for_interface_and_label(interface, label)
113
+ wmi_value = WINDOWS_LABEL_WMI_MAP[label.downcase.to_sym]
114
+ label_value = nil
115
+ WMI.execquery("SELECT Index FROM Win32_NetworkAdapter WHERE NetConnectionID = '#{interface}'").each do |nic|
116
+ WMI.execquery("SELECT #{wmi_value} FROM Win32_NetworkAdapterConfiguration WHERE Index = #{nic.Index}").each do |nic_config|
117
+ case label.downcase.to_sym
118
+ when :ipaddress
119
+ nic_config.IPAddress.any? do |addr|
120
+ label_value = addr if valid_ipv4_address?(addr)
121
+ label_value
122
+ end
123
+ when :ipaddress6
124
+ nic_config.IPAddress.any? do |addr|
125
+ label_value = addr if IP::Windows.valid_ipv6_address?(addr)
126
+ label_value
127
+ end
128
+ when :netmask
129
+ nic_config.IPSubnet.any? do |addr|
130
+ label_value = addr if IP::Windows.valid_ipv4_address?(addr)
131
+ label_value
132
+ end
133
+ when :macaddress
134
+ label_value = nic_config.MACAddress
135
+ end
136
+ end
137
+ end
138
+
139
+ label_value
140
+ end
141
+
142
+ # Returns an array of partial Win32_NetworkAdapterConfiguration objects.
143
+ #
144
+ # @return [Array<WIN32OLE>] objects
145
+ #
146
+ # @api private
147
+ def self.network_adapter_configurations
148
+ nics = []
149
+ # WIN32OLE doesn't implement Enumerable
150
+ WMI.execquery(WMI_IP_INFO_QUERY).each do |nic|
151
+ nics << nic
152
+ end
153
+ nics
154
+ end
155
+
156
+ # Gets a list of active IPv4 network adapter configurations sorted by the
157
+ # lowest IP connection metric. If two configurations have the same metric,
158
+ # then the IPv4 specific binding order as specified in the registry will
159
+ # be used.
160
+ #
161
+ # @return [Array<WIN32OLE>]
162
+ #
163
+ # @api private
164
+ def self.get_preferred_ipv4_adapters
165
+ get_preferred_network_adapters(Bindings4.new)
166
+ end
167
+
168
+ # Gets a list of active IPv6 network adapter configurations sorted by the
169
+ # lowest IP connection metric. If two configurations have the same metric,
170
+ # then the IPv6 specific binding order as specified in the registry will
171
+ # be used.
172
+ #
173
+ # @return [Array<WIN32OLE>]
174
+ #
175
+ # @api private
176
+ def self.get_preferred_ipv6_adapters
177
+ get_preferred_network_adapters(Bindings6.new)
178
+ end
179
+
180
+ # Gets a list of active network adapter configurations sorted by the lowest
181
+ # IP connection metric. If two configurations have the same metric, then
182
+ # the adapter binding order as specified in the registry will be used.
183
+ # Note the order may different for IPv4 vs IPv6 addresses.
184
+ #
185
+ # @see http://support.microsoft.com/kb/894564
186
+ # @return [Array<WIN32OLE>]
187
+ #
188
+ # @api private
189
+ def self.get_preferred_network_adapters(bindings)
190
+ network_adapter_configurations.select do |nic|
191
+ bindings.bindings.include?(nic.SettingID)
192
+ end.sort do |nic_left,nic_right|
193
+ cmp = nic_left.IPConnectionMetric <=> nic_right.IPConnectionMetric
194
+ if cmp == 0
195
+ bindings.bindings[nic_left.SettingID] <=> bindings.bindings[nic_right.SettingID]
196
+ else
197
+ cmp
198
+ end
199
+ end
200
+ end
201
+
202
+ class Bindings4
203
+ def initialize
204
+ @key = 'SYSTEM\CurrentControlSet\Services\Tcpip\Linkage'
205
+ end
206
+
207
+ def bindings
208
+ require 'vmopt/utils/registry'
209
+ bindings = {}
210
+
211
+ Registry.hklm_read(@key, 'Bind').each_with_index do |entry, index|
212
+ match_data = entry.match(/\\Device\\(\{.*\})/)
213
+ unless match_data.nil?
214
+ bindings[match_data[1]] = index
215
+ end
216
+ end
217
+
218
+ bindings
219
+ rescue
220
+ {}
221
+ end
222
+ end
223
+
224
+ class Bindings6 < Bindings4
225
+ def initialize
226
+ @key = 'SYSTEM\CurrentControlSet\Services\Tcpip6\Linkage'
227
+ end
228
+ end
229
+
230
+ # Determines if the value passed in is a valid ipv4 address.
231
+ #
232
+ # @param [String] ip_address the IPv4 address to validate
233
+ # @return [Boolean]
234
+ #
235
+ # @api private
236
+ def self.valid_ipv4_address?(ip_address)
237
+ String(ip_address).scan(/(?:[0-9]{1,3}\.){3}[0-9]{1,3}/).each do |match|
238
+ # excluding 169.254.x.x in Windows - this is the DHCP APIPA
239
+ # meaning that if the node cannot get an ip address from the dhcp server,
240
+ # it auto-assigns a private ip address
241
+ unless match == "127.0.0.1" or match =~ /^169.254.*/
242
+ return !!match
243
+ end
244
+ end
245
+
246
+ false
247
+ end
248
+
249
+ # Determines if the value passed in is a valid ipv6 address.
250
+ #
251
+ # @param [String] ip_address the IPv6 address to validate
252
+ # @return [Boolean]
253
+ #
254
+ # @api private
255
+ def self.valid_ipv6_address?(ip_address)
256
+ String(ip_address).scan(/(?>[0-9,a-f,A-F]*\:{1,2})+[0-9,a-f,A-F]{0,4}/).each do |match|
257
+ unless match =~ /fe80.*/ or match == "::1"
258
+ return !!match
259
+ end
260
+ end
261
+
262
+ false
263
+ end
264
+
265
+ end
266
+
267
+
268
+ if __FILE__ == $0
269
+
270
+ #查询网络接口名称
271
+ WinNet.interfaces.each{|i| puts i}
272
+
273
+ #查询网络接口mac地址
274
+ WinNet.interfaces.each do |inf|
275
+ puts WinNet.value_for_interface_and_label(inf, :macaddress)
276
+ end
277
+
278
+ #查询网络接口的属性,分别是描述,服务名,设置id
279
+ WinNet.network_adapter_configurations.each{|interface| puts interface.description}
280
+ WinNet.network_adapter_configurations.each{|interface| puts interface.serviceName}
281
+ WinNet.network_adapter_configurations.each{|interface| puts interface.settingID}
282
+
283
+ #查询网卡的连接状态
284
+ WinNet.interfaces.each do|i|
285
+ puts "#{i}: "+WinNet.netconnstatus[i]
286
+ end
287
+
288
+ #打印设备的PNPDeviceID,可用来提交给devcon.exe工具
289
+ WinNet.network_adapter.each{|interface| puts "#{interface.NetConnectionId} : " + "#{interface.pNPDeviceID}"}
290
+
291
+ end
292
+
293
+
294
+
295
+
@@ -0,0 +1,200 @@
1
+ # encoding: utf-8
2
+ #功能:提供windows窗口的基本操作
3
+
4
+ =begin rdoc
5
+ 类名: 通用操作类
6
+ 描述: 封装系统操作调用相关的内容
7
+ =end
8
+ require "win32ole"
9
+ WIN32OLE.codepage = WIN32OLE::CP_UTF8
10
+ require "Win32API"
11
+ require "rautomation"
12
+ require "vmopt/ext/string_ext"
13
+
14
+ module WinUtils
15
+
16
+ class KillProcessFailError < RuntimeError; end #杀死进程失败的错误
17
+ class EmptyFileFailError < RuntimeError; end #清除目录错误
18
+ class NotFindZipError < RuntimeError; end #查不到对应的ZIP文件
19
+ class NotFindFileError < RuntimeError; end #查不到对应文件
20
+ class NotSuitableStringError < RuntimeError; end #未按要求的的字符串
21
+ class NotFindWindowError < RuntimeError; end #查找不到窗口
22
+ class ActivateFailError < RuntimeError; end #激活窗口失败
23
+ class WaitConnectTimeoutError < RuntimeError; end #TCP连接失败异常
24
+ class NoSavePathError < RuntimeError;end #没有路径可保存
25
+
26
+ =begin rdoc
27
+ 参数:无
28
+ 作用:检测到除了为简体中文时为中文系统,其余都判断为英文系统.
29
+ 返回值:返回国家域名缩写的小写形式
30
+ =end
31
+ def self.os_type
32
+ WIN32OLE.connect('winmgmts:\\\.').ExecQuery("select * from Win32_OperatingSystem").each do |m|
33
+ return "cn" if m.OSLanguage == 4 || m.OSLanguage == 2052
34
+ end
35
+ "en"
36
+ end
37
+
38
+ =begin rdoc
39
+ 参数:titlename:查找的标题名称,activate_flag = false
40
+ 作用:查找是否有给定标题名称的惟一对象,activate_flag表示是否能够激活窗口。
41
+ 返回值:找到惟一对象则返回true;找不到或找到为非惟一的则返回false
42
+ =end
43
+ def self.find_single_active_window?(titlename,activate_flag = false)
44
+ find_res=0
45
+ all_rautowindow = RAutomation::Window.windows
46
+ all_rautowindow.each do |win|
47
+ find_res+=1 if (win.exists? && win.title !=nil && (win.title.include?(titlename) rescue false))
48
+ end
49
+ return false if find_res.to_s != "1" #找到了有多个标题框的内容,直接返回fasle
50
+ rautowindow = RAutomation::Window.new(:title=>titlename,:adapter=>"Autoit")
51
+ if activate_flag
52
+ return false unless rautowindow.exists? #不存在为假;
53
+ rautowindow.WinActivate(rautowindow.title) unless rautowindow.WinActive(rautowindow.title)
54
+ return true if res_status.to_s == "15"
55
+ return false
56
+ else
57
+ rautowindow.exists?
58
+ end
59
+ end
60
+
61
+ =begin rdoc
62
+ 参数:要搜索的标题名称和激活窗口标志,激活窗口标志默认为true
63
+ 作用:查找是否有查找到给定的标题名称的对话框,如果有则返回RAutomation对
64
+ 象,否则返回nil
65
+ 返回值:成功找到返回RAutomation的Windows对象
66
+ =end
67
+ def self.find_window(titlename,flag = true)
68
+ retrytime=0
69
+ begin
70
+ rautowindow = RAutomation::Window.new(:title=>titlename,:adapter=>"Autoit")
71
+ retrytime+=1
72
+ sleep 1
73
+ end while !rautowindow.exists? and retrytime <= 10
74
+ raise ::WinUtils::NotFindWindowError,"Not found the windows like #{titlename}." if !rautowindow.exists?
75
+ if flag
76
+ res = rautowindow.WinActivate(rautowindow.title) unless rautowindow.WinActive(rautowindow.title)
77
+ raise ::WinUtils::ActivateFailError,"Cant't Activate the Window #{rautowindow.title}" if res.to_s == "0"
78
+ end
79
+ rautowindow
80
+ end
81
+
82
+
83
+
84
+ =begin rdoc
85
+ 参数:根据窗口的text来定位title
86
+ 作用:查找是否有查找到给定的窗口的text的对话框,如果有则返回RAutomation对
87
+ 象,否则的返回false
88
+ 返回值:成功找到返回RAutomation的Windows对象
89
+ =end
90
+ def self.find_window_by_text(textname)
91
+ rautowindows = RAutomation::Window.windows
92
+ rautowindows.map do |win|
93
+ return win if win.text.include?(textname)
94
+ end
95
+ nil
96
+ end
97
+
98
+ =begin rdoc
99
+ 参数:process_name:进程名;reserve_process_path:期望路径
100
+ 作用:杀掉给定名称的进程,reserve_process_path有值则保留这个环境下的进程
101
+ 返回值:若异常则抛出异常,否则返回真
102
+ =end
103
+ def self.kill_process(process_name,reserve_process_path=nil)
104
+ raise ArgumentError,"the argument can't be nil." if process_name.nil?
105
+ begin
106
+ gbk_reserve_process_path = reserve_process_path.to_gbk unless reserve_process_path.nil?
107
+ WIN32OLE.connect('winmgmts:\\\.').ExecQuery("SELECT * FROM Win32_Process").each do |item|
108
+ if item.Caption == process_name.to_gbk
109
+ if gbk_reserve_process_path == nil
110
+ item.Terminate
111
+ next
112
+ end
113
+ next if item.ExecutablePath != nil && item.ExecutablePath.gsub("\\","/").downcase == gbk_reserve_process_path.gsub("\\","/").downcase
114
+ item.Terminate
115
+ end
116
+ end
117
+ return true
118
+ rescue =>err
119
+ raise ::WinUtils::KillProcessFailError,"Kill process: #{process_name.to_utf8} failed!err_msg:#{err}"
120
+ end
121
+ end
122
+
123
+ =begin rdoc
124
+ 参数:process_name:进程名
125
+ 作用:查找给定名称的进程,
126
+ 返回值:查看是否有找到给定文件名的进程,若有则返回真,若无则返回假
127
+ =end
128
+ def self.find_process?(process_name)
129
+ raise ArgumentError,"the argument can't be nil." if process_name.nil?
130
+ gbk_process_name = process_name.to_gbk
131
+ WIN32OLE.connect('winmgmts:\\\.').ExecQuery("SELECT * FROM Win32_Process").each do |item|
132
+ return true if item.Caption.downcase == gbk_process_name.downcase
133
+ end
134
+ false
135
+ end
136
+
137
+ =begin rdoc
138
+ 参数:准备被清空的目录dir或文件
139
+ 作用:清空目录下的所有文件;但保留dir目录,若dir为文件就会删除
140
+ 返回值:若异常则抛出异常,否则返回真
141
+ =end
142
+ def self.empty_dir(dir)
143
+ raise ArgumentError,"the argument can't be nil." if dir.nil?
144
+ begin
145
+ gbk_dest_dir = dir.to_gbk
146
+ Find.find(gbk_dest_dir) do |file|
147
+ next if ! File.exist?(file)
148
+ #next if File.directory?(file) && (file.downcase == gbk_dest_dir.downcase)
149
+ if File.directory?(file)
150
+ FileWinUtils.rm_rf(file)
151
+ else
152
+ File.delete(file)
153
+ end
154
+ end
155
+ return true
156
+ rescue =>err
157
+ raise ::WinUtils::EmptyFileFailError,"empty_dir #{dir.to_utf8} failed!err_msg:#{err}."
158
+ end
159
+ end
160
+
161
+ =begin rdoc
162
+ 参数:给定的目录,需要查找的文件名
163
+ 作用:在给定的目录中查找给定的文件,若查找到时返回这个文件的目路径,否则返回空
164
+ 返回值:返回文件所在路径或为空
165
+ =end
166
+ def self.get_filepath(dest_dir,filename)
167
+ raise ArgumentError,"the argument can't be nil." if dest_dir.nil? || filename.nil?
168
+ gbk_dest_dir = dest_dir.to_gbk
169
+ gbk_filename = filename.to_gbk
170
+ Find.find(gbk_dest_dir) do |filepath|
171
+ filepath_arr = filepath.split("/")
172
+ return (Pathname.new(File.expand_path(filepath)).realpath).to_s.gsub("/","\\\\") if (filepath_arr[-1].downcase == gbk_filename.downcase && !File.directory?(filepath) )
173
+ end
174
+ raise ::WinUtils::NotFindFileError,"Not find named :#{filename.to_utf8} file in the dir:#{dest_dir.to_utf8}."
175
+ end
176
+ =begin rdoc
177
+ 参数:两个字符串str1,str2
178
+ 作用:去除str1中头部有str2的部分,需要完整匹配
179
+ 返回值:被去除后的字符串
180
+ =end
181
+ def self.remove_head_str(str1,str2)
182
+ str1_size = str1.size
183
+ str2_size = str2.size
184
+ raise ::WinUtils::NotSuitableStringError,"the length of str1 need > str2's size." if str1_size<str2_size
185
+ return "" if str1 == str2
186
+ i = 1
187
+ str2_arr_size = str2.split("\n").size
188
+ result_str=""
189
+ str1.each_line do |line|
190
+ if i<=str2_arr_size
191
+ raise ::WinUtils::NotSuitableStringError,"The relation of str1:#{str1.dump} and str2:#{str2.dump} is not suitable." unless str2.include?(line)
192
+ i = i+1
193
+ next
194
+ end
195
+ result_str<<line
196
+ end
197
+ result_str.strip
198
+ end
199
+
200
+ end #end of WinUtils.