0

我在一个项目中,我必须从 Ubuntu for Windows 创建一个 msi 包。

我设法创建了一个从 Ubuntu rgace 到“msitools”的 msi 文件,它使用 wxs 文件(它就像一个 xml 文件)来配置包。

wxs 文件的示例,它采用一个文件 (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>

现在我的问题是用ruby创建一个树结构生成器,这样我的wxs文件就可以打包我项目的所有文件,而无需手动编写。

我编写了一个代码,可以创建一个 xml 文件并在此打印我的蛮力代码:

文件夹

$ 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

如果有人知道如何从树结构生成代码,那将对我有很大帮助!

4

1 回答 1

0

听起来您想创建一个模仿目录结构的 XML 结构?这是一个递归函数,它应该可以完成您想要的大部分操作,或者至少可以作为一个很好的起点。当您找到目录或文件时,这些puts语句可以被删除或替换为您需要执行的任何其他操作。

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
于 2022-02-27T22:44:41.243 回答