vmopt 0.0.2

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.
@@ -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.