I am on a project where I have to create an msi package from Ubuntu for Windows.
I managed to create an msi file from Ubuntu rgace to "msitools" which uses wxs files (it's like an xml file) to configure the package.
Example of an wxs file which take one file (FoobarAppl10.exe).
<?xml version='1.0' encoding='windows-1252'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
<Product Name='Foobar 1.0' Id='ABCDDCBA-86C7-4D14-AEC0-86416A69ABDE' UpgradeCode='ABCDDCBA-7349-453F-94F6-BCB5110BA4FD'
Language='1033' Codepage='1252' Version='1.0.0' Manufacturer='Acme Ltd.'>
<Package Id='*' Keywords='Installer' Description="Acme's Foobar 1.0 Installer"
Comments='Foobar is a registered trademark of Acme Ltd.' Manufacturer='Acme Ltd.'
InstallerVersion='100' Languages='1033' Compressed='yes' SummaryCodepage='1252' />
<Media Id='1' Cabinet='Sample.cab' EmbedCab='yes' DiskPrompt="CD-ROM #1" />
<Property Id='DiskPrompt' Value="Acme's Foobar 1.0 Installation [1]" />
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='ProgramFilesFolder' Name='PFiles'>
<Directory Id='Acme' Name='Acme'>
<Directory Id='INSTALLDIR' Name='Foobar 1.0'>
<Component Id='MainExecutable' Guid='ABCDDCBA-83F1-4F22-985B-FDB3C8ABD471'>
<File Id='FoobarEXE' Name='FoobarAppl10.exe' DiskId='1' Source='FoobarAppl10.exe' KeyPath='yes'/>
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
<Feature Id='Complete' Level='1'>
<ComponentRef Id='MainExecutable' />
</Feature>
</Product>
</Wix>
Now my problem is to create a tree structure generator with ruby so that my wxs file packages all the files of my project without write it manually.
I write a code that can create a xml file and print my brute code in this:
$ ls
build.wxs foobarAppl10.exe generator_xml.rb
require 'nokogiri'
out_file = File.new("generated.wxs", "w")
builder = Nokogiri::XML::Builder.new(:encoding => 'windows-1252') { |xml|
xml.Wix('xmlns' => 'http://schemas.microsoft.com/wix/2006/wi') do
xml.Product('Name' => 'Foobar 1.0', 'Id' => 'ABCDDCBA-86C7-4D14-AEC0-86416A69ABDE',
'UpgradeCode' =>'ABCDDCBA-7349-453F-94F6-BCB5110BA4FD', 'Language' => '1033', 'Codepage' => '1252',
'Version' => '1.0.0', 'Manufacturer' => 'Acme Ltd.') do
xml.Package('Id' => '*', 'Keywords' => 'Installer', 'Description' => "Acme's Foobar 1.0 Installer",
'Comments' => 'Foobar is a registered trademark of Acme Ltd.', 'Manufacturer' => 'Acme Ltd.',
'InstallerVersion' => '100', 'Languages' => '1033', 'Compressed' => 'yes', 'SummaryCodepage' => '1252')
xml.Media('Id' => '1', 'Cabinet' => 'Sample.cab', 'EmbedCab' => 'yes', 'DiskPrompt' => "CD-ROM #1")
xml.Property('Id' => 'DiskPromt', 'Value' => "Acme's Foobar 1.0 Installation [1]")
xml.Directory('Id' => 'TARGETDIR', 'Name' =>'SourceDir') do
xml.Directory('Id' => 'ProgramFilesFolder', 'Name' =>'PFiles') do
xml.Directory('Id' => 'Acme', 'Name' =>'Acme') do
xml.Directory('Id' => 'INSTALLDIR', 'Name' =>'Foobar 1.0') do
xml.Component('Id' => 'MainExecutable', 'Guid' => 'ABCDDCBA-83F1-4F22-985B-FDB3C8ABD471') do
xml.File('Id' => 'FoobarEXE', 'Name' => 'FoobarAppl10.exe', 'DiskId' => '1', 'Source' => 'FoobarAppl10.exe', 'KeyPath' =>'yes')
end
end
end
end
end
xml.Feature('Id' => 'Complete', 'Level' => '1') do
xml.Component('Id' => 'MainExecutable')
end
end
end
}
puts builder.to_xml
out_file.puts(builder.to_xml)
out_file.close
If someone know how to generate code from a tree structure it will help me a lot!
It sounds like you are want to create an XML structure that mimics a directory structure? Here is a recursive function that should do most of what you want, or at lease serve as a good staring point. The puts
statements can be removed or replaced with any other actions that you need to perform when you find a directory or file.
require 'nokogiri'
def process_dir(current_path, xml)
return if !File.directory?(current_path) || Dir.empty?(current_path)
directory_name = current_path.split("/").last
# insert code here to compute other attributes for Directory node
xml.Directory(Name: directory_name) do
Dir.children(current_path).each do |entry|
file = "#{current_path}/#{entry}"
if !File.directory?(file)
# insert code here to compute other attributes for File node
xml.File(Name: entry)
puts "found file named #{entry} at #{current_path}"
else
puts "found directory named #{current_path}/#{entry}"
process_dir("#{current_path}/#{entry}", xml)
end
end
end
end
builder = Nokogiri::XML::Builder.new do |xml|
xml.root { process_dir(".", xml) }
end
pp builder.to_xml