win32ole - windowsinstaller.installer method

M

Micke Micke

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
 
M

Masaki Suketa

Hello,

Micke said:
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

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 Suketa
 
M

Micke Micke

Masaki said:
Hello,



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 Suketa

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
 
M

Masaki Suketa

Hello,

Micke said:
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.

How about calling GC.start in GetProperty method?

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

Regards,
Masaki Suketa
 
M

Micke Micke

Masaki said:
Hello,



How about calling GC.start in GetProperty method?

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

Regards,
Masaki Suketa

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top