wixgem 0.66.0 → 0.84.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: afaebdbb46da73a1f4c59778843531925277b5f3
4
- data.tar.gz: f413613c8bb0dd16d830627df93110090fcb85ef
3
+ metadata.gz: 2f903e98ba851435dde4f9a8d002455b1f85341d
4
+ data.tar.gz: 0579fd5fb3f257d9bf7d172cebd9f2463dc55f99
5
5
  SHA512:
6
- metadata.gz: 8f14bb7ea14667795dcea1d69a4662ee050966f5d2fec159dd1a786ae56b8a5df1ab3172f74a964999466668f87b1a1c49c856ac7dbc10f67d43f80865508b60
7
- data.tar.gz: c82ab664e399cbd331cb214872a0f4e93b85de4d8fdd1f90c7af88ee64d97d8c07b8681892b536dfb418464d5ea167a8ffdad90466f72e363497771b32780f97
6
+ metadata.gz: 84d696956ef7cb66ee5e711f7ab24b45aa212ccbbdab504a7ef196bc7714b4c4981844b6c350fb7b18e43af74ff38af5c9f30bfaa4f6106839e6059fe417cfde
7
+ data.tar.gz: 313a096755a6b651314c8e91fbef7dcec01ec7ca616decd5184b5c7bb432733cb4292cb670c60abc1f496a9fcf487c088b49b69804f1502b50ac77f046bc011a
data/README.md CHANGED
@@ -13,8 +13,6 @@ The [WiX Toolset](http://wixtoolset.org) must be installed.
13
13
  ```ruby
14
14
  require 'wixgem'
15
15
 
16
- WIX_TOOLSET_ROOT='path to root of Wix toolset'
17
- Wixgem::Wix.install_path = WIX_TOOLSET_ROOT
18
16
  Wixgen::Wix.make_installation('Product.msi', ['rakefile.rb']])
19
17
 
20
18
  Wixgen::Wix.make_installation('Product.msi', {product_name: 'productname',
@@ -31,8 +29,7 @@ Wixgen::Wix.make_installation('Product.msi', {modify_file_paths: {/\Atest_files\
31
29
  require 'wixgem'
32
30
 
33
31
  WIX_TOOLSET_ROOT='path to root of Wix toolset'
34
- Wixgem::Wix.install_path = WIX_TOOLSET_ROOT
35
- Wixgen::Wix.make_mergemodule('Product.msi', ['rakefile.rb']])
32
+ Wixgen::Wix.make_mergemodule('Product.msm', ['rakefile.rb']])
36
33
 
37
34
  ```
38
35
  An example rakefile.rb is included in the example directory of the gem.
@@ -42,7 +39,7 @@ An example rakefile.rb is included in the example directory of the gem.
42
39
  Wixgem will generate an installation or merge module from an array of files. The Wixgem also supports a
43
40
  small set of optional arguments allowing the developer to customize the generated installation file.
44
41
 
45
- #### Optional input hash arguments
42
+ #### Optional input hash keys
46
43
  * **product_name**: String specifing the product name of the installation.
47
44
  * **manufacturer**: String specifing the manufacturer of the installation.
48
45
  * **version**: String specifing the version of the installation. i.e. '1.1.0.0'
@@ -53,14 +50,32 @@ small set of optional arguments allowing the developer to customize the generate
53
50
  * **modify_file_paths**: A hash of regex objects to replacement string pairs. The regular expressions are applied to
54
51
  the file paths allowing the developer to modify the relative location of the files in the installation.
55
52
  * **has_vb6_files**: Required if installation contains any ocx's or dll's compiled with Visual Basic 6.
56
- * **remove_existing_products**: A boolean value. If the value is true the installation will remove all existing
57
- installations of the product before installing the product.
53
+ * **remove_existing_products**: A boolean value. If the value is true the installation will remove the previous
54
+ installation of the product before installing the product.
58
55
  * **all_users**: String value perUser or perMachine. The default is perUser.
59
- * **suppress_registry_harvesting** Suppress registry harvesting. Can fix the Runtime Error E6034.
56
+ * **suppress_registry_harvesting** Suppress's heat's registry harvesting. Can fix the Runtime Error E6034.
60
57
  * **suppress_COM_elements** Suppress COM elements.
61
58
  * **installer_version** Represents the minimum version of the Windows installer required to install
62
- this package. The default version is 4.0. Other valid versions are 2.0,
63
- 3.0, 3.5, 4.0, 4.5.
59
+ this package. The default version is 4.5. Other valid versions are 2.0,
60
+ 3.0, 3.5, 4.0, 4.5.
61
+ * **requires_netframework** Tests to see if the require netframework version is installed on the machine. The
62
+ associated value specifies the netframework version. The net framework strings can
63
+ be found at http://wixtoolset.org/documentation/manual/v3/customactions/wixnetfxextension.html
64
+ * **binary_table** Key is associated with an array of hashes specifying a file and a binary key to place into the
65
+ binary table.
66
+ * **custom_actions** Key is associated with an array of hashes specifying the arguments for custom actions.
67
+ * ** shortcuts ** Key is associated with a hash specifying arguments to create shortcuts. Currently,
68
+ the only supported shortcut is a desktop shortcut.
69
+ * ** extensions ** Key is associated with a hash to register executables with extensions.
70
+ * ** com_self_register ** Is a key associated with an array of files com dll's/exe's to mark for self
71
+ registration
72
+ * ** ignore_files ** Is a key associated with an array of files to ignore when generating the installation. This
73
+ key is useful for having files copied to the installation folder to generating the installation,
74
+ but not adding the files to the installation. An example of usage is I had a COM dll causing
75
+ heat some problems, so I needed to add the dependency dll's to the install directory so heat could
76
+ harvest the com registry entries, but heat was choking on adding the support dll to the
77
+ installation. Thus, I was able to create a merge module for the COM dll and another merge module for
78
+ the supporting dlls.
64
79
  * **debug**: Boolean value. If debug is true the Product's wxs file and a log file are copied
65
80
  to the same directory as the output msi file. If you are familiar with WiX this can helpful
66
81
  if there is a problem.
Binary file
Binary file
data/lib/admin.rb CHANGED
@@ -8,4 +8,4 @@ def admin?
8
8
  return true if(cmd[:exit_code] == 0)
9
9
  return false
10
10
  end
11
- ENV['HOME'] ||= "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}" if(admin?)
11
+ ENV['HOME'] = ENV['USERPROFILE'] if(admin?)
@@ -0,0 +1,46 @@
1
+ class AssociateExtension
2
+ def initialize(xml_doc)
3
+ @xml_doc = xml_doc
4
+ end
5
+
6
+ def associate(file, extension)
7
+ file = file.gsub(/\//,'\\')
8
+ file_elements = REXML::XPath.match(@xml_doc, "//File[@Source='.\\#{file}']")
9
+ raise "Unable to find file '#{file}' to associate with extension '#{extension}'" if(file_elements.nil? || file_elements.size != 1)
10
+
11
+ file_parent = file_elements[0].parent
12
+
13
+ app=File.basename(file)
14
+ # App Paths to support Start,Run -> "myapp"
15
+ #<RegistryValue Root="HKLM" Key="SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\MyApp.exe" Value="[!MyApp.exe]" Type="string" />
16
+ file_parent.add_element 'RegistryValue', { 'Root' => 'HKLM', 'Key' => "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\#{app}",
17
+ 'Value' => "[INSTALLDIR]#{file}", 'Type' => 'string' }
18
+ #<RegistryValue Root="HKLM" Key="SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\MyApp.exe" Name="Path" Value="[APPLICATIONFOLDER]" Type="string" />
19
+ file_parent.add_element 'RegistryValue', { 'Root' => 'HKLM', 'Key' => "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\#{app}",
20
+ 'Name' => 'Path', 'Value' => '[INSTALLDIR]', 'Type' => 'string' }
21
+
22
+ # Extend to the "open with" list + Win7 jump menu pinning
23
+ #<RegistryValue Root="HKLM" Key="SOFTWARE\Classes\Applications\MyApp.exe\SupportedTypes" Name=".xyz" Value="" Type="string" />
24
+ file_parent.add_element 'RegistryValue', { 'Root' => 'HKLM', 'Key' => "SOFTWARE\\Classes\\Applications\\#{app}\\SupportedTypes",
25
+ 'Name' => extension, 'Value' => '', 'Type' => 'string' }
26
+ #<RegistryValue Root="HKLM" Key="SOFTWARE\Classes\Applications\MyApp.exe\shell\open" Name="FriendlyAppName" Value="!(loc.ApplicationName)" Type="string" />
27
+ file_parent.add_element 'RegistryValue', { 'Root' => 'HKLM', 'Key' => "SOFTWARE\\Classes\\Applications\\#{app}\\shell\\open\\command",
28
+ 'Value' => "[INSTALLDIR]#{file} \"%1\"", 'Type' => 'string' }
29
+
30
+ # MyApp.Document ProgID
31
+ #<RegistryValue Root="HKLM" Key="SOFTWARE\Classes\MyApp.Document" Name="FriendlyTypeName" Value="!(loc.DescXYZ)" Type="string" />
32
+ file_parent.add_element 'RegistryValue', { 'Root' => 'HKLM', 'Key' => "SOFTWARE\\Classes\\#{File.basename(app, '.exe')}.Document",
33
+ 'Name' => 'Aim Project File', 'Value' => "[INSTALLDIR]#{app} \"%1\"", 'Type' => 'string' }
34
+
35
+ #<ProgId Id="MyApp.Document" Description="!(loc.DescXYZ)" Icon="filetype.ico" Advertise="yes">
36
+ # <Extension Id="xyz">
37
+ # <Verb Id="open" Command="!(loc.ExplorerMenuOpenXYZ)" Argument="&quot;%1&quot;" />
38
+ # <MIME Advertise="yes" ContentType="application/xyz" Default="yes" />
39
+ # </Extension>
40
+ #</ProgId>
41
+ prog_id = file_parent.add_element 'ProgId', { 'Id' => "#{File.basename(app, '.exe')}.Document", 'Description' => "Aim project file",
42
+ 'Advertise' => 'yes'}
43
+ ext = prog_id.add_element 'Extension', { 'Id' => extension.gsub(/\./, '') }
44
+ ext.add_element 'Verb', { 'Id' => 'open', 'Command' => "[INSTALLDIR]#{app}", 'Argument' => "\"%1\"" }
45
+ end
46
+ end
@@ -0,0 +1,74 @@
1
+ require 'rexml/document'
2
+ require 'SecureRandom'
3
+
4
+ module Wixgem
5
+
6
+ class CustomAction
7
+ def initialize(xml_doc, input)
8
+ @xml_doc = xml_doc
9
+ @input = input
10
+ end
11
+ def add(custom_action)
12
+ unless(custom_action.key?(:file) || custom_action.key?(:binary_key))
13
+ raise 'Currently, only supported custom actions work with installed executable or binary key'
14
+ end
15
+
16
+ file_key=nil
17
+ if(custom_action.key?(:file))
18
+ install_path = ".\\#{custom_action[:file].gsub(/\//,'\\')}"
19
+ file_elements = REXML::XPath.match(@xml_doc, "//File[@Source='#{install_path}']")
20
+ raise "Unable to locate installation file '#{custom_action[:file]} for custom action'" if(file_elements.nil? || (file_elements.size == 0))
21
+
22
+ file_key = file_elements[0].attributes['Id']
23
+ end
24
+
25
+ id = "ca_#{SecureRandom.uuid.gsub(/-/,'')}"
26
+ id = custom_action[:id] if(custom_action.key?(:id))
27
+
28
+ cmd_line = ''
29
+ cmd_line = custom_action[:exe_command] if(custom_action.key?(:exe_command))
30
+
31
+ impersonate = 'yes'
32
+ impersonate = custom_action[:impersonate] if(custom_action.key?(:impersonate))
33
+
34
+ condition='NOT Installed AND NOT REMOVE'
35
+ condition='1' if(custom_action.key?(:binary_key))
36
+ condition = custom_action[:condition] if(custom_action.key?(:condition))
37
+
38
+ execute='deferred'
39
+ execute = custom_action[:execute] if(custom_action.key?(:execute))
40
+
41
+ ret='check'
42
+ ret = custom_action[:return] if(custom_action.key?(:return))
43
+
44
+ wix_element = REXML::XPath.match(@xml_doc, "/Wix")[0]
45
+ fragment = wix_element.add_element 'Fragment'
46
+
47
+ action = fragment.add_element 'CustomAction', { 'Id' => id, 'ExeCommand' => cmd_line, 'Impersonate' => impersonate, 'Return' => ret, 'HideTarget' => 'no', 'Execute' => execute }
48
+ if(custom_action.key?(:binary_key))
49
+ action.attributes['BinaryKey'] = custom_action[:binary_key]
50
+ else
51
+ action.attributes['FileKey'] = file_key
52
+ end
53
+
54
+ install_execute_sequence = fragment.add_element 'InstallExecuteSequence'
55
+
56
+ custom_action[:before] = 'InstallFinalize' if(!custom_action.key?(:after) && !custom_action.key?(:before))
57
+ if(custom_action.key?(:after))
58
+ action = install_execute_sequence.add_element 'Custom', { 'Action' => id, 'After' => custom_action[:after] }
59
+ action.text = condition
60
+ else
61
+ action = install_execute_sequence.add_element 'Custom', { 'Action' => id, 'Before' => custom_action[:before] }
62
+ action.text = condition
63
+ end
64
+
65
+ control=nil
66
+ elements = REXML::XPath.match(@xml_doc, "/Wix/Product")
67
+ elements = REXML::XPath.match(@xml_doc, "/Wix/Module") if(elements.nil? || elements.size == 0)
68
+
69
+ elements[0].add_element 'CustomActionRef', { 'Id' => id }
70
+
71
+ end
72
+ end
73
+
74
+ end
@@ -0,0 +1,18 @@
1
+ require 'securerandom'
2
+
3
+ #module Wixgem
4
+
5
+ def temp_directory
6
+ tmp_file = "#{ENV['TEMP'].gsub(/\\/,'/')}/#{SecureRandom.hex}"
7
+ FileUtils.mkpath(tmp_file)
8
+ begin
9
+ yield tmp_file
10
+ rescue Exception => e
11
+ raise e
12
+ ensure
13
+ sleep(0.1)
14
+ FileUtils.rm_rf(tmp_file)
15
+ end
16
+ end
17
+
18
+ #end
data/lib/wixgem.rb CHANGED
@@ -1,14 +1,24 @@
1
1
  require 'fileutils'
2
- require 'tmpdir.rb'
3
2
  require 'rexml/document'
4
3
  require 'CMD'
5
4
  require 'SecureRandom'
6
- require_relative('file.rb')
7
- require_relative('shortcut.rb')
5
+
6
+ require_relative 'file.rb'
7
+ require_relative 'shortcut.rb'
8
+ require_relative 'custom_action.rb'
9
+ require_relative 'temp_directory.rb'
10
+ require_relative 'associate_extension.rb'
11
+
12
+ # Editor for wix Files WixEdit: http://http://wixedit.sourceforge.net/
13
+ # Full list of Wix editors : http://robmensching.com/blog/posts/2007/11/20/wix-editors/
14
+ # I guess SharpDevelop is good
15
+
16
+ # Good web page for including the dialog https://www.packtpub.com/books/content/windows-installer-xml-wix-adding-user-interface
8
17
 
9
18
  module Wixgem
10
19
 
11
20
  class Wix
21
+
12
22
  @@install_path = ''
13
23
  @@install_path = ENV['WIX'] unless(ENV['WIX'].nil?)
14
24
 
@@ -50,53 +60,77 @@ class Wix
50
60
  @logger = nil
51
61
  end
52
62
 
63
+ def self.manage_installdir(xml_doc, input)
64
+ product_target_elements = REXML::XPath.match(xml_doc, "/Wix/Product/Directory[@Id='TARGETDIR']")
65
+ if(!product_target_elements.nil? && product_target_elements.size == 1)
66
+ targetdir = product_target_elements[0]
67
+ installdir = targetdir.add_element 'Directory', { 'Id' => 'ProgramFilesFolder' }
68
+ installdir = installdir.add_element 'Directory', { 'Id' => "Dir_#{input[:manufacturer]}", 'Name' => input[:manufacturer] } if(input.has_key?(:manufacturer))
69
+ installdir = installdir.add_element 'Directory', { 'Id' => 'INSTALLDIR', 'Name' => input[:product_name] }
70
+ else
71
+ module_target_elements = REXML::XPath.match(xml_doc, "/Wix/Module/Directory[@Id='TARGETDIR']")
72
+ targetdir = module_target_elements[0]
73
+ targetdir.add_element 'Directory', { 'Id' => 'MergeRedirectFolder', 'FileSource' => '.' }
74
+ end
75
+ return xml_doc
76
+ end
77
+
78
+ def self.manage_netframework(xml_doc, input)
79
+ wix = REXML::XPath.match(xml_doc, "/Wix")[0]
80
+ add_netfx_namespace = false
81
+ if(input.key?(:requires_netframework))
82
+ add_netfx_namespace=true
83
+ fragment = wix.add_element 'Fragment'
84
+ fragment.add_element 'PropertyRef', { 'Id' => input[:requires_netframework] }
85
+ condition = fragment.add_element 'Condition', { 'Message' => "This application requires .NET Framework #{input[:requires_netframework]}. Please install the .NET Framework then run this installer again." }
86
+ condition.text = "<![CDATA[Installed OR #{input[:requires_netframework]}]]>"
87
+ end
88
+
89
+ wix.attributes['xmlns:netfx'] = 'https://schemas.microsoft.com/wix/NetFxExtension' if(add_netfx_namespace)
90
+ return xml_doc
91
+ end
92
+
93
+ def self.manage_ui(xml_doc, input)
94
+ product_elements = REXML::XPath.match(xml_doc, "/Wix/Product")
95
+
96
+ return if(product_elements.nil? || product_elements.size != 1)
97
+ return unless(input.key?(:ui))
98
+
99
+ product = product_elements[0]
100
+ ui = product.add_element 'UIRef', { 'Id' => input[:ui] }
101
+
102
+ return xml_doc
103
+ end
104
+
53
105
  def self.manage_upgrade(xml_doc, input)
54
- product = REXML::XPath.match(xml_doc, '//Wix/Product')
55
- return xml_doc if(product.length == 0)
106
+ products = REXML::XPath.match(xml_doc, '//Wix/Product')
107
+ return xml_doc if(products.length == 0)
56
108
 
57
- if(input.has_key?(:remove_existing_products) && input[:remove_existing_products])
109
+ if(input[:remove_existing_products])
58
110
  raise 'Hash must have a version key if the hash has a :remove_existing_products key' unless(input.has_key?(:version))
59
111
  raise 'Hash must have an upgrade_code key if the hash has a :remove_existing_products key' unless(input.has_key?(:upgrade_code))
60
112
 
61
- upgrade = product[0].add_element 'Upgrade', { 'Id' => input[:upgrade_code] }
62
- upgrade.add_element 'UpgradeVersion', { 'Minimum' => input[:version], 'OnlyDetect'=>'yes', 'Property'=>'NEWERVERSIONDETECTED' }
63
- upgrade.add_element 'UpgradeVersion', { 'Minimum' => '0.0.0', 'IncludeMinimum'=>'yes','Maximum'=>input[:version],'IncludeMaximum'=>'no','Property'=>'OLDERVERSIONBEINGUPGRADED' }
64
-
65
- install_and_execute = REXML::XPath.match(xml_doc, '//Wix/Product/InstallExecuteSequence')
66
- install_and_execute[0].add_element 'RemoveExistingProducts', { 'After'=>'InstallValidate' }
113
+ upgrade = products[0].add_element 'MajorUpgrade', { 'AllowDowngrades' => 'yes' }
67
114
  end
68
115
 
69
116
  return xml_doc
70
117
  end
71
118
 
72
119
  def self.manage_custom_actions(xml_doc, input)
73
- # Example custom action
74
- #<CustomAction Id='comReg' Directory='INSTALLLOCATION' Execute='deferred' Impersonate='no' ExeCommand='"[NETFRAMEWORK40CLIENTINSTALLROOTDIR]regasm.exe" "[INSTALLLOCATION]EAWordImporter.dll" /codebase' Return='check' />
75
-
76
- manufacturer = 'Default Manufacturer'
77
- manufacturer = input[:manufacturer] if(input.has_key?(:manufacturer))
78
-
79
- install_path = '[ProgramFilesFolder][ProductName]'
80
- install_path = "[ProgramFilesFolder][Manufacturer]\\[ProductName]" unless(manufacturer == 'Default Manufacturer')
81
-
82
- product = REXML::XPath.match(xml_doc, '//Wix/Product')
83
- return xml_doc if(product.length == 0)
84
-
85
- product[0].add_element 'SetProperty', { 'Id' => 'ARPINSTALLLOCATION', 'Value' => "#{install_path}", 'After' => 'CostFinalize', 'Sequence' => 'both' }
86
- product[0].add_element 'CustomAction', { 'Id' => 'SetTARGETDIR', 'Property' => 'TARGETDIR', 'Value' => "#{install_path}", 'Execute' => 'firstSequence', 'Return' => 'check'}
120
+ custom_actions = CustomAction.new(xml_doc, input)
121
+ return xml_doc if(input[:custom_actions].nil?)
122
+
123
+ input[:custom_actions].each { |ca| custom_actions.add(ca) } if(input.key?(:custom_actions))
87
124
 
88
- install_execute_sequence = product[0].add_element 'InstallExecuteSequence'
89
- custom_action = install_execute_sequence.add_element 'Custom', { 'Action' => 'SetTARGETDIR', 'Before'=>'CostInitialize' }
125
+ return xml_doc
126
+ end
127
+
128
+ def self.manage_associate_extensions(xml_doc, input)
129
+ return xml_doc unless(input.key?(:extensions))
90
130
 
91
- install_ui_sequence = product[0].add_element 'InstallUISequence'
92
- custom_action = install_ui_sequence.add_element 'Custom', { 'Action' => 'SetTARGETDIR', 'Before'=>'CostInitialize' }
131
+ ext = AssociateExtension.new(xml_doc)
132
+ input[:extensions].each { |exe, file_ext| ext.associate(exe, file_ext) }
93
133
 
94
- admin_execute_sequence = product[0].add_element 'AdminExecuteSequence'
95
- custom_action = admin_execute_sequence.add_element 'Custom', { 'Action' => 'SetTARGETDIR', 'Before'=>'CostInitialize' }
96
-
97
- admin_ui_sequence = product[0].add_element 'AdminUISequence'
98
- custom_action = admin_ui_sequence.add_element 'Custom', { 'Action' => 'SetTARGETDIR', 'Before'=>'CostInitialize' }
99
-
100
134
  return xml_doc
101
135
  end
102
136
 
@@ -112,7 +146,7 @@ class Wix
112
146
  }
113
147
  return xml_doc if(merge_modules.length == 0)
114
148
 
115
- directory_root = REXML::XPath.match(xml_doc, '//Wix/Product/Directory')
149
+ directory_root = REXML::XPath.match(xml_doc, "//Directory[@Id='INSTALLDIR']")
116
150
  if(directory_root.length == 0)
117
151
  module_root = REXML::XPath.match(xml_doc, '//Wix/Module')
118
152
  raise 'Merge modules can not be added to a merge module' unless(module_root.nil?)
@@ -161,6 +195,30 @@ class Wix
161
195
  return xml_doc
162
196
  end
163
197
 
198
+ def self.manage_self_register(xml_doc, input)
199
+ return xml_doc unless(input.has_key?(:com_self_register))
200
+ input[:com_self_register].each do |file|
201
+ file_elements = REXML::XPath.match(xml_doc, "//File[@Source='.\\#{file.gsub(/\//,'\\')}']")
202
+ raise "Unable to find file '#{file}' for self registering" unless (file_elements.length == 1)
203
+ file_elements[0].attributes['SelfRegCost'] = '0'
204
+ end
205
+
206
+ return xml_doc
207
+ end
208
+
209
+ def self.manage_binary_table(xml_doc, input)
210
+ return xml_doc unless(input.has_key?(:binary_table))
211
+ wix_element = REXML::XPath.match(xml_doc, "/Wix")[0]
212
+
213
+ fragment = wix_element.add_element 'Fragment'
214
+ input[:binary_table].each { |entry|
215
+ #puts "File: #{entry[:file]}"
216
+ binary = fragment.add_element 'Binary', { 'Id' => entry[:id], 'SourceFile' => entry[:file] }
217
+ }
218
+
219
+ return xml_doc
220
+ end
221
+
164
222
  def self.modify_file_path(input, file)
165
223
  return file unless(input.kind_of?(Hash) && input.has_key?(:modify_file_paths))
166
224
 
@@ -208,9 +266,17 @@ class Wix
208
266
  max_path = files.max { |a, b| a.length <=> b.length }
209
267
  columen_size = max_path.length + 10
210
268
  end
211
-
269
+
270
+ ingore_files = self.ignore_files(input)
271
+ if(input.has_key?(:ignore_files))
272
+ @logger << "------------------------------------ ignoring files -----------------------------------" unless(@logger.nil?)
273
+ input[:ignore_files].each { |file| @logger << file }
274
+ end
275
+
212
276
  @logger << "------------------------------------ Installation Paths -----------------------------------" unless(@logger.nil?)
213
277
  @logger << "%-#{columen_size}s %s\n" % ['File path', 'Installation Path'] unless(@logger.nil?)
278
+ files.reject! { |f| ingore_files.include?(f) }
279
+
214
280
  files.each do |file|
215
281
  if(File.file?(file))
216
282
  install_path = file
@@ -219,13 +285,7 @@ class Wix
219
285
  end
220
286
  @logger << "%-#{columen_size}s %s\n" % [file, install_path] unless(@logger.nil?)
221
287
  end
222
- end
223
-
224
- if(input.has_key?(:ignore_files))
225
- @logger << "------------------------------------ ignoring files -----------------------------------" unless(@logger.nil?)
226
- input[:ignore_files].each { |file| @logger << file }
227
- end
228
-
288
+ end
229
289
  @logger << "-------------------------------------------------------------------------------------------" unless(@logger.nil?)
230
290
  end
231
291
 
@@ -244,6 +304,11 @@ class Wix
244
304
  end
245
305
  end
246
306
 
307
+ def self.modify_binary_files(input)
308
+ return unless(input.key?(:binary_table))
309
+ input[:binary_table].each { |entry| entry[:file] = File.absolute_path(entry[:file]) }
310
+ end
311
+
247
312
  def self.log_wix_output(cmd)
248
313
  return unless(@debug && !@logger.nil?)
249
314
 
@@ -265,6 +330,11 @@ class Wix
265
330
  cmd = cmd.gsub(/-srd/, '-svb6 -srd') if(input.has_key?(:has_vb6_files) && input[:has_vb6_files])
266
331
  cmd = cmd.gsub(/-srd/, '-sreg -srd') if(input.has_key?(:suppress_registry_harvesting) && input[:suppress_registry_harvesting])
267
332
  cmd = cmd.gsub(/-srd/, '-scom -srd') if(input.has_key?(:suppress_COM_elements) && input[:suppress_COM_elements])
333
+ if(input[:msi?])
334
+ cmd = cmd.gsub(/-srd/, '-dr INSTALLDIR -srd')
335
+ else
336
+ cmd = cmd.gsub(/-srd/, '-dr MergeRedirectFolder -srd')
337
+ end
268
338
  return cmd
269
339
  end
270
340
 
@@ -310,9 +380,10 @@ class Wix
310
380
  file_elements = REXML::XPath.match(xml_doc, '//Wix/Fragment/DirectoryRef/Component/File')
311
381
  file_elements[0].attributes['Source'] = "SourceDir\\#{file.gsub(/\//,'\\')}" if(file_elements.length == 1)
312
382
  file_elements[0].attributes['Id'] = "fil#{SecureRandom.uuid.gsub(/-/,'')}" if(file_elements.length == 1) # Assigning new Id, because the id is somehow generated from the filename. So it is possible for heat to generate duplicate id's
383
+
313
384
  File.open(filename, 'w') { |f| f.puts(xml_doc.to_s) }
314
385
  end
315
- directory_fragments['.'] = 'TARGETDIR'
386
+ directory_fragments['.'] = 'INSTALLDIR'
316
387
 
317
388
  xml_doc = REXML::Document.new(File.read(wxs_file))
318
389
 
@@ -362,6 +433,7 @@ class Wix
362
433
  end
363
434
 
364
435
  product_name = File.basename(wxs_file, '.wxs')
436
+ input[:product_name] = product_name unless(input.has_key?(:product_name))
365
437
  product_name = input[:product_name] if(input.has_key?(:product_name))
366
438
 
367
439
  manufacturer = 'Not Set'
@@ -375,6 +447,9 @@ class Wix
375
447
 
376
448
  upgrade_code = ''
377
449
  upgrade_code = input[:upgrade_code] if(input.has_key?(:upgrade_code))
450
+
451
+ install_path = '[ProgramFilesFolder][ProductName]'
452
+ install_path = "[ProgramFilesFolder][Manufacturer]\\[ProductName]" unless(manufacturer == 'Not Set')
378
453
 
379
454
  wxs_text = File.read(wxs_file)
380
455
 
@@ -388,36 +463,50 @@ class Wix
388
463
  wxs_text = wxs_text.gsub(/Product Id=\"[^\"]+\"/) { |s| s = "Product Id=\"#{product_code}\"" } unless(product_code.empty?)
389
464
  wxs_text = wxs_text.gsub(/UpgradeCode=\"[^\"]+\"/) { |s| s = "UpgradeCode=\"#{upgrade_code}\"" } unless(upgrade_code.empty?)
390
465
 
466
+ File.open(wxs_file, 'w') { |f| f.write(wxs_text) }
467
+
391
468
  xml_doc = REXML::Document.new(wxs_text)
469
+ products = REXML::XPath.match(xml_doc, "/Wix/Product")
470
+ products.each do |product|
471
+ product.add_element 'SetProperty', { 'Id' => 'ARPINSTALLLOCATION', 'Value' => "#{install_path}", 'After' => 'CostFinalize', 'Sequence' => 'both' }
472
+ end
473
+
392
474
  packages = REXML::XPath.match(xml_doc, '//Wix/Product/Package')
393
475
  packages.each do |package|
394
476
  package.add_attribute('InstallScope', 'perMachine') if(input.has_key?(:all_users))
477
+ package.add_attribute('InstallScope', input[:install_scope]) if(input.has_key?(:install_scope))
395
478
  package.attributes['InstallerVersion'] = 450
396
479
  package.attributes['InstallerVersion'] = (input[:installer_version]*100).to_i if(input.has_key?(:installer_version))
480
+ package.attributes['InstallPrivileges']= input[:install_priviledges] if(input.has_key?(:install_priviledges))
397
481
  end
398
482
 
483
+ xml_doc = manage_installdir(xml_doc, input)
484
+ xml_doc = manage_netframework(xml_doc, input)
485
+ #xml_doc = manage_ui(xml_doc, input)
399
486
  xml_doc = manage_custom_actions(xml_doc, input)
400
487
  xml_doc = manage_upgrade(xml_doc,input)
401
488
  xml_doc = manage_msm_files(xml_doc)
402
489
  xml_doc = manage_read_only_files(xml_doc,input)
403
490
  xml_doc = manage_shortcuts(xml_doc, input)
404
-
405
- File.open(wxs_file, 'w') { |f| f.puts(xml_doc.to_s) }
406
- #formatter = REXML::Formatters::Pretty.new(2)
407
- #formatter.compact = true # This is the magic line that does what you need!
408
- #wxs_text = ''
409
- #formatter.write(xml, wxs_text)
410
- #File.open(wxs_file, 'w') { |f| f.puts(wxs_text) }
491
+ xml_doc = manage_self_register(xml_doc, input)
492
+ xml_doc = manage_binary_table(xml_doc, input)
493
+ xml_doc = manage_associate_extensions(xml_doc, input)
494
+
495
+ formatter = REXML::Formatters::Pretty.new(2)
496
+ formatter.compact = true
497
+ File.open(wxs_file, 'w') { |f| formatter.write(xml_doc, f) }
411
498
  end
412
499
 
413
- def self.create_output(wxs_file, output)
500
+ def self.create_output(wxs_file, input, output)
414
501
  wixobj_file = "#{File.basename(wxs_file,'.wxs')}.wixobj"
415
502
 
416
503
  candle_cmd = CMD.new("\"#{install_path}/bin/candle.exe\" -out \"#{wixobj_file}\" \"#{wxs_file}\"", { quiet: true })
417
504
  candle_cmd.execute
418
505
  log_wix_output(candle_cmd)
419
506
 
420
- light_cmd = CMD.new("\"#{install_path}/bin/light.exe\" -nologo -out \"#{output}\" \"#{wixobj_file}\"", { quiet: true })
507
+ cmd_args = "-nologo -out \"#{output}\" \"#{wixobj_file}\""
508
+ cmd_args = "-ext WixUIExtension -cultures:en-us #{cmd_args}" if(input.key?(:ui))
509
+ light_cmd = CMD.new("\"#{install_path}/bin/light.exe\" #{cmd_args}", { quiet: true })
421
510
  light_cmd.execute
422
511
  log_wix_output(light_cmd)
423
512
  end
@@ -434,7 +523,6 @@ class Wix
434
523
  verify_input_keys(input)
435
524
 
436
525
  @debug = input[:debug] if(!@debug && input.has_key?(:debug))
437
-
438
526
  start_logger if(@debug)
439
527
 
440
528
  FileUtils.mkpath(File.dirname(output)) unless(Dir.exists?(File.dirname(output)))
@@ -445,21 +533,21 @@ class Wix
445
533
 
446
534
  output_absolute_path = File.absolute_path(output)
447
535
  input[:original_pwd] = Dir.pwd
536
+ input[:msi?] = output.include?('.msi')
537
+
538
+ modify_binary_files(input)
448
539
 
449
- #dir = './tmp_dir'
450
- #FileUtils.rm_rf(dir) if(Dir.exists?(dir))
451
- #FileUtils.mkdir(dir)
452
- Dir.mktmpdir do |dir|
540
+ temp_directory do |dir|
453
541
  wxs_file = "#{basename}.wxs"
454
542
  begin
455
543
  copy_install_files(dir, input)
456
544
 
457
545
  Dir.chdir(dir) do |current_dir|
458
546
  create_wxs_file(wxs_file, input, ext)
459
- create_output(wxs_file, output_absolute_path)
547
+ create_output(wxs_file, input, output_absolute_path)
460
548
  end
461
549
  rescue Exception => e
462
- raise "Wixgem exception: #{e}"
550
+ raise e
463
551
  ensure
464
552
  FileUtils.cp("#{dir}/#{wxs_file}", "#{output_absolute_path}.wxs") if(File.exists?("#{dir}/#{wxs_file}") && @debug)
465
553
  File.open("#{output_absolute_path}.log", 'w') { |f| f.puts(@logger) } if(@debug &!@logger.nil?)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wixgem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.66.0
4
+ version: 0.84.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Marshall
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-14 00:00:00.000000000 Z
11
+ date: 2015-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: ocra
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
97
111
  description: Simple Ruby interface to facilitate creating and compiling windows installation
98
112
  files with the Wix Toolset.
99
113
  email: KCCKSMarshall@gmail.com
@@ -103,12 +117,17 @@ extra_rdoc_files: []
103
117
  files:
104
118
  - LICENSE
105
119
  - README.md
120
+ - example/example.msi
121
+ - example/example.msm
106
122
  - example/install_files/directory/file2.txt
107
123
  - example/install_files/file1.txt
108
124
  - example/rakefile.rb
109
125
  - lib/admin.rb
126
+ - lib/associate_extension.rb
127
+ - lib/custom_action.rb
110
128
  - lib/file.rb
111
129
  - lib/shortcut.rb
130
+ - lib/temp_directory.rb
112
131
  - lib/wixgem.rb
113
132
  homepage: http://rubygems.org/gems/wixgem
114
133
  licenses: