require 'win32ole' require 'dev_tasks' module Wixgem class WindowsInstaller def self.install(msi_file) msi_file = msi_file.gsub(/\//, '\\') raise "#{msi_file} is already installed" if(WindowsInstaller.installed?(msi_file)) execute("msiexec.exe /i #{msi_file}") end def self.uninstall(msi_file) raise "#{msi_file} does not exist!" unless(File.exists?(msi_file)) info = msi_properties(installer, msi_file) uninstall_product_code(info['ProductCode']) end def self.uninstall_product_name(product_name) raise "#{product_name} is not installed" unless(product_name_installed?(product_name)) uninstall_product_code(product_code_from_product_name(product_name)) end def self.uninstall_product_code(product_code) raise "#{product_code} is not installed" unless(product_code_installed?(product_code)) execute("msiexec.exe /quiet /x #{product_code}") end def self.msi_installed?(msi_file) info = msi_properties(msi_file) return product_code_installed?(info['ProductCode']) end def self.product_name_installed?(product_name) installer = WIN32OLE.new('WindowsInstaller.Installer') installer.Products.each { |prod_code| name = installer.ProductInfo(prod_code, "ProductName") return true if (product_name == name) } return false end def self.product_code_installed?(product_code) installer = WIN32OLE.new('WindowsInstaller.Installer') installer.Products.each { |installed_product_code| return true if (product_code == installed_product_code) } return false end def self.product_name_installed_version(product_name) installer = WIN32OLE.new('WindowsInstaller.Installer') info = product_info(installer, product_code_from_product_name(product_name, installer)) return info['VersionString'] end private def self.product_code_from_msi(msi_file, installer = nil) msi_info = msi_properties(msi_file) return msi_info['ProductCode'] end def self.product_code_from_product_name(product_name, installer = nil) installer = WIN32OLE.new('WindowsInstaller.Installer') if(installer.nil?) installer.Products.each { |prod_code| name = installer.ProductInfo(prod_code, "ProductName") return prod_code if (product_name == name) } raise "Failed to find product code for product: #{product_name}" end def self.product_code_properties(product_code, installer = nil) installer = WIN32OLE.new('WindowsInstaller.Installer') if(installer.nil?) hash = Hash.new # known product keywords found on internet. Would be nice to generate. %w[Language PackageCode Transforms AssignmentType PackageName InstalledProductName VersionString RegCompany RegOwner ProductID ProductIcon InstallLocation InstallSource InstallDate Publisher LocalPackage HelpLink HelpTelephone URLInfoAbout URLUpdateInfo InstanceType].sort.each do |prop| value = installer.ProductInfo(product_code, prop) hash[prop] = value unless(value.nil? || value == '') end return hash end def self.print_properties(product_name) installer = WIN32OLE.new('WindowsInstaller.Installer') properties = product_info(installer, product_code(product_name, installer)) properties.each { |id, value| puts "#{id}: #{value}" } end def self.msi_records(msi_file) records = {} installer = WIN32OLE.new('WindowsInstaller.Installer') sql_query = "SELECT * FROM `Property`" db = installer.OpenDatabase(msi_file, 0) view = db.OpenView(sql_query) view.Execute(nil) record = view.Fetch() return '' if(record == nil) while(!record.nil?) records[record.StringData(1)] = record.StringData(2) record = view.Fetch() end db.ole_free db = nil installer.ole_free installer = nil return records end def self.print_msi_records(msi_file) records = msi_records(msi_file) puts "#{msi_file} Properties:" records.each do |key,value| puts "#{key}: #{value}" end end def self.print_product_name(product_name) installer = WIN32OLE.new('WindowsInstaller.Installer') # only one session per process! session = installer.OpenProduct(product_code_from_product_name?(product_name, installer)) db = session.Database sql_query = "SELECT * FROM `Property`" view = db.OpenView(sql_query) view.Execute(nil) record = view.Fetch() return '' if(record == nil) puts "Session Properties:" while(!record.nil?) puts "#{record.StringData(1)}: #{record.StringData(2)}" record = view.Fetch() end db.ole_free db = nil installer.ole_free installer = nil puts '' end def self.execute(cmd) command = Wixgem::Command.new(cmd) command.execute end end end