Ruby Win32 Registry: The system cannot find the file specified when looking for registry key that doesn't exist

StackOverflow https://stackoverflow.com/questions/22393572

  •  14-06-2023
  •  | 
  •  

質問

I'm writing a ruby function to get the UninstallString from a given DisplayName. My function only runs successfully when I give it an existing DisplayName to find, it crashes when I give something doesn't exist. I'm not sure which variable to check on what condition (nil? empty?) so I can throw an exception to my script print a message 'not found' instead of crashing ?

require 'win32/registry'

def get_uninstallstring(app_name)

  paths = [ "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
            "Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
            "Software\\Wow6464Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"  ]
  access_type = Win32::Registry::KEY_ALL_ACCESS

  paths.each do |path|         # This is line 9
    Win32::Registry::HKEY_LOCAL_MACHINE.open(path, access_type) do |reg|
      reg.each_key do |key|
        k = reg.open(key) 
        app = k['DisplayName'] rescue nil
        if app == app_name
          str = k['UninstallString'] rescue nil
          return str
        end
      end
    end
  end
  return false
end

puts get_uninstallstring("ABC")    # This is line 24

Here is the error output:

C:/ruby/1.9.1/win32/registry.rb:385:in `open': The system cannot find the file specified. (Win32::Registry::Error)
        from C:/heliopolis/opscode/chef/embedded/lib/ruby/1.9.1/win32/registry.rb:496:in `open'
        from test.rb:10:in `block in get_uninstallstring'
        from test.rb:9:in `each'
        from test.rb:9:in `get_uninstallstring'
        from test.rb:24:in `<main>'
役に立ちましたか?

解決

So I found a solution myself. I had to write another function to check if the key exists in a given path before I could actually get its value.

def key_exists?(path)
  begin
    Win32::Registry::HKEY_LOCAL_MACHINE.open(path, ::Win32::Registry::KEY_READ)
    return true
  rescue
    return false
  end
end

and here is the modified get function:

  paths.each do |path| 
    if key_exists?(path)
      Win32::Registry::HKEY_LOCAL_MACHINE.open(path, access_type) do |reg|
        reg.each_key do |key|
          k = reg.open(key)
          app = k['DisplayName'] rescue nil
          if app == app_name
        return k['UninstallString'] rescue nil
          end
        end
      end
    else
      return false
    end
  end
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top