Class: MiqWin32::Software
- Inherits:
-
Object
- Object
- MiqWin32::Software
- Defined in:
- lib/metadata/util/win32/Win32Software.rb
Constant Summary collapse
- PRODUCTS_MAPPING =
[ 'DisplayName', :name, 'Publisher', :vendor, 'DisplayVersion', :version, 'Comments', :description, 'InstallLocation', :path, # 'PackageName', :package_name, # 'ProductIcon', :product_icon, # 'PackageName', :package_name, 'InstallDate', :install_time, ]
- APP_PATHS_MAPPING =
[ 'FileDescription', :name, 'CompanyName', :vendor, 'ProductVersion', :version, 'FileDescription', :description, 'ProductName', :package_name, 'lang', :language, 'path', :path, ]
- UNINSTALL_MAPPING =
[ 'DisplayName', :name, 'Publisher', :vendor, 'DisplayVersion', :version, 'FileDescription', :description, 'ReleaseType', :release_type, 'InstallDate', :installed_on ]
- HOTFIX_MAPPING =
[ 'Fix Description', :description, # Check Fix Decription, and then if 'Comments', :description2, # not found, check Comments 'Installed', :installed, 'Service Pack', :service_pack, 'Valid', :valid, ]
- HOTFIX_MAPPING_VISTA =
[ 'CurrentState', :current_state, 'Visibility', :visibility, 'InstallTimeHigh', :install_time_high, 'InstallTimeLow', :install_time_low ]
Instance Attribute Summary collapse
-
#applications ⇒ Object
readonly
Returns the value of attribute applications.
-
#patches ⇒ Object
readonly
Returns the value of attribute patches.
-
#product_keys ⇒ Object
readonly
Returns the value of attribute product_keys.
Class Method Summary collapse
Instance Method Summary collapse
- #add_applications(mapping, type_name, element) ⇒ Object
- #clean_up_path(attrs) ⇒ Object
- #convert_times(attrs) ⇒ Object
- #element_to_xml(doc = nil, software_type, doc_element, node_element) ⇒ Object
- #hotfix_id(element) ⇒ Object
-
#initialize(_c, fs) ⇒ Software
constructor
A new instance of Software.
-
#initialize_registry_doc(fs) ⇒ Object
# Process application images e.find_each(“./descendant::image”) { |i| nh = i.attributes; validate_image(i, nh)}.
- #isDupApp?(attrs) ⇒ Boolean
- #registry_applications(registry_doc, fs) ⇒ Object
- #registry_applications_app_paths(registry_doc, registry_path, fs) ⇒ Object
- #registry_applications_uninstall(element) ⇒ Object
- #registry_applications_user_data(reg_node) ⇒ Object
- #registry_patches(registry_doc) ⇒ Object
- #registry_patches_hotfixes(element) ⇒ Object
- #registry_patches_packages(hotfix, element) ⇒ Object
- #to_xml(doc = nil) ⇒ Object
Constructor Details
#initialize(_c, fs) ⇒ Software
Returns a new instance of Software.
56 57 58 59 60 61 62 63 64 65 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 56 def initialize(_c, fs) @patches = [] @applications = [] @patch_install_dates = {} @product_keys = {} reg_doc = initialize_registry_doc(fs) registry_applications(reg_doc, fs) registry_patches(reg_doc) end |
Instance Attribute Details
#applications ⇒ Object (readonly)
Returns the value of attribute applications.
8 9 10 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 8 def applications @applications end |
#patches ⇒ Object (readonly)
Returns the value of attribute patches.
8 9 10 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 8 def patches @patches end |
#product_keys ⇒ Object (readonly)
Returns the value of attribute product_keys.
8 9 10 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 8 def product_keys @product_keys end |
Class Method Details
.DecodeProductKey(product_key) ⇒ Object
254 255 256 257 258 259 260 261 262 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 254 def self.DecodeProductKey(product_key) parts = product_key.to_s.split(",") return if parts.length < 67 ManageIQ::Smartstate::Util.base24_decode(parts[52..67].map(&:hex)) rescue => err $log.error "MIQ(DecodeProductKey): [#{err}]" nil end |
Instance Method Details
#add_applications(mapping, type_name, element) ⇒ Object
138 139 140 141 142 143 144 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 138 def add_applications(mapping, type_name, element) return if (attrs = XmlFind.decode(element, mapping))[:name].nil? attrs[:typename] = type_name; attrs[:product_key] = @product_keys[attrs[:name]] clean_up_path(attrs) convert_times(attrs) @applications << attrs unless isDupApp?(attrs) end |
#clean_up_path(attrs) ⇒ Object
240 241 242 243 244 245 246 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 240 def clean_up_path(attrs) if attrs[:path] ["\\", ";"].each { |c| attrs[:path].chomp!(c) } attrs[:path].gsub!(/^"/, "") attrs[:path].gsub!(/"$/, "") end end |
#convert_times(attrs) ⇒ Object
248 249 250 251 252 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 248 def convert_times(attrs) [:install_time].each do |i| attrs[i] = attrs[i].in_time_zone if attrs[i] end end |
#element_to_xml(doc = nil, software_type, doc_element, node_element) ⇒ Object
224 225 226 227 228 229 230 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 224 def element_to_xml(doc = nil, software_type, doc_element, node_element) doc ||= MiqXml.createDoc(nil) return doc if software_type.empty? node = doc.add_element(doc_element) software_type.each { |a| node.add_element(node_element, XmlHelpers.stringify_keys(a)) } doc end |
#hotfix_id(element) ⇒ Object
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 198 def hotfix_id(element) # Expected pattern: Package_for_KBxxx_RTM~xxxx # Get the hotfix id (KB #) out of the keyname package = element.attributes[:keyname].split("_") # If the package identifier starts with KB, use this # otherwise grab the ID from the end of the string (if it's long enough) if package[2][0, 2] == 'KB' hotfix_id = package[2] elsif package.size >= 4 hotfix_id = package[3] else # Unknown package ID pattern, print this out str = '' element.write(str) $log.warn("Win32Software::initialize - Can't determine patch element's hotfix id: #{str}") end hotfix_id.split('~')[0] unless hotfix_id.nil? end |
#initialize_registry_doc(fs) ⇒ Object
# Process application images
e.find_each("./descendant::image") { |i| nh[:image_md5] = i.attributes['md5']; validate_image(i, nh)}
def self.validate_image(imageNode, nh)
#logger.warn("MIQ(applications-add_elements): Checking application image [#{nh.inspect}] -- [#{imageNode.to_s}]")
x = ApplicationImage.find_by_md5(imageNode.attributes['md5'])
if x
#logger.warn("MIQ(applications-add_elements): Application image found [#{imageNode.attributes['md5']}]")
else
#logger.warn("MIQ(applications-add_elements): Application image NOT found [#{imageNode.attributes['md5']}]")
ApplicationImage.create({:md5=>imageNode.attributes['md5'], :name=>nh['name'], :vendor=>nh['vendor'], :version=>nh['version']})
end
end
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 81 def initialize_registry_doc(fs) regHnd = RemoteRegistry.new(fs, true) # reg_doc = regHnd.loadHive("software", ["Microsoft"]) reg_doc = regHnd.loadHive('software', [{:key => 'Microsoft/Windows NT/CurrentVersion/Hotfix', :value => ['fix description', 'comments', 'installed', 'service pack', 'valid']}, {:key => 'Microsoft/Windows/CurrentVersion/Installer/UserData', :value => ['DisplayName', 'Publisher', 'DisplayVersion', 'Comments', 'InstallLocation', 'InstallDate']}, {:key => 'Microsoft/Windows/CurrentVersion/Uninstall', :value => ['DisplayName', 'Publisher', 'DisplayVersion', 'FileDescription', 'ReleaseType', 'InstallDate']}, {:key => 'Wow6432Node/Microsoft/Windows/CurrentVersion/Uninstall', :value => ['DisplayName', 'Publisher', 'DisplayVersion', 'FileDescription', 'ReleaseType', 'InstallDate']}, {:key => 'Microsoft/Windows/CurrentVersion/App Paths', :value => ['(Default)', 'FileDescription', 'CompanyName', 'ProductVersion', 'FileDescription', 'ProductName', 'lang', 'path']}, {:key => 'Wow6432Node/Microsoft/Windows/CurrentVersion/App Paths', :value => ['(Default)', 'FileDescription', 'CompanyName', 'ProductVersion', 'FileDescription', 'ProductName', 'lang', 'path']}, # These locations are used to check for Product keys {:key => 'Microsoft/Internet Explorer/Registration', :value => ['digitalproductid']}, {:key => 'Microsoft/Windows/CurrentVersion/Component Based Servicing/Packages', :value => ['CurrentState', 'Visibility', 'InstallTimeHigh', 'InstallTimeLow']}, {:key => 'Microsoft/Office', :value => ['digitalproductid']}]) @digital_product_keys = regHnd.digitalProductKeys regHnd.close @product_keys = collectProductKeys(@digital_product_keys) reg_doc end |
#isDupApp?(attrs) ⇒ Boolean
232 233 234 235 236 237 238 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 232 def isDupApp?(attrs) clean_up_path(attrs) @applications.each do |app| return true if app[:name] == attrs[:name] end false end |
#registry_applications(registry_doc, fs) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 102 def registry_applications(registry_doc, fs) # Get the applications reg_node = MIQRexml.findRegElement("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData", registry_doc.root) registry_applications_user_data(reg_node) if reg_node ["HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\App Paths", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths"].each do |reg_path| registry_applications_app_paths(registry_doc, reg_path, fs) end ["HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"].each do |reg_path| reg_node = MIQRexml.findRegElement(reg_path, registry_doc.root) reg_node&.each_element_with_attribute(:keyname) do |e| registry_applications_uninstall(e) end end end |
#registry_applications_app_paths(registry_doc, registry_path, fs) ⇒ Object
130 131 132 133 134 135 136 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 130 def registry_applications_app_paths(registry_doc, registry_path, fs) return unless (reg_node = MIQRexml.findRegElement(registry_path, registry_doc.root)) postProcessApps(reg_node, fs) reg_node.each_element_with_attribute(:keyname) do |e| add_applications(APP_PATHS_MAPPING, "app_path", e) end end |
#registry_applications_uninstall(element) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 146 def registry_applications_uninstall(element) return if (attrs = XmlFind.decode(element, UNINSTALL_MAPPING))[:name].nil? if ["security update", "update"].include?(attrs.delete(:release_type).to_s.downcase) @patch_install_dates[e.attributes[:keyname]] = Time.parse.getlocal(attrs[:installed_on]) unless attrs[:installed_on].nil? return else attrs.delete(:installed_on) end attrs[:typename] = "uninstall"; attrs[:product_key] = @product_keys[attrs[:name]] @applications << attrs unless isDupApp?(attrs) end |
#registry_applications_user_data(reg_node) ⇒ Object
119 120 121 122 123 124 125 126 127 128 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 119 def registry_applications_user_data(reg_node) reg_node.each_element_with_attribute(:keyname) do |users| users.each_element_with_attribute(:keyname) do |components| next unless components.attributes[:keyname].downcase == "products" components.each_element_with_attribute(:keyname) do |products| add_applications(PRODUCTS_MAPPING, "win32_product", products) end end end end |
#registry_patches(registry_doc) ⇒ Object
158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 158 def registry_patches(registry_doc) # Get the patches (Win2000, Win2003, WinXP) reg_node = MIQRexml.findRegElement("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix", registry_doc.root) reg_node&.each_element_with_attribute(:keyname) do |e| registry_patches_hotfixes(e) end # Get the patches (Vista, Win2008, Windows 7) reg_node = MIQRexml.findRegElement("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Component Based Servicing\\Packages", registry_doc.root) hotfix = {} reg_node&.each_element do |e| registry_patches_packages(hotfix, e) end end |
#registry_patches_hotfixes(element) ⇒ Object
172 173 174 175 176 177 178 179 180 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 172 def registry_patches_hotfixes(element) attrs = XmlFind.decode(element, HOTFIX_MAPPING) # Check both descriptions and take the first one with a value attrs.delete(:description2) if attrs[:description] || attrs[:description2].blank? attrs[:description] = attrs.delete(:description2) if attrs[:description2] attrs.merge!(:name => element.attributes[:keyname], :vendor => "Microsoft Corporation", :installed_on => @patch_install_dates[element.attributes[:keyname]]) unless element.attributes.nil? || element.attributes[:keyname].nil? @patches << attrs end |
#registry_patches_packages(hotfix, element) ⇒ Object
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 182 def registry_patches_packages(hotfix, element) return if element.attributes.nil? || element.attributes[:keyname].nil? if element.attributes[:keyname][0, 8] == 'Package_' # don't add this package if the ID is nil return if (hotfix_id = hotfix_id(element)).nil? hotfix[hotfix_id] ||= begin attrs = XmlFind.decode(element, HOTFIX_MAPPING_VISTA) install_time = wtime2time(attrs[:install_time_high], attrs[:install_time_low]) @patches << {:name => hotfix_id, :vendor => "Microsoft Corporation", :installed_on => install_time, :installed => 1} true end end end |
#to_xml(doc = nil) ⇒ Object
217 218 219 220 221 222 |
# File 'lib/metadata/util/win32/Win32Software.rb', line 217 def to_xml(doc = nil) doc ||= MiqXml.createDoc(nil) element_to_xml(doc, @applications, "applications", "application") element_to_xml(doc, @patches, "patches", "patch") doc end |