wixgem 0.93.0 → 0.99.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 +4 -4
- data/example/example.msi +0 -0
- data/example/example.msm +0 -0
- data/lib/custom_action.rb +49 -54
- data/lib/file.rb +3 -3
- data/lib/service.rb +86 -0
- data/lib/wixgem.rb +321 -309
- metadata +19 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad604c669315ebac1c9b8b70a76ee956e65b8b3aeec95e92ad952f3b8e185bb7
|
4
|
+
data.tar.gz: 111ab3b46b72aee343a638918dbfce3e6498e5309fe6ceeaa46551f2e1560c5c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b74e4e894a2087ed6f89f8d0ee0b9b5dc03a95f124c7ac9535f40e9847ff7b3cb19cb22deb31329c4e3c68978aa63c94f114f5349cdd9a1e7e2531e0a289a28
|
7
|
+
data.tar.gz: 9da8e9369d947d367d2a704a6aac16ab7f37a96bf790927ef80c77805cff74ff48acf56c682b3b9807f11f142bb9949148ad57d3cddcd3a51ae3da55c8837742
|
data/example/example.msi
ADDED
Binary file
|
data/example/example.msm
CHANGED
Binary file
|
data/lib/custom_action.rb
CHANGED
@@ -9,78 +9,73 @@ class CustomAction
|
|
9
9
|
@input = input
|
10
10
|
end
|
11
11
|
def add(custom_action)
|
12
|
-
unless(custom_action.key?(:file) || custom_action.key?(:binary_key) || custom_action.key?(:property))
|
13
|
-
raise 'Currently, only supported custom actions work with installed executable, binary key, or
|
14
|
-
|
12
|
+
unless(custom_action.key?(:file) || custom_action.key?(:binary_key) || custom_action.key?(:property) || custom_action.key?(:directory))
|
13
|
+
raise 'Currently, only supported custom actions work with installed executable, binary key, property, or directory'
|
14
|
+
end
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
file_key=nil
|
17
|
+
if(custom_action.key?(:file))
|
18
18
|
install_path = ".\\#{custom_action[:file].gsub(/\//,'\\')}"
|
19
|
-
|
20
|
-
|
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
21
|
|
22
|
-
|
23
|
-
|
22
|
+
file_key = file_elements[0].attributes['Id']
|
23
|
+
end
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
id = "ca_#{SecureRandom.uuid.gsub(/-/,'')}"
|
26
|
+
id = custom_action[:id] if(custom_action.key?(:id))
|
27
|
+
|
28
|
+
impersonate = 'yes'
|
29
|
+
impersonate = custom_action[:impersonate] if(custom_action.key?(:impersonate))
|
27
30
|
|
28
|
-
|
29
|
-
|
31
|
+
condition='NOT Installed AND NOT REMOVE'
|
32
|
+
condition='1' if(custom_action.key?(:binary_key))
|
33
|
+
condition = custom_action[:condition] if(custom_action.key?(:condition))
|
30
34
|
|
31
|
-
|
32
|
-
|
35
|
+
execute='deferred'
|
36
|
+
execute = custom_action[:execute] if(custom_action.key?(:execute))
|
33
37
|
|
34
|
-
|
35
|
-
|
36
|
-
condition = custom_action[:condition] if(custom_action.key?(:condition))
|
38
|
+
ret='check'
|
39
|
+
ret = custom_action[:return] if(custom_action.key?(:return))
|
37
40
|
|
38
|
-
|
39
|
-
|
41
|
+
wix_element = REXML::XPath.match(@xml_doc, "/Wix")[0]
|
42
|
+
fragment = wix_element.add_element 'Fragment'
|
40
43
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
action = fragment.add_element 'CustomAction', { 'Id' => id, '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
|
-
action.attributes['ExeCommand'] = cmd_line if(custom_action.key?(:exe_command))
|
44
|
+
action = fragment.add_element 'CustomAction', { 'Id' => id, 'Impersonate' => impersonate, 'Return' => ret, 'HideTarget' => 'no', 'Execute' => execute }
|
45
|
+
if(custom_action.key?(:binary_key))
|
46
|
+
action.attributes['BinaryKey'] = custom_action[:binary_key]
|
47
|
+
else
|
48
|
+
action.attributes['FileKey'] = file_key
|
49
|
+
end
|
55
50
|
|
56
|
-
|
51
|
+
action.attributes['Directory'] = custom_action[:directory] if(custom_action.key?(:directory))
|
52
|
+
action.attributes['ExeCommand'] = custom_action[:exe_command] if(custom_action.key?(:exe_command))
|
53
|
+
action.attributes['DllEntry'] = custom_action[:dll_entry] if(custom_action.key?(:dll_entry))
|
57
54
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
55
|
+
if(custom_action.key?(:property))
|
56
|
+
raise "Custom action property '#{custom_action[:property]} must have a value!" unless(custom_action.key?(:value))
|
57
|
+
action.attributes.delete('ExeCommand')
|
58
|
+
action.attributes.delete('Return')
|
59
|
+
action.attributes['Property'] = custom_action[:property]
|
60
|
+
action.attributes['Value'] = custom_action[:value]
|
61
|
+
end
|
65
62
|
|
66
63
|
install_execute_sequence = fragment.add_element 'InstallExecuteSequence'
|
67
64
|
|
68
|
-
|
69
|
-
|
70
|
-
|
65
|
+
custom_action[:before] = 'InstallFinalize' if(!custom_action.key?(:after) && !custom_action.key?(:before))
|
66
|
+
if(custom_action.key?(:after))
|
67
|
+
action = install_execute_sequence.add_element 'Custom', { 'Action' => id, 'After' => custom_action[:after] }
|
71
68
|
action.text = condition
|
72
|
-
|
73
|
-
|
69
|
+
else
|
70
|
+
action = install_execute_sequence.add_element 'Custom', { 'Action' => id, 'Before' => custom_action[:before] }
|
74
71
|
action.text = condition
|
75
|
-
|
72
|
+
end
|
76
73
|
|
77
|
-
|
78
|
-
|
79
|
-
|
74
|
+
control=nil
|
75
|
+
elements = REXML::XPath.match(@xml_doc, "/Wix/Product")
|
76
|
+
elements = REXML::XPath.match(@xml_doc, "/Wix/Module") if(elements.nil? || elements.size == 0)
|
80
77
|
|
81
|
-
|
82
|
-
|
78
|
+
elements[0].add_element 'CustomActionRef', { 'Id' => id }
|
83
79
|
end
|
84
80
|
end
|
85
|
-
|
86
81
|
end
|
data/lib/file.rb
CHANGED
@@ -4,10 +4,10 @@ class File
|
|
4
4
|
def self.read_only?(path)
|
5
5
|
raise "'#{path}' does not exist" unless(File.exists?(path))
|
6
6
|
|
7
|
-
|
7
|
+
fso = WIN32OLE.new('Scripting.FileSystemObject')
|
8
8
|
raise 'Failed to create Scripting.FileSystemObject' if(fso.nil?)
|
9
|
-
|
9
|
+
fo = fso.GetFile(path)
|
10
10
|
|
11
|
-
|
11
|
+
return ((fo.Attributes & 1) != 0) ? true : false
|
12
12
|
end
|
13
13
|
end
|
data/lib/service.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
require 'SecureRandom'
|
3
|
+
|
4
|
+
#module Wixgem
|
5
|
+
|
6
|
+
class Service
|
7
|
+
def initialize(hash)
|
8
|
+
@hash = hash
|
9
|
+
end
|
10
|
+
|
11
|
+
def create(xml_doc)
|
12
|
+
raise "Service hash is required to have a :service_exe key" unless(@hash.has_key?(:service_exe))
|
13
|
+
raise "Service hash is required to have a :service key" unless(@hash.has_key?(:service))
|
14
|
+
raise "Service hash is required to have a :name key" unless(@hash[:service].has_key?(:name))
|
15
|
+
|
16
|
+
service_exe = @hash[:service_exe]
|
17
|
+
raise "Service #{file} does not exist" unless(File.exists?(service_exe))
|
18
|
+
|
19
|
+
file_elements = REXML::XPath.match(xml_doc, "//File[@Source='.\\#{service_exe.gsub(/\//,'\\')}']")
|
20
|
+
raise "Service #{@file} does not match a 'File' element with a 'Source' attribute in the wix generated wix file" if(file_elements.length == 0)
|
21
|
+
|
22
|
+
service_exe_element = file_elements[0]
|
23
|
+
service_exe_element.attributes['KeyPath']='yes'
|
24
|
+
|
25
|
+
create_service_element(service_exe_element)
|
26
|
+
|
27
|
+
return xml_doc
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def create_service_element(service_exe_element)
|
32
|
+
parent_element = service_exe_element.parent
|
33
|
+
|
34
|
+
service = @hash[:service]
|
35
|
+
service_control = {}
|
36
|
+
service_control = @hash[:service_control] if(@hash.has_key?(:service))
|
37
|
+
|
38
|
+
service_element = parent_element.add_element('ServiceInstall')
|
39
|
+
|
40
|
+
service_element.attributes['Id'] = "Service_#{SecureRandom.uuid.gsub(/-/,'')}"
|
41
|
+
service_element.attributes['Name'] = service[:name]
|
42
|
+
service_element.attributes['ErrorControl'] = 'normal'
|
43
|
+
service_element.attributes['Start'] = 'demand'
|
44
|
+
service_element.attributes['Type'] = 'ownProcess'
|
45
|
+
|
46
|
+
service_control_element = parent_element.add_element 'ServiceControl'
|
47
|
+
service_control_element.attributes['Id'] = "ServiceControl_#{SecureRandom.uuid.gsub(/-/,'')}"
|
48
|
+
service_control_element.attributes['Name'] = service[:name]
|
49
|
+
|
50
|
+
service.each { |attribute, value| service_element.attributes[symbol_to_id(attribute)] = value }
|
51
|
+
service_control.each { |attribute, value| service_control_element.attributes[symbol_to_id(attribute)] = value }
|
52
|
+
|
53
|
+
return service_element
|
54
|
+
end
|
55
|
+
def symbol_to_id(symbol)
|
56
|
+
service_map = {
|
57
|
+
account: 'Account',
|
58
|
+
arguments: 'Arguments',
|
59
|
+
description: 'Description',
|
60
|
+
display_name: 'DisplayName',
|
61
|
+
erase_description: 'EraseDescription',
|
62
|
+
error_control: 'ErrorControl',
|
63
|
+
id: 'Id',
|
64
|
+
interactive: 'Interactive',
|
65
|
+
load_order_group:'LoadOrderGroup',
|
66
|
+
name: 'Name',
|
67
|
+
password: 'Password',
|
68
|
+
start: 'Start',
|
69
|
+
type: 'Type',
|
70
|
+
vital: 'Vital'
|
71
|
+
}
|
72
|
+
|
73
|
+
return service_map[symbol] if(service_map.has_key?(symbol))
|
74
|
+
|
75
|
+
service_control_map = {
|
76
|
+
id: 'Id',
|
77
|
+
name: 'Name',
|
78
|
+
remove: 'Remove',
|
79
|
+
start: 'Start',
|
80
|
+
stop: 'Stop',
|
81
|
+
wait: 'Wait'
|
82
|
+
}
|
83
|
+
return service_control_map[symbol]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
data/lib/wixgem.rb
CHANGED
@@ -8,6 +8,7 @@ require_relative 'shortcut.rb'
|
|
8
8
|
require_relative 'custom_action.rb'
|
9
9
|
require_relative 'temp_directory.rb'
|
10
10
|
require_relative 'associate_extension.rb'
|
11
|
+
require_relative 'service.rb'
|
11
12
|
|
12
13
|
# Editor for wix Files WixEdit: http://http://wixedit.sourceforge.net/
|
13
14
|
# Full list of Wix editors : http://robmensching.com/blog/posts/2007/11/20/wix-editors/
|
@@ -61,29 +62,29 @@ class Wix
|
|
61
62
|
end
|
62
63
|
|
63
64
|
def self.manage_installdir(xml_doc, input)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
product_target_elements = REXML::XPath.match(xml_doc, "/Wix/Product/Directory[@Id='TARGETDIR']")
|
66
|
+
if(!product_target_elements.nil? && product_target_elements.size == 1)
|
67
|
+
targetdir = product_target_elements[0]
|
68
|
+
installdir = targetdir.add_element 'Directory', { 'Id' => 'ProgramFilesFolder' }
|
68
69
|
installdir = installdir.add_element 'Directory', { 'Id' => "Dir_#{input[:manufacturer]}", 'Name' => input[:manufacturer] } if(input.has_key?(:manufacturer))
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
70
|
+
installdir = installdir.add_element 'Directory', { 'Id' => 'INSTALLDIR', 'Name' => input[:product_name] }
|
71
|
+
else
|
72
|
+
module_target_elements = REXML::XPath.match(xml_doc, "/Wix/Module/Directory[@Id='TARGETDIR']")
|
73
|
+
targetdir = module_target_elements[0]
|
74
|
+
targetdir.add_element 'Directory', { 'Id' => 'MergeRedirectFolder', 'FileSource' => '.' }
|
75
|
+
end
|
76
|
+
return xml_doc
|
76
77
|
end
|
77
78
|
|
78
79
|
def self.manage_netframework(xml_doc, input)
|
79
80
|
if(input.key?(:requires_netframework))
|
80
|
-
|
81
|
-
|
81
|
+
wix = REXML::XPath.match(xml_doc, "/Wix")[0]
|
82
|
+
wix.attributes['xmlns:netfx'] = 'https://schemas.microsoft.com/wix/NetFxExtension'
|
82
83
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
84
|
+
product = REXML::XPath.match(xml_doc, "/Wix/Product")[0]
|
85
|
+
product.add_element 'PropertyRef', { 'Id' => input[:requires_netframework] }
|
86
|
+
condition = product.add_element 'Condition', { 'Message' => "This application requires .NET Framework #{input[:requires_netframework]}. Please install the .NET Framework then run this installer again." }
|
87
|
+
condition.text = "<![CDATA[Installed OR #{input[:requires_netframework]}]]>"
|
87
88
|
end
|
88
89
|
|
89
90
|
return xml_doc
|
@@ -91,16 +92,16 @@ class Wix
|
|
91
92
|
|
92
93
|
def self.manage_win10_crt(xml_doc, input)
|
93
94
|
if(input.key?(:requires_win10_crt))
|
94
|
-
|
95
|
+
product = REXML::XPath.match(xml_doc, "/Wix/Product")[0]
|
95
96
|
|
96
|
-
|
97
|
-
|
98
|
-
|
97
|
+
property = product.add_element 'Property', { 'Id' => 'WIN10_CRT_PRESENT' }
|
98
|
+
search = property.add_element 'DirectorySearch', { 'Id' => 'SystemFolderDriverVersion', 'Path' => '[SystemFolder]' }
|
99
|
+
search.add_element 'FileSearch', { 'Name' => 'ucrtbase.dll' }
|
99
100
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
101
|
+
msg = 'Requires Universal CRT see Windows Update KB2999226. Windows update should have installed the Universal CRT. Download and install from https://www.microsoft.com/en-us/download/details.aspx?id=48145'
|
102
|
+
condition = product.add_element 'Condition', { 'Message' => msg }
|
103
|
+
condition.text = "<![CDATA[Installed OR WIN10_CRT_PRESENT]]>"
|
104
|
+
end
|
104
105
|
|
105
106
|
return xml_doc
|
106
107
|
end
|
@@ -108,95 +109,95 @@ class Wix
|
|
108
109
|
def self.manage_ui(xml_doc, input)
|
109
110
|
product_elements = REXML::XPath.match(xml_doc, "/Wix/Product")
|
110
111
|
|
111
|
-
|
112
|
-
|
112
|
+
return if(product_elements.nil? || product_elements.size != 1)
|
113
|
+
return unless(input.key?(:ui))
|
113
114
|
|
114
|
-
|
115
|
-
|
115
|
+
product = product_elements[0]
|
116
|
+
ui = product.add_element 'UIRef', { 'Id' => input[:ui] }
|
116
117
|
|
117
118
|
return xml_doc
|
118
119
|
end
|
119
120
|
|
120
121
|
def self.manage_upgrade(xml_doc, input)
|
121
|
-
|
122
|
-
|
122
|
+
products = REXML::XPath.match(xml_doc, '//Wix/Product')
|
123
|
+
return xml_doc if(products.length == 0)
|
123
124
|
|
124
|
-
|
125
|
-
|
126
|
-
|
125
|
+
if(input[:remove_existing_products])
|
126
|
+
raise 'Hash must have a version key if the hash has a :remove_existing_products key' unless(input.has_key?(:version))
|
127
|
+
raise 'Hash must have an upgrade_code key if the hash has a :remove_existing_products key' unless(input.has_key?(:upgrade_code))
|
127
128
|
|
128
|
-
|
129
|
-
|
129
|
+
upgrade = products[0].add_element 'MajorUpgrade', { 'AllowDowngrades' => 'yes' }
|
130
|
+
end
|
130
131
|
|
131
|
-
|
132
|
+
return xml_doc
|
132
133
|
end
|
133
134
|
|
134
135
|
def self.manage_custom_actions(xml_doc, input)
|
135
136
|
custom_actions = CustomAction.new(xml_doc, input)
|
136
|
-
|
137
|
+
return xml_doc if(input[:custom_actions].nil?)
|
137
138
|
|
138
|
-
|
139
|
+
input[:custom_actions].each { |ca| custom_actions.add(ca) } if(input.key?(:custom_actions))
|
139
140
|
|
140
|
-
|
141
|
+
return xml_doc
|
141
142
|
end
|
142
143
|
|
143
144
|
def self.manage_associate_extensions(xml_doc, input)
|
144
145
|
return xml_doc unless(input.key?(:extensions))
|
145
146
|
|
146
|
-
|
147
|
-
|
147
|
+
ext = AssociateExtension.new(xml_doc)
|
148
|
+
input[:extensions].each { |exe, file_ext| ext.associate(exe, file_ext) }
|
148
149
|
|
149
|
-
|
150
|
+
return xml_doc
|
150
151
|
end
|
151
152
|
|
152
153
|
def self.manage_msm_files(xml_doc)
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
154
|
+
merge_modules = {}
|
155
|
+
component_group = REXML::XPath.match(xml_doc, '//Wix/Fragment/ComponentGroup')
|
156
|
+
component_group.each { |component_group|
|
157
|
+
component_group.each_element('Component') { |component|
|
158
|
+
component.each_element('File') { |file|
|
159
|
+
merge_modules[component] = file if(File.extname(file.attributes['Source']) == '.msm')
|
160
|
+
}
|
161
|
+
}
|
160
162
|
}
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
end
|
163
|
+
return xml_doc if(merge_modules.length == 0)
|
164
|
+
|
165
|
+
directory_root = REXML::XPath.match(xml_doc, "//Directory[@Id='INSTALLDIR']")
|
166
|
+
if(directory_root.length == 0)
|
167
|
+
module_root = REXML::XPath.match(xml_doc, '//Wix/Module')
|
168
|
+
raise 'Merge modules can not be added to a merge module' unless(module_root.nil?)
|
169
|
+
raise 'Wix element //Wix/Product/Directory does not exist'
|
170
|
+
end
|
170
171
|
|
171
|
-
|
172
|
+
default_feature = REXML::XPath.match(xml_doc, '//Wix/Product/Feature')
|
172
173
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
174
|
+
merge_modules.each { |component,file|
|
175
|
+
id = component.attributes['Id'].gsub('cmp','merge')
|
176
|
+
directory_root[0].add_element 'Merge', { 'Id' => id, 'SourceFile' => file.attributes['Source'], 'Language' => '1033', 'DiskId' => '1'}
|
177
|
+
default_feature[0].add_element 'MergeRef', { 'Id' => id }
|
177
178
|
|
178
|
-
|
179
|
+
component_group[0].delete_element(component)
|
179
180
|
}
|
180
181
|
|
181
|
-
|
182
|
+
return xml_doc
|
182
183
|
end
|
183
184
|
|
184
185
|
def self.manage_read_only_files(xml_doc,input)
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
186
|
+
install_files = files(input)
|
187
|
+
|
188
|
+
install_files.each do |file|
|
189
|
+
absolute_path = file
|
190
|
+
absolute_path = "#{input[:original_pwd]}/#{file}" unless(File.exists?(file))
|
191
|
+
|
192
|
+
if(File.read_only?(absolute_path))
|
193
|
+
install_path = ".\\#{self.modify_file_path(input, file).gsub(/\//,'\\')}"
|
194
|
+
install_path = install_path.gsub(/\.\\\\/,'.\\')
|
195
|
+
file_elements = REXML::XPath.match(xml_doc, "//File[@Source='#{install_path}']")
|
196
|
+
file_elements[0].attributes['ReadOnly'] = 'yes' if(file_elements.length == 1)
|
197
|
+
end
|
196
198
|
end
|
197
|
-
end
|
198
199
|
|
199
|
-
|
200
|
+
return xml_doc
|
200
201
|
end
|
201
202
|
|
202
203
|
def self.manage_shortcuts(xml_doc,input)
|
@@ -207,31 +208,42 @@ class Wix
|
|
207
208
|
xml_doc = shortcut.create(xml_doc)
|
208
209
|
end
|
209
210
|
|
211
|
+
return xml_doc
|
212
|
+
end
|
213
|
+
|
214
|
+
def self.manage_services(xml_doc,input)
|
215
|
+
return xml_doc unless(input.has_key?(:services))
|
216
|
+
|
217
|
+
input[:services].each do |service_hash|
|
218
|
+
service = Service.new(service_hash)
|
219
|
+
xml_doc = service.create(xml_doc)
|
220
|
+
end
|
221
|
+
|
210
222
|
return xml_doc
|
211
223
|
end
|
212
224
|
|
213
225
|
def self.manage_self_register(xml_doc, input)
|
214
226
|
return xml_doc unless(input.has_key?(:com_self_register))
|
215
227
|
input[:com_self_register].each do |file|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
228
|
+
file_elements = REXML::XPath.match(xml_doc, "//File[@Source='.\\#{file.gsub(/\//,'\\')}']")
|
229
|
+
raise "Unable to find file '#{file}' for self registering" unless (file_elements.length == 1)
|
230
|
+
file_elements[0].attributes['SelfRegCost'] = '0'
|
231
|
+
end
|
220
232
|
|
221
|
-
|
233
|
+
return xml_doc
|
222
234
|
end
|
223
235
|
|
224
236
|
def self.manage_binary_table(xml_doc, input)
|
225
|
-
|
226
|
-
|
237
|
+
return xml_doc unless(input.has_key?(:binary_table))
|
238
|
+
wix_element = REXML::XPath.match(xml_doc, "/Wix")[0]
|
227
239
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
240
|
+
fragment = wix_element.add_element 'Fragment'
|
241
|
+
input[:binary_table].each { |entry|
|
242
|
+
#puts "File: #{entry[:file]}"
|
243
|
+
binary = fragment.add_element 'Binary', { 'Id' => entry[:id], 'SourceFile' => entry[:file] }
|
244
|
+
}
|
233
245
|
|
234
|
-
|
246
|
+
return xml_doc
|
235
247
|
end
|
236
248
|
|
237
249
|
def self.modify_file_path(input, file)
|
@@ -246,7 +258,8 @@ class Wix
|
|
246
258
|
def self.files(input)
|
247
259
|
files = input
|
248
260
|
files = input[:files] if(input.kind_of?(Hash))
|
249
|
-
|
261
|
+
|
262
|
+
return files
|
250
263
|
end
|
251
264
|
|
252
265
|
def self.ignore_files(input)
|
@@ -257,328 +270,327 @@ class Wix
|
|
257
270
|
end
|
258
271
|
|
259
272
|
def self.copy_install_files(directory, input)
|
260
|
-
|
273
|
+
files = files(input)
|
261
274
|
|
262
|
-
|
263
|
-
|
264
|
-
|
275
|
+
missing_files = []
|
276
|
+
files.each do |file|
|
277
|
+
if(File.file?(file))
|
265
278
|
install_path = file
|
266
279
|
if(input.has_key?(:modify_file_paths))
|
267
280
|
input[:modify_file_paths].each { |regex, replacement_string| install_path = install_path.gsub(regex, replacement_string) }
|
268
281
|
end
|
269
|
-
|
282
|
+
raise "Invalid relative installation path: #{install_path}" if(install_path.include?(':'))
|
270
283
|
|
271
284
|
install_path = "#{directory}/#{install_path}"
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
285
|
+
FileUtils.mkpath(File.dirname(install_path)) unless(Dir.exists?(File.dirname(install_path)))
|
286
|
+
FileUtils.cp(file, install_path, { preserve: true })
|
287
|
+
elsif(!File.exists?(file))
|
288
|
+
missing_files.insert(missing_files.length, file)
|
289
|
+
end
|
276
290
|
end
|
277
|
-
end
|
278
291
|
|
279
292
|
if(@debug)
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
293
|
+
if(files.length > 0)
|
294
|
+
max_path = files.max { |a, b| a.length <=> b.length }
|
295
|
+
columen_size = max_path.length + 10
|
296
|
+
end
|
284
297
|
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
298
|
+
ingore_files = self.ignore_files(input)
|
299
|
+
if(input.has_key?(:ignore_files))
|
300
|
+
@logger << "------------------------------------ ignoring files -----------------------------------" unless(@logger.nil?)
|
301
|
+
input[:ignore_files].each { |file| @logger << file }
|
302
|
+
end
|
303
|
+
|
304
|
+
@logger << "------------------------------------ Installation Paths -----------------------------------" unless(@logger.nil?)
|
305
|
+
@logger << "%-#{columen_size}s %s\n" % ['File path', 'Installation Path'] unless(@logger.nil?)
|
306
|
+
files.reject! { |f| ingore_files.include?(f) }
|
307
|
+
|
308
|
+
files.each do |file|
|
309
|
+
if(File.file?(file))
|
297
310
|
install_path = file
|
298
311
|
if(input.has_key?(:modify_file_paths))
|
299
312
|
input[:modify_file_paths].each { |regex, replacement_string| install_path = install_path.gsub(regex, replacement_string) }
|
300
313
|
end
|
301
|
-
|
314
|
+
@logger << "%-#{columen_size}s %s\n" % [file, install_path] unless(@logger.nil?)
|
302
315
|
end
|
303
316
|
end
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
raise 'No files were given to wixgem' if(files.length == 0)
|
317
|
+
@logger << "-------------------------------------------------------------------------------------------" unless(@logger.nil?)
|
318
|
+
end
|
308
319
|
|
309
|
-
|
310
|
-
|
311
|
-
missing_files.
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
+
raise 'No files were given to wixgem' if(files.length == 0)
|
321
|
+
|
322
|
+
if(missing_files.length > 0)
|
323
|
+
missing_files_str = ''
|
324
|
+
missing_files.each { |f|
|
325
|
+
if(missing_files_str.empty?)
|
326
|
+
missing_files_str = f
|
327
|
+
else
|
328
|
+
missing_files_str = "#{missing_files_str}, #{f}"
|
329
|
+
end
|
330
|
+
}
|
331
|
+
raise "Wixgem missing files: #{missing_files_str}"
|
332
|
+
end
|
320
333
|
end
|
321
334
|
|
322
335
|
def self.modify_binary_files(input)
|
323
336
|
return unless(input.key?(:binary_table))
|
324
|
-
|
337
|
+
input[:binary_table].each { |entry| entry[:file] = File.absolute_path(entry[:file]) }
|
325
338
|
end
|
326
339
|
|
327
340
|
def self.log_wix_output(cmd)
|
328
|
-
|
341
|
+
return unless(@debug && !@logger.nil?)
|
329
342
|
|
330
|
-
|
331
|
-
|
343
|
+
@logger << "----------------------------------------------------------------------------"
|
344
|
+
@logger << cmd
|
332
345
|
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
346
|
+
if(!cmd[:output].empty?)
|
347
|
+
@logger << "--------------------------- std output -----------------------------------"
|
348
|
+
@logger << cmd[:output]
|
349
|
+
end
|
337
350
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
351
|
+
if(!cmd[:error].empty?)
|
352
|
+
@logger << "--------------------------- std error ------------------------------------"
|
353
|
+
@logger << cmd[:error]
|
354
|
+
end
|
342
355
|
end
|
343
356
|
|
344
357
|
def self.modify_heat_commandline(input, cmd)
|
345
358
|
cmd = cmd.gsub(/-srd/, '-svb6 -srd') if(input.has_key?(:has_vb6_files) && input[:has_vb6_files])
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
359
|
+
cmd = cmd.gsub(/-srd/, '-sreg -srd') if(input.has_key?(:suppress_registry_harvesting) && input[:suppress_registry_harvesting])
|
360
|
+
cmd = cmd.gsub(/-srd/, '-scom -srd') if(input.has_key?(:suppress_COM_elements) && input[:suppress_COM_elements])
|
361
|
+
if(input[:msi?])
|
362
|
+
cmd = cmd.gsub(/-srd/, '-dr INSTALLDIR -srd')
|
363
|
+
else
|
364
|
+
cmd = cmd.gsub(/-srd/, '-dr MergeRedirectFolder -srd')
|
365
|
+
end
|
366
|
+
return cmd
|
354
367
|
end
|
355
368
|
|
356
369
|
def self.execute_heat(input, cmd_line_options)
|
357
|
-
|
358
|
-
|
359
|
-
|
370
|
+
heat_cmd = Execute.new("\"#{install_path.gsub(/\\/,'/')}/bin/heat.exe\" #{modify_heat_commandline(input, cmd_line_options)}", { quiet: true })
|
371
|
+
heat_cmd.execute
|
372
|
+
log_wix_output(heat_cmd)
|
360
373
|
end
|
361
374
|
|
362
375
|
def self.execute_heat_file(wxs_file, input, template_option)
|
363
|
-
|
364
|
-
|
376
|
+
install_files = files(input)
|
377
|
+
modified_paths = []
|
365
378
|
install_files.each { |file| modified_paths << modify_file_path(input, file) }
|
366
|
-
|
379
|
+
install_files = modified_paths
|
367
380
|
|
368
|
-
|
369
|
-
|
381
|
+
install_ignore_files = ignore_files(input)
|
382
|
+
modified_paths = []
|
370
383
|
install_ignore_files.each { |file| modified_paths << modify_file_path(input, file) }
|
371
|
-
|
384
|
+
install_ignore_files = modified_paths
|
372
385
|
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
raise "At least one file is required to build a #{package_type}" if(install_files.length == 0)
|
386
|
+
install_files.reject! { |f| install_ignore_files.include?(f) }
|
387
|
+
package_type = 'installation'
|
388
|
+
package_type = 'merge module' if(template_option.include?('module'))
|
389
|
+
raise "At least one file is required to build a #{package_type}" if(install_files.length == 0)
|
378
390
|
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
391
|
+
directory_fragments = {}
|
392
|
+
wxs_files = {}
|
393
|
+
install_files.each do |file|
|
394
|
+
windows_path = file.gsub(/\//, '\\')
|
383
395
|
|
384
|
-
|
385
|
-
|
396
|
+
filename = wxs_file
|
397
|
+
if(install_files.index(file) == 0)
|
386
398
|
execute_heat(input, "file \"#{windows_path}\" -v #{template_option} -cg InstallionFiles -gg -nologo -srd -o \"#{filename}\"")
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
399
|
+
else
|
400
|
+
filename = File.basename(wxs_file).gsub('.wxs', "-#{wxs_files.length}.wxs")
|
401
|
+
execute_heat(input, "file \"#{windows_path}\" -v -template fragment -gg -nologo -srd -o \"#{filename}\"")
|
402
|
+
wxs_files[file] = filename
|
403
|
+
end
|
404
|
+
|
405
|
+
directory_fragments[File.dirname(file)] = "dir#{SecureRandom.uuid.gsub(/-/,'')}"
|
406
|
+
xml_doc = REXML::Document.new(File.read(filename))
|
407
|
+
file_elements = REXML::XPath.match(xml_doc, '//Wix/Fragment/DirectoryRef/Component/File')
|
408
|
+
file_elements[0].attributes['Source'] = "SourceDir\\#{file.gsub(/\//,'\\')}" if(file_elements.length == 1)
|
409
|
+
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
|
410
|
+
|
411
|
+
File.open(filename, 'w') { |f| f.puts(xml_doc.to_s) }
|
412
|
+
end
|
413
|
+
directory_fragments['.'] = 'INSTALLDIR'
|
402
414
|
|
403
|
-
|
415
|
+
xml_doc = REXML::Document.new(File.read(wxs_file))
|
404
416
|
|
405
|
-
|
406
|
-
|
417
|
+
wix_elements = REXML::XPath.match(xml_doc, '//Wix')
|
418
|
+
raise "Invalid wxs file: #{wxs_file}" unless(wix_elements.length == 1)
|
407
419
|
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
420
|
+
directory_fragments.each do |key, id|
|
421
|
+
if(key != '.')
|
422
|
+
fragment_element = wix_elements[0].add_element 'Fragment'
|
423
|
+
directory_ref_element = fragment_element.add_element 'DirectoryRef', { 'Id' => directory_fragments[File.dirname(key)] }
|
424
|
+
directory_ref_element.add_element 'Directory', { 'Id' => id, 'Name' => File.basename(key) }
|
425
|
+
end
|
426
|
+
end
|
415
427
|
|
416
|
-
|
417
|
-
|
428
|
+
component_group_element = REXML::XPath.match(xml_doc, '//Wix/Fragment/ComponentGroup')
|
429
|
+
raise "Failed to create installation package for file: #{wxs_file}" unless(component_group_element.length == 1)
|
418
430
|
|
419
|
-
|
420
|
-
|
421
|
-
|
431
|
+
wxs_files.each do |file, filename|
|
432
|
+
xml_fragment_doc = REXML::Document.new(File.read(filename))
|
433
|
+
component_elements = REXML::XPath.match(xml_fragment_doc, '//Wix/Fragment/DirectoryRef/Component')
|
422
434
|
|
423
|
-
|
424
|
-
|
425
|
-
|
435
|
+
component_elements.each do |component_element|
|
436
|
+
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
|
437
|
+
component_element = component_group_element[0].add_element component_element, { 'Directory' => directory_fragments[File.dirname(file)] }
|
426
438
|
end
|
427
|
-
|
439
|
+
end
|
428
440
|
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
441
|
+
formatter = REXML::Formatters::Pretty.new(2)
|
442
|
+
formatter.compact = true # This is the magic line that does what you need!
|
443
|
+
xml_text=''
|
444
|
+
formatter.write(xml_doc, xml_text)
|
445
|
+
File.open(wxs_file, 'w') { |f| f.puts xml_text }
|
434
446
|
end
|
435
447
|
|
436
448
|
def self.execute_heat_dir(wxs_file, input, template_option)
|
437
|
-
|
449
|
+
execute_heat(input,"dir . #{template_option} -cg InstallionFiles -gg -nologo -srd -o \"#{wxs_file}\"")
|
438
450
|
end
|
439
451
|
|
440
452
|
def self.create_wxs_file(wxs_file, input, ext)
|
441
453
|
template_option = "-template product"
|
442
|
-
|
454
|
+
template_option = "-template module" unless(ext == ".msi")
|
443
455
|
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
456
|
+
if(input.has_key?(:ignore_files))
|
457
|
+
execute_heat_file(wxs_file, input, template_option)
|
458
|
+
else
|
459
|
+
execute_heat_dir(wxs_file, input, template_option)
|
460
|
+
end
|
449
461
|
|
450
|
-
|
451
|
-
|
462
|
+
product_name = File.basename(wxs_file, '.wxs')
|
463
|
+
input[:product_name] = product_name unless(input.has_key?(:product_name))
|
452
464
|
product_name = input[:product_name] if(input.has_key?(:product_name))
|
453
465
|
|
454
466
|
manufacturer = 'Not Set'
|
455
467
|
manufacturer = input[:manufacturer] if(input.has_key?(:manufacturer))
|
456
468
|
|
457
|
-
|
469
|
+
product_version = ''
|
458
470
|
product_version = input[:version] if(input.has_key?(:version))
|
459
471
|
|
460
|
-
|
461
|
-
|
472
|
+
product_code = ''
|
473
|
+
product_code = input[:product_code] if(input.has_key?(:product_code))
|
462
474
|
|
463
|
-
|
464
|
-
|
475
|
+
upgrade_code = ''
|
476
|
+
upgrade_code = input[:upgrade_code] if(input.has_key?(:upgrade_code))
|
465
477
|
|
466
|
-
|
467
|
-
|
478
|
+
install_path = '[ProgramFilesFolder][ProductName]'
|
479
|
+
install_path = "[ProgramFilesFolder][Manufacturer]\\[ProductName]" unless(manufacturer == 'Not Set')
|
468
480
|
|
469
|
-
|
481
|
+
wxs_text = File.read(wxs_file)
|
470
482
|
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
483
|
+
wxs_text = wxs_text.gsub(/SourceDir\\/) { |s| s = '.\\' }
|
484
|
+
wxs_text = wxs_text.gsub(/PUT-PRODUCT-NAME-HERE/) { |s| s = product_name }
|
485
|
+
wxs_text = wxs_text.gsub(/PUT-MODULE-NAME-HERE/) { |s| s = product_name }
|
486
|
+
wxs_text = wxs_text.gsub(/PUT-COMPANY-NAME-HERE/) { |s| s = manufacturer }
|
487
|
+
wxs_text = wxs_text.gsub(/PUT-FEATURE-TITLE-HERE/) { |s| s = 'Files to Install' }
|
476
488
|
|
477
|
-
|
478
|
-
|
479
|
-
|
489
|
+
wxs_text = wxs_text.gsub(/Version=\"1.0.0.0\"/) { |s| s = "Version=\"#{product_version}\"" } unless(product_version.empty?)
|
490
|
+
wxs_text = wxs_text.gsub(/Product Id=\"[^\"]+\"/) { |s| s = "Product Id=\"#{product_code}\"" } unless(product_code.empty?)
|
491
|
+
wxs_text = wxs_text.gsub(/UpgradeCode=\"[^\"]+\"/) { |s| s = "UpgradeCode=\"#{upgrade_code}\"" } unless(upgrade_code.empty?)
|
480
492
|
|
481
|
-
|
493
|
+
File.open(wxs_file, 'w') { |f| f.write(wxs_text) }
|
482
494
|
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
495
|
+
xml_doc = REXML::Document.new(wxs_text)
|
496
|
+
products = REXML::XPath.match(xml_doc, "/Wix/Product")
|
497
|
+
products.each do |product|
|
498
|
+
product.add_element 'SetProperty', { 'Id' => 'ARPINSTALLLOCATION', 'Value' => "#{install_path}", 'After' => 'CostFinalize', 'Sequence' => 'both' }
|
499
|
+
end
|
488
500
|
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
501
|
+
packages = REXML::XPath.match(xml_doc, '//Wix/Product/Package')
|
502
|
+
packages.each do |package|
|
503
|
+
package.add_attribute('InstallScope', 'perMachine') if(input.has_key?(:all_users))
|
504
|
+
package.add_attribute('InstallScope', input[:install_scope]) if(input.has_key?(:install_scope))
|
505
|
+
package.attributes['InstallerVersion'] = 450
|
506
|
+
package.attributes['InstallerVersion'] = (input[:installer_version]*100).to_i if(input.has_key?(:installer_version))
|
495
507
|
package.attributes['InstallPrivileges']= input[:install_priviledges] if(input.has_key?(:install_priviledges))
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
508
|
+
end
|
509
|
+
|
510
|
+
xml_doc = manage_installdir(xml_doc, input)
|
511
|
+
xml_doc = manage_netframework(xml_doc, input)
|
512
|
+
xml_doc = manage_win10_crt(xml_doc, input)
|
513
|
+
#xml_doc = manage_ui(xml_doc, input)
|
514
|
+
xml_doc = manage_custom_actions(xml_doc, input)
|
515
|
+
xml_doc = manage_upgrade(xml_doc,input)
|
516
|
+
xml_doc = manage_msm_files(xml_doc)
|
517
|
+
xml_doc = manage_read_only_files(xml_doc,input)
|
518
|
+
xml_doc = manage_shortcuts(xml_doc, input)
|
519
|
+
xml_doc = manage_self_register(xml_doc, input)
|
520
|
+
xml_doc = manage_binary_table(xml_doc, input)
|
521
|
+
xml_doc = manage_associate_extensions(xml_doc, input)
|
522
|
+
xml_doc = manage_services(xml_doc, input)
|
510
523
|
|
511
524
|
formatter = REXML::Formatters::Pretty.new(2)
|
512
525
|
formatter.compact = true
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
526
|
+
File.open(wxs_file, 'w') { |f| formatter.write(xml_doc, f) }
|
527
|
+
str = File.read(wxs_file)
|
528
|
+
str = str.gsub(/</,'<')
|
529
|
+
str = str.gsub(/>/,'>')
|
517
530
|
File.open(wxs_file, 'w') { |f| f.puts(str) }
|
518
531
|
end
|
519
532
|
|
520
533
|
def self.create_output(wxs_file, input, output)
|
521
534
|
wixobj_file = "#{File.basename(wxs_file,'.wxs')}.wixobj"
|
522
535
|
|
523
|
-
|
524
|
-
|
525
|
-
|
536
|
+
candle_cmd = Execute.new("\"#{install_path.gsub(/\\/,'/')}/bin/candle.exe\" -out \"#{wixobj_file}\" \"#{wxs_file}\"", { quiet: true })
|
537
|
+
candle_cmd.execute
|
538
|
+
log_wix_output(candle_cmd)
|
526
539
|
|
527
|
-
|
540
|
+
cmd_args = "-nologo -out \"#{output}\" \"#{wixobj_file}\""
|
528
541
|
cmd_args = "-ext WixNetfxExtension -ext WixUIExtension -ext WixUtilExtension -cultures:en-us #{cmd_args}"
|
529
|
-
|
530
|
-
|
531
|
-
|
542
|
+
light_cmd = Execute.new("\"#{install_path.gsub(/\\/,'/')}/bin/light.exe\" #{cmd_args}", { quiet: true })
|
543
|
+
light_cmd.execute
|
544
|
+
log_wix_output(light_cmd)
|
532
545
|
end
|
533
546
|
|
534
547
|
def self.verify_input_keys(input)
|
535
|
-
|
548
|
+
input[:files].reject! { |f| File.directory?(f) }
|
536
549
|
|
537
550
|
[:files,:ignore_files].each { |key| raise "Hash key #{key} cannot be nil" if(input.has_key?(key) && input[key].nil?)}
|
538
551
|
end
|
539
552
|
|
540
553
|
def self.create_package(output, input)
|
541
|
-
|
542
|
-
|
543
|
-
|
554
|
+
raise 'WIX path is not set! Install Wixtoolset or assign with Wixgem::Wix.install_path = <path to wix toolset' if(self.install_path.nil?)
|
555
|
+
input = { files: input } unless(input.kind_of?(Hash))
|
556
|
+
verify_input_keys(input)
|
544
557
|
|
545
|
-
|
546
|
-
|
558
|
+
@debug = input[:debug] if(!@debug && input.has_key?(:debug))
|
559
|
+
start_logger if(@debug)
|
547
560
|
|
548
|
-
|
561
|
+
FileUtils.mkpath(File.dirname(output)) unless(Dir.exists?(File.dirname(output)))
|
549
562
|
|
550
|
-
|
563
|
+
ext = File.extname(output)
|
551
564
|
basename = File.basename(output, ext)
|
552
|
-
|
565
|
+
FileUtils.rm(output) if(File.exists?(output))
|
553
566
|
|
554
|
-
|
555
|
-
|
556
|
-
|
567
|
+
output_absolute_path = File.absolute_path(output)
|
568
|
+
input[:original_pwd] = Dir.pwd
|
569
|
+
input[:msi?] = output.include?('.msi')
|
557
570
|
|
558
|
-
|
571
|
+
modify_binary_files(input)
|
559
572
|
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
573
|
+
temp_directory do |dir|
|
574
|
+
wxs_file = "#{basename}.wxs"
|
575
|
+
begin
|
576
|
+
copy_install_files(dir, input)
|
564
577
|
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
578
|
+
Dir.chdir(dir) do |current_dir|
|
579
|
+
create_wxs_file(wxs_file, input, ext)
|
580
|
+
create_output(wxs_file, input, output_absolute_path)
|
581
|
+
end
|
582
|
+
rescue Exception => e
|
583
|
+
raise e
|
584
|
+
ensure
|
585
|
+
FileUtils.cp("#{dir}/#{wxs_file}", "#{output_absolute_path}.wxs") if(File.exists?("#{dir}/#{wxs_file}") && @debug)
|
586
|
+
File.open("#{output_absolute_path}.log", 'w') { |f| f.puts(@logger) } if(@debug &!@logger.nil?)
|
587
|
+
end
|
588
|
+
end
|
576
589
|
|
577
|
-
|
578
|
-
|
590
|
+
pdb_file = output_absolute_path.gsub(ext,'.wixpdb')
|
591
|
+
FileUtils.rm(pdb_file) if(File.exists?(pdb_file))
|
579
592
|
|
580
|
-
|
593
|
+
end_logger if(@debug)
|
594
|
+
end
|
581
595
|
end
|
582
|
-
end
|
583
|
-
|
584
596
|
end
|
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.
|
4
|
+
version: 0.99.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: 2019-
|
11
|
+
date: 2019-05-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: execute
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: win32-service
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: WindowsInstaller
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -117,6 +131,7 @@ extra_rdoc_files: []
|
|
117
131
|
files:
|
118
132
|
- LICENSE
|
119
133
|
- README.md
|
134
|
+
- example/example.msi
|
120
135
|
- example/example.msm
|
121
136
|
- example/install_files/directory/file2.txt
|
122
137
|
- example/install_files/file1.txt
|
@@ -125,6 +140,7 @@ files:
|
|
125
140
|
- lib/associate_extension.rb
|
126
141
|
- lib/custom_action.rb
|
127
142
|
- lib/file.rb
|
143
|
+
- lib/service.rb
|
128
144
|
- lib/shortcut.rb
|
129
145
|
- lib/temp_directory.rb
|
130
146
|
- lib/wixgem.rb
|
@@ -147,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
163
|
- !ruby/object:Gem::Version
|
148
164
|
version: '0'
|
149
165
|
requirements: []
|
150
|
-
rubygems_version: 3.0.
|
166
|
+
rubygems_version: 3.0.3
|
151
167
|
signing_key:
|
152
168
|
specification_version: 4
|
153
169
|
summary: Simple Ruby interface to facilitate working with Wix Toolset
|