Win32ole - windowsinstaller.installer method

Hi all

I’m a beginner at ruby, so correct me if I’m doing something stupid.

I have created a method that reads a property from a windowsinstaller
table. (msi-package).

I have a list with paths to msi-packages, its 238 msi-packages that I’m
searching throe.
If i searching all the 238 files it eats a lot of memory (240 mb). And
21 packages fails to be read.
If i split the list in two it work without any problem, all the files
works.

I wonder if i have write my method in a bad way.

Any ideas ?

Method:

def GetProperty(msiPath, property)
begin
require ‘win32ole’
msiInstaller = WIN32OLE.new(‘WindowsInstaller.Installer’)
db = msiInstaller.OpenDatabase(msiPath, 0)
view = db.OpenView(“SELECT Value FROM Property WHERE Property =
‘#{property}’”)
view.Execute()
rescue RuntimeError
return “ERROR”
end
record = view.Fetch()
if record != nil then
return record.StringData(1)
else
return 0
end
end

GetProperty("\path\to\msi\package.msi", “ALLUSERS”)

If the property don’t exist it return 0, if the msi-package don’t exist
it return error, or if any other error message appear. If everything
work it return the value of ALLUSERS in the property-table of the
msi-packge.

If i inactivate the method the script doesn’t use so much memory.

// Micke

Hello,

Micke M. wrote:

    msiInstaller = WIN32OLE.new('WindowsInstaller.Installer')
    else
        return 0
    end

end

I have not written script using WindowsInstaller, but I think:
(1) msiInstaller should be created only at once if you could.
(2) view.close() should be called before return from GetProperty.
(I can’t find how to close db(Database) object.)

(1)
require ‘win32ole’
class Installer
@@msiInstaller = nil
def self.create
if !@@msiInstaller
@@msiInstaller = WIN32OLE.new(‘WindowsInstaller.Installer’)
end
@@msiInstaller
end
end

def GetProperty(msiPath, property)
begin
msiInstaller = Installer.create

(2)
record = view.Fetch()
val = 0
if record != nil then
val = record.StringData(1)
else
val = 0
end
view.close
return val

Hope this helps.
Regards,
Masaki S.

Masaki S. wrote:

Hello,

Micke M. wrote:

    msiInstaller = WIN32OLE.new('WindowsInstaller.Installer')
    else
        return 0
    end

end

I have not written script using WindowsInstaller, but I think:
(1) msiInstaller should be created only at once if you could.
(2) view.close() should be called before return from GetProperty.
(I can’t find how to close db(Database) object.)

(1)
require ‘win32ole’
class Installer
@@msiInstaller = nil
def self.create
if !@@msiInstaller
@@msiInstaller = WIN32OLE.new(‘WindowsInstaller.Installer’)
end
@@msiInstaller
end
end

def GetProperty(msiPath, property)
begin
msiInstaller = Installer.create

(2)
record = view.Fetch()
val = 0
if record != nil then
val = record.StringData(1)
else
val = 0
end
view.close
return val

Hope this helps.
Regards,
Masaki S.

Hi Masaki

I have tried the example above, unfortunately i get same result as
before. The script eats allot of memory, and it will not receive all the
msi-package information.

As i mention before, if I divide the msi-package-list in to, run the
script to time, it works.

I have tried with the latest version of ruby, but it fails, this time it
fails with more packages compare to 1.8 release of ruby.
I also tried to cut up the list in two arrays, and execute the
msi-method two times, but i get same problem as above.

I tried to make a similar script in python, except i can’t apply
transform-files, it worked without any problem, and much less memory
usage.
So i wonder if it is a problem in the win32ole.

Thanks for you help.

// Micke

Hello,

Micke M. wrote:

I also tried to cut up the list in two arrays, and execute the
msi-method two times, but i get same problem as above.

How about calling GC.start in GetProperty method?

def GetProperty(msiPath, property)
GC.start # <- add this line
begin
msiInstaller = Installer.create

Regards,
Masaki S.

Hello,

At 07/28/2009 07:54 PM, Micke M. wrote:

Do you know any good article how to structure ruby-programs ?

Sorry, I don’t know English article about Win32OLE.
(but someone in this ML knows it…)

The articles written in Japanese are:
http://jp.rubyist.net/magazine/?0003-Win32OLE
http://www.morijp.com/masarl/homepage3.nifty.com/masarl/article/ruby-win32ole.html

Regards,
Masaki S.

Masaki S. wrote:

Hello,

Micke M. wrote:

I also tried to cut up the list in two arrays, and execute the
msi-method two times, but i get same problem as above.

How about calling GC.start in GetProperty method?

def GetProperty(msiPath, property)
GC.start # <- add this line
begin
msiInstaller = Installer.create

Regards,
Masaki S.

Hi Masaki

A big thanks fore you help, the GC.start solved the problem.

Do you know any good article how to structure ruby-programs ?

// Micke