wixgem 0.47.0 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 678485dbc753adc3b92f0e69a927797626abd3f0
4
- data.tar.gz: 435a5a32bd415d89ee0616a844dd3de646bb8bdc
3
+ metadata.gz: 6cc49605457da97d26245c8d8d141bae95d2ea6f
4
+ data.tar.gz: a486cfdb2dfe6f9e7434328ad11c0d587db481b9
5
5
  SHA512:
6
- metadata.gz: a924e211519f31188cc3763e1f1f0ba0dc063aba8b4697863a9fe58f38e6c0ce5c1f98d2c247c56e62e61b3fe6968d99213795eef6c193d00b8207728697b297
7
- data.tar.gz: 96071d10cabcf0a4f536ecaca035de5dd184fd9185492eb0e03f7e56d4067b9e6f241b178fb938421f367ae47a1459ae767f3484397e93f590cac3e5779e3060
6
+ metadata.gz: f64e9cb3bb1d1092914d3f701889df6cafed615b5aa12d9fed383e23ea0f7881f3574d7ee0c5f159f54614d54b3689d443287751ffcc62bf7bfea0b82e2e062a
7
+ data.tar.gz: 243e5b1b0526550ba457c63b3228ed236bbde014dd33b0396cd979b57f167be81b090a13ee5df7187f82b20815d4f32058b66bbb411c345c57c8ed27dc0b957f
@@ -69,7 +69,6 @@ class WindowsInstaller
69
69
  raise "Failed to find product code for product: #{product_name}"
70
70
  end
71
71
 
72
- private
73
72
  def self.product_info(installer, code)
74
73
  raise 'Windows installer cannot be nil' if(installer.nil?)
75
74
  hash = Hash.new
@@ -96,13 +95,13 @@ class WindowsInstaller
96
95
  return hash
97
96
  end
98
97
 
99
- public
100
98
  def self.dump_info(product_name)
101
99
  installer = WIN32OLE.new('WindowsInstaller.Installer')
102
100
  properties = product_info(installer, product_code_from_product_name(product_name, installer))
103
101
  properties.each { |id, value| puts "#{id}: #{value}" }
104
102
  end
105
103
 
104
+ private
106
105
  def self.msi_records(msi_file)
107
106
  records = {}
108
107
 
@@ -164,7 +163,7 @@ class WindowsInstaller
164
163
  end
165
164
 
166
165
  def self.execute(cmd)
167
- command = Wixgem::Command.new(cmd)
166
+ command = Wixgem::Command.new(cmd, { quiet: true } )
168
167
  #command[:debug] = true
169
168
  command.execute
170
169
  end
data/lib/command.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'open3'
2
- require 'hash'
3
2
 
4
3
  module Wixgem
5
4
 
data/lib/wixgem.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  require 'fileutils'
2
- require 'SecureRandom'
3
2
  require 'tmpdir.rb'
4
3
  require 'rexml/document'
5
4
  require "#{File.dirname(__FILE__)}/command.rb"
5
+ require 'SecureRandom'
6
6
 
7
7
  module Wixgem
8
8
 
@@ -29,12 +29,12 @@ class Wix
29
29
 
30
30
  def self.make_mergemodule(output_file, input)
31
31
  gem_dir = File.dirname(__FILE__)
32
- apply_wix_template(output_file, input)
32
+ create_package(output_file, input)
33
33
  end
34
34
 
35
35
  def self.make_installation(output_file, input)
36
36
  gem_dir = File.dirname(__FILE__)
37
- apply_wix_template(output_file, input)
37
+ create_package(output_file, input)
38
38
  end
39
39
 
40
40
  private
@@ -127,8 +127,33 @@ class Wix
127
127
  return xml_doc
128
128
  end
129
129
 
130
+ def self.modify_file_path(input, file)
131
+ return file unless(input.kind_of?(Hash) && input.has_key?(:modify_file_paths))
132
+
133
+ modify_paths = input[:modify_file_paths]
134
+ modify_paths.each { |regex, replacement_string| file = file.gsub(regex, replacement_string) }
135
+
136
+ return file
137
+ end
138
+
139
+ def self.files(input)
140
+ files = input
141
+ files = input[:files] if(input.kind_of?(Hash))
142
+
143
+ files.each { |file| files.delete(file) if(File.directory?(file)) }
144
+
145
+ return files
146
+ end
147
+
148
+ def self.ignore_files(input)
149
+ files = []
150
+ files = input[:ignore_files] if(input.kind_of?(Hash) && input.has_key?(:ignore_files))
151
+
152
+ return files
153
+ end
154
+
130
155
  def self.copy_install_files(directory, input)
131
- files = input[:files]
156
+ files = files(input)
132
157
  raise 'No files were given to wixgem' if(files.length == 0)
133
158
 
134
159
  missing_files = []
@@ -179,24 +204,119 @@ class Wix
179
204
  end
180
205
  end
181
206
 
182
- def self.create_wxs_file(wxs_file, input, ext)
183
- template_option = "-template product"
184
- template_option = "-template module" unless(ext == ".msi")
185
-
186
- cmd = "\"#{install_path}/bin/heat.exe\" dir . #{template_option} -cg InstallionFiles -gg -nologo -srd -o \"#{wxs_file}\""
187
- cmd = cmd.gsub(/-srd/, '-svb6 -srd') if(input.has_key?(:has_vb6_files) && input[:has_vb6_files])
207
+ def self.log_wix_output(cmd)
208
+ return unless(@debug && !@logger.nil?)
209
+
210
+ @logger << "----------------------------------------------------------------------------"
211
+ @logger << cmd
212
+
213
+ if(!cmd[:output].empty?)
214
+ @logger << "--------------------------- std output -----------------------------------"
215
+ @logger << cmd[:output]
216
+ end
217
+
218
+ if(!cmd[:error].empty?)
219
+ @logger << "--------------------------- std error ------------------------------------"
220
+ @logger << cmd[:error]
221
+ end
222
+ end
223
+
224
+ def self.modify_heat_commandline(input, cmd)
225
+ cmd = cmd.gsub(/-srd/, '-svb6 -srd') if(input.has_key?(:has_vb6_files) && input[:has_vb6_files])
188
226
  cmd = cmd.gsub(/-srd/, '-sreg -srd') if(input.has_key?(:suppress_registry_harvesting) && input[:suppress_registry_harvesting])
189
227
  cmd = cmd.gsub(/-srd/, '-scom -srd') if(input.has_key?(:suppress_COM_elements) && input[:suppress_COM_elements])
190
-
191
- heat_cmd = Command.new(cmd, { quiet: true })
192
- @logger << "command: #{heat_cmd[:command]}" if(@debug && !@logger.nil?)
228
+ return cmd
229
+ end
193
230
 
231
+ def self.execute_heat(input, cmd_line_options)
232
+ heat_cmd = Command.new("\"#{install_path}/bin/heat.exe\" #{modify_heat_commandline(input, cmd_line_options)}", { quiet: true })
194
233
  heat_cmd.execute
195
- if(@debug && !heat_cmd[:output].empty?)
196
- @logger << "--------------------------- Heat output -----------------------------------" unless(@logger.nil?)
197
- @logger << heat_cmd[:output] unless(@logger.nil?)
234
+ log_wix_output(heat_cmd)
235
+ end
236
+
237
+ def self.execute_heat_file(wxs_file, input, template_option)
238
+ install_files = files(input)
239
+ modified_paths = []
240
+ install_files.each { |file| modified_paths << modify_file_path(input, file) }
241
+ install_files = modified_paths
242
+
243
+ install_ignore_files = ignore_files(input)
244
+ modified_paths = []
245
+ install_ignore_files.each { |file| modified_paths << modify_file_path(input, file) }
246
+ install_ignore_files = modified_paths
247
+
248
+ install_files.reject! { |f| install_ignore_files.include?(f) }
249
+
250
+ directory_fragments = {}
251
+ wxs_files = {}
252
+ install_files.each do |file|
253
+ windows_path = file.gsub(/\//, '\\')
254
+
255
+ filename = wxs_file
256
+ if(install_files.index(file) == 0)
257
+ execute_heat(input, "file \"#{windows_path}\" #{template_option} -cg InstallionFiles -gg -nologo -srd -o \"#{filename}\"")
258
+ else
259
+ filename = File.basename(wxs_file).gsub('.wxs', "-#{wxs_files.length}.wxs")
260
+ execute_heat(input, "file \"#{windows_path}\" -template fragment -gg -nologo -srd -o \"#{filename}\"")
261
+ wxs_files[file] = filename
262
+ end
263
+
264
+ directory_fragments[File.dirname(file)] = "dir#{SecureRandom.uuid.gsub(/-/,'')}"
265
+ xml_doc = REXML::Document.new(File.read(filename))
266
+ file_elements = REXML::XPath.match(xml_doc, '//Wix/Fragment/DirectoryRef/Component/File')
267
+ file_elements[0].attributes['Source'] = "SourceDir\\#{file.gsub(/\//,'\\')}" if(file_elements.length == 1)
268
+ 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
269
+ File.open(filename, 'w') { |f| f.puts(xml_doc.to_s) }
270
+ end
271
+ directory_fragments['.'] = 'TARGETDIR'
272
+
273
+ xml_doc = REXML::Document.new(File.read(wxs_file))
274
+
275
+ wix_elements = REXML::XPath.match(xml_doc, '//Wix')
276
+ raise "Invalid wxs file: #{wxs_file}" unless(wix_elements.length == 1)
277
+
278
+ directory_fragments.each do |key, id|
279
+ if(key != '.')
280
+ fragment_element = wix_elements[0].add_element 'Fragment'
281
+ directory_ref_element = fragment_element.add_element 'DirectoryRef', { 'Id' => directory_fragments[File.dirname(key)] }
282
+ directory_ref_element.add_element 'Directory', { 'Id' => id, 'Name' => File.basename(key) }
283
+ end
284
+ end
285
+
286
+ component_group_element = REXML::XPath.match(xml_doc, '//Wix/Fragment/ComponentGroup')
287
+ raise "Failed to create installation package for file: #{wxs_file}" unless(component_group_element.length == 1)
288
+
289
+ wxs_files.each do |file, filename|
290
+ xml_fragment_doc = REXML::Document.new(File.read(filename))
291
+ component_elements = REXML::XPath.match(xml_fragment_doc, '//Wix/Fragment/DirectoryRef/Component')
292
+
293
+ component_elements.each do |component_element|
294
+ component_element.attributes['Id'] = "cmp#{SecureRandom.uuid.gsub(/-/,'')}" # Assigning new Id, because the id is somehow generated from the filename. So it is possible for heat to generate duplicate id's
295
+ component_element = component_group_element[0].add_element component_element, { 'Directory' => directory_fragments[File.dirname(file)] }
296
+ end
198
297
  end
199
-
298
+
299
+ formatter = REXML::Formatters::Pretty.new(2)
300
+ formatter.compact = true # This is the magic line that does what you need!
301
+ xml_text=''
302
+ formatter.write(xml_doc, xml_text)
303
+ File.open(wxs_file, 'w') { |f| f.puts xml_text }
304
+ end
305
+
306
+ def self.execute_heat_dir(wxs_file, input, template_option)
307
+ execute_heat(input,"dir . #{template_option} -cg InstallionFiles -gg -nologo -srd -o \"#{wxs_file}\"")
308
+ end
309
+
310
+ def self.create_wxs_file(wxs_file, input, ext)
311
+ template_option = "-template product"
312
+ template_option = "-template module" unless(ext == ".msi")
313
+
314
+ if(input.has_key?(:ignore_files))
315
+ execute_heat_file(wxs_file, input, template_option)
316
+ else
317
+ execute_heat_dir(wxs_file, input, template_option)
318
+ end
319
+
200
320
  product_name = File.basename(wxs_file, '.wxs')
201
321
  product_name = input[:product_name] if(input.has_key?(:product_name))
202
322
 
@@ -248,25 +368,15 @@ class Wix
248
368
  wixobj_file = "#{File.basename(wxs_file,'.wxs')}.wixobj"
249
369
 
250
370
  candle_cmd = Command.new("\"#{install_path}/bin/candle.exe\" -out \"#{wixobj_file}\" \"#{wxs_file}\"", { quiet: true })
251
- @logger << "command: #{candle_cmd[:command]}" if(@debug && !@logger.nil?)
252
-
253
371
  candle_cmd.execute
254
- if(@debug && !candle_cmd[:output].empty?)
255
- @logger << "--------------------------- Candle output -----------------------------------" unless(@logger.nil?)
256
- @logger << candle_cmd[:output] unless(@logger.nil?)
257
- end
372
+ log_wix_output(candle_cmd)
258
373
 
259
374
  light_cmd = Command.new("\"#{install_path}/bin/light.exe\" -nologo -out \"#{output}\" \"#{wixobj_file}\"", { quiet: true })
260
- @logger << "command: #{light_cmd[:command]}" if(@debug && !@logger.nil?)
261
-
262
375
  light_cmd.execute
263
- if(@debug && !light_cmd[:output].empty?)
264
- @logger << "--------------------------- Light output -----------------------------------" unless(@logger.nil?)
265
- @logger << light_cmd[:output] unless(@logger.nil?)
266
- end
376
+ log_wix_output(light_cmd)
267
377
  end
268
378
 
269
- def self.apply_wix_template(output, input)
379
+ def self.create_package(output, input)
270
380
  raise 'WIX path is not set!' if(install_path.nil?)
271
381
  input = { files: input } unless(input.kind_of?(Hash))
272
382
  @debug = input[:debug] if(!@debug && input.has_key?(:debug))
@@ -281,6 +391,9 @@ class Wix
281
391
 
282
392
  output_absolute_path = File.absolute_path(output)
283
393
 
394
+ #dir = './tmp_dir'
395
+ #FileUtils.rm_rf(dir) if(Dir.exists?(dir))
396
+ #FileUtils.mkdir(dir)
284
397
  Dir.mktmpdir do |dir|
285
398
  copy_install_files(dir, input)
286
399
 
metadata CHANGED
@@ -1,69 +1,69 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wixgem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.47.0
4
+ version: 0.48.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-01-31 00:00:00.000000000 Z
11
+ date: 2015-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ~>
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: dev
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ~>
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  description: Simple Ruby interface to facilitate creating and compiling windows installation
@@ -81,7 +81,6 @@ files:
81
81
  - example/install_files/file1.txt
82
82
  - example/rakefile.rb
83
83
  - lib/WindowsInstaller.rb
84
- - lib/WindowsInstaller_hold.rb
85
84
  - lib/command.rb
86
85
  - lib/wixgem.rb
87
86
  homepage: http://rubygems.org/gems/wixgem
@@ -94,17 +93,17 @@ require_paths:
94
93
  - lib
95
94
  required_ruby_version: !ruby/object:Gem::Requirement
96
95
  requirements:
97
- - - ">="
96
+ - - '>='
98
97
  - !ruby/object:Gem::Version
99
98
  version: 1.9.1
100
99
  required_rubygems_version: !ruby/object:Gem::Requirement
101
100
  requirements:
102
- - - ">="
101
+ - - '>='
103
102
  - !ruby/object:Gem::Version
104
103
  version: '0'
105
104
  requirements: []
106
105
  rubyforge_project:
107
- rubygems_version: 2.2.2
106
+ rubygems_version: 2.2.0
108
107
  signing_key:
109
108
  specification_version: 4
110
109
  summary: Simple Ruby interface to facilitate working with Wix Toolset
@@ -1,156 +0,0 @@
1
- require 'win32ole'
2
- require 'dev_tasks'
3
-
4
- module Wixgem
5
-
6
- class WindowsInstaller
7
- def self.install(msi_file)
8
- msi_file = msi_file.gsub(/\//, '\\')
9
- raise "#{msi_file} is already installed" if(WindowsInstaller.installed?(msi_file))
10
- execute("msiexec.exe /i #{msi_file}")
11
- end
12
-
13
- def self.uninstall(msi_file)
14
- raise "#{msi_file} does not exist!" unless(File.exists?(msi_file))
15
-
16
- info = msi_properties(installer, msi_file)
17
- uninstall_product_code(info['ProductCode'])
18
- end
19
-
20
- def self.uninstall_product_name(product_name)
21
- raise "#{product_name} is not installed" unless(product_name_installed?(product_name))
22
- uninstall_product_code(product_code_from_product_name(product_name))
23
- end
24
-
25
- def self.uninstall_product_code(product_code)
26
- raise "#{product_code} is not installed" unless(product_code_installed?(product_code))
27
- execute("msiexec.exe /quiet /x #{product_code}")
28
- end
29
-
30
- def self.msi_installed?(msi_file)
31
- info = msi_properties(msi_file)
32
- return product_code_installed?(info['ProductCode'])
33
- end
34
-
35
- def self.product_name_installed?(product_name)
36
- installer = WIN32OLE.new('WindowsInstaller.Installer')
37
- installer.Products.each { |prod_code|
38
- name = installer.ProductInfo(prod_code, "ProductName")
39
- return true if (product_name == name)
40
- }
41
- return false
42
- end
43
-
44
- def self.product_code_installed?(product_code)
45
- installer = WIN32OLE.new('WindowsInstaller.Installer')
46
- installer.Products.each { |installed_product_code| return true if (product_code == installed_product_code) }
47
- return false
48
- end
49
-
50
- def self.product_name_installed_version(product_name)
51
- installer = WIN32OLE.new('WindowsInstaller.Installer')
52
- info = product_info(installer, product_code_from_product_name(product_name, installer))
53
- return info['VersionString']
54
- end
55
-
56
- private
57
- def self.product_code_from_msi(msi_file, installer = nil)
58
- msi_info = msi_properties(msi_file)
59
- return msi_info['ProductCode']
60
- end
61
-
62
- def self.product_code_from_product_name(product_name, installer = nil)
63
- installer = WIN32OLE.new('WindowsInstaller.Installer') if(installer.nil?)
64
- installer.Products.each { |prod_code|
65
- name = installer.ProductInfo(prod_code, "ProductName")
66
- return prod_code if (product_name == name)
67
- }
68
- raise "Failed to find product code for product: #{product_name}"
69
- end
70
-
71
- def self.product_code_properties(product_code, installer = nil)
72
- installer = WIN32OLE.new('WindowsInstaller.Installer') if(installer.nil?)
73
- hash = Hash.new
74
- # known product keywords found on internet. Would be nice to generate.
75
- %w[Language PackageCode Transforms AssignmentType PackageName InstalledProductName VersionString RegCompany
76
- RegOwner ProductID ProductIcon InstallLocation InstallSource InstallDate Publisher LocalPackage HelpLink
77
- HelpTelephone URLInfoAbout URLUpdateInfo InstanceType].sort.each do |prop|
78
- value = installer.ProductInfo(product_code, prop)
79
- hash[prop] = value unless(value.nil? || value == '')
80
- end
81
- return hash
82
- end
83
-
84
- def self.print_properties(product_name)
85
- installer = WIN32OLE.new('WindowsInstaller.Installer')
86
- properties = product_info(installer, product_code(product_name, installer))
87
- properties.each { |id, value| puts "#{id}: #{value}" }
88
- end
89
-
90
- def self.msi_records(msi_file)
91
- records = {}
92
-
93
- installer = WIN32OLE.new('WindowsInstaller.Installer')
94
- sql_query = "SELECT * FROM `Property`"
95
-
96
- db = installer.OpenDatabase(msi_file, 0)
97
-
98
- view = db.OpenView(sql_query)
99
- view.Execute(nil)
100
-
101
- record = view.Fetch()
102
- return '' if(record == nil)
103
-
104
- while(!record.nil?)
105
- records[record.StringData(1)] = record.StringData(2)
106
- record = view.Fetch()
107
- end
108
- db.ole_free
109
- db = nil
110
- installer.ole_free
111
- installer = nil
112
-
113
- return records
114
- end
115
-
116
- def self.print_msi_records(msi_file)
117
- records = msi_records(msi_file)
118
-
119
- puts "#{msi_file} Properties:"
120
- records.each do |key,value|
121
- puts "#{key}: #{value}"
122
- end
123
- end
124
-
125
- def self.print_product_name(product_name)
126
- installer = WIN32OLE.new('WindowsInstaller.Installer')
127
- # only one session per process!
128
- session = installer.OpenProduct(product_code_from_product_name?(product_name, installer))
129
- db = session.Database
130
-
131
- sql_query = "SELECT * FROM `Property`"
132
- view = db.OpenView(sql_query)
133
- view.Execute(nil)
134
-
135
- record = view.Fetch()
136
- return '' if(record == nil)
137
-
138
- puts "Session Properties:"
139
- while(!record.nil?)
140
- puts "#{record.StringData(1)}: #{record.StringData(2)}"
141
- record = view.Fetch()
142
- end
143
- db.ole_free
144
- db = nil
145
- installer.ole_free
146
- installer = nil
147
- puts ''
148
- end
149
-
150
- def self.execute(cmd)
151
- command = Wixgem::Command.new(cmd)
152
- command.execute
153
- end
154
- end
155
-
156
- end