Filename | /cygdrive/c/lo/libo-master/instsetoo_native/util/C:/lo/libo-master/solenv/bin/modules/installer/windows/mergemodule.pm |
Statements | Executed 1420700 statements in 99.5s |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
84 | 8 | 1 | 86.7s | 86.7s | CORE:system (opcode) | installer::windows::mergemodule::
15 | 3 | 1 | 6.20s | 6.20s | CORE:backtick (opcode) | installer::windows::mergemodule::
117927 | 2 | 1 | 2.40s | 2.40s | CORE:regcomp (opcode) | installer::windows::mergemodule::
5 | 1 | 1 | 1.96s | 2.38s | analyze_filetable_file | installer::windows::mergemodule::
5 | 1 | 1 | 1.14s | 3.87s | change_component_table | installer::windows::mergemodule::
282524 | 36 | 1 | 542ms | 542ms | CORE:match (opcode) | installer::windows::mergemodule::
5 | 1 | 1 | 418ms | 12.1s | change_file_table | installer::windows::mergemodule::
268 | 43 | 1 | 35.0ms | 35.0ms | CORE:ftfile (opcode) | installer::windows::mergemodule::
5 | 1 | 1 | 19.6ms | 264ms | change_featurecomponent_table | installer::windows::mergemodule::
1 | 1 | 1 | 16.9ms | 31.4ms | collect_feature | installer::windows::mergemodule::
20 | 1 | 1 | 14.6ms | 18.2ms | make_executeidtcontent_hash | installer::windows::mergemodule::
1 | 1 | 1 | 13.0ms | 101s | merge_mergemodules_into_msi_database | installer::windows::mergemodule::
30 | 6 | 1 | 5.48ms | 5.48ms | CORE:chdir (opcode) | installer::windows::mergemodule::
20 | 4 | 1 | 4.48ms | 51.8ms | change_executesequence_table | installer::windows::mergemodule::
20 | 1 | 1 | 3.60ms | 4.52ms | make_moduleexecuteidtcontent_hash | installer::windows::mergemodule::
10 | 2 | 1 | 1.96ms | 1.96ms | CORE:ftdir (opcode) | installer::windows::mergemodule::
88 | 12 | 1 | 1.26ms | 1.26ms | CORE:subst (opcode) | installer::windows::mergemodule::
4 | 1 | 1 | 1.19ms | 1.46ms | analyze_msiassemblytable_file | installer::windows::mergemodule::
5 | 1 | 1 | 602µs | 5.22ms | change_media_table | installer::windows::mergemodule::
33 | 1 | 1 | 477µs | 477µs | get_new_line_for_file_table | installer::windows::mergemodule::
4 | 1 | 1 | 449µs | 5.80ms | change_msiassembly_table | installer::windows::mergemodule::
1 | 1 | 1 | 362µs | 463µs | BEGIN@30 | installer::windows::mergemodule::
5 | 1 | 1 | 320µs | 373µs | analyze_media_file | installer::windows::mergemodule::
5 | 1 | 1 | 107µs | 107µs | CORE:sort (opcode) | installer::windows::mergemodule::
5 | 1 | 1 | 98µs | 98µs | set_current_last_sequence | installer::windows::mergemodule::
5 | 1 | 1 | 63µs | 63µs | get_last_diskid | installer::windows::mergemodule::
5 | 1 | 1 | 54µs | 54µs | change_directory_table | installer::windows::mergemodule::
4 | 1 | 1 | 44µs | 44µs | get_new_line_for_msiassembly_table | installer::windows::mergemodule::
1 | 1 | 1 | 21µs | 24µs | BEGIN@32 | installer::windows::mergemodule::
1 | 1 | 1 | 20µs | 22µs | BEGIN@41 | installer::windows::mergemodule::
1 | 1 | 1 | 19µs | 19µs | set_last_cabfile_name | installer::windows::mergemodule::
1 | 1 | 1 | 18µs | 20µs | BEGIN@39 | installer::windows::mergemodule::
1 | 1 | 1 | 17µs | 19µs | BEGIN@40 | installer::windows::mergemodule::
1 | 1 | 1 | 17µs | 19µs | BEGIN@38 | installer::windows::mergemodule::
1 | 1 | 1 | 17µs | 18µs | BEGIN@43 | installer::windows::mergemodule::
1 | 1 | 1 | 16µs | 41µs | BEGIN@31 | installer::windows::mergemodule::
1 | 1 | 1 | 15µs | 42µs | BEGIN@36 | installer::windows::mergemodule::
1 | 1 | 1 | 14µs | 16µs | BEGIN@33 | installer::windows::mergemodule::
1 | 1 | 1 | 14µs | 16µs | BEGIN@34 | installer::windows::mergemodule::
1 | 1 | 1 | 14µs | 16µs | BEGIN@37 | installer::windows::mergemodule::
1 | 1 | 1 | 14µs | 16µs | BEGIN@35 | installer::windows::mergemodule::
1 | 1 | 1 | 14µs | 16µs | BEGIN@42 | installer::windows::mergemodule::
0 | 0 | 0 | 0s | 0s | analyze_directorytable_file | installer::windows::mergemodule::
0 | 0 | 0 | 0s | 0s | collect_directories | installer::windows::mergemodule::
0 | 0 | 0 | 0s | 0s | create_new_media_line | installer::windows::mergemodule::
0 | 0 | 0 | 0s | 0s | get_diskid | installer::windows::mergemodule::
0 | 0 | 0 | 0s | 0s | get_diskprompt | installer::windows::mergemodule::
0 | 0 | 0 | 0s | 0s | get_lastsequence | installer::windows::mergemodule::
0 | 0 | 0 | 0s | 0s | get_new_line_for_directory_table | installer::windows::mergemodule::
0 | 0 | 0 | 0s | 0s | get_source | installer::windows::mergemodule::
0 | 0 | 0 | 0s | 0s | get_volumelabel | installer::windows::mergemodule::
0 | 0 | 0 | 0s | 0s | sort_files_collector_for_sequence | installer::windows::mergemodule::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | #************************************************************************* | ||||
2 | # | ||||
3 | # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||||
4 | # | ||||
5 | # Copyright 2000, 2010 Oracle and/or its affiliates. | ||||
6 | # | ||||
7 | # OpenOffice.org - a multi-platform office productivity suite | ||||
8 | # | ||||
9 | # This file is part of OpenOffice.org. | ||||
10 | # | ||||
11 | # OpenOffice.org is free software: you can redistribute it and/or modify | ||||
12 | # it under the terms of the GNU Lesser General Public License version 3 | ||||
13 | # only, as published by the Free Software Foundation. | ||||
14 | # | ||||
15 | # OpenOffice.org is distributed in the hope that it will be useful, | ||||
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
18 | # GNU Lesser General Public License version 3 for more details | ||||
19 | # (a copy is included in the LICENSE file that accompanied this code). | ||||
20 | # | ||||
21 | # You should have received a copy of the GNU Lesser General Public License | ||||
22 | # version 3 along with OpenOffice.org. If not, see | ||||
23 | # <http://www.openoffice.org/license.html> | ||||
24 | # for a copy of the LGPLv3 License. | ||||
25 | # | ||||
26 | #************************************************************************* | ||||
27 | |||||
28 | package installer::windows::mergemodule; | ||||
29 | |||||
30 | 2 | 65µs | 2 | 564µs | # spent 463µs (362+101) within installer::windows::mergemodule::BEGIN@30 which was called:
# once (362µs+101µs) by installer::BEGIN@74 at line 30 # spent 463µs making 1 call to installer::windows::mergemodule::BEGIN@30
# spent 101µs making 1 call to Exporter::import |
31 | 2 | 58µs | 2 | 66µs | # spent 41µs (16+25) within installer::windows::mergemodule::BEGIN@31 which was called:
# once (16µs+25µs) by installer::BEGIN@74 at line 31 # spent 41µs making 1 call to installer::windows::mergemodule::BEGIN@31
# spent 25µs making 1 call to Exporter::import |
32 | 2 | 55µs | 2 | 26µs | # spent 24µs (21+3) within installer::windows::mergemodule::BEGIN@32 which was called:
# once (21µs+3µs) by installer::BEGIN@74 at line 32 # spent 24µs making 1 call to installer::windows::mergemodule::BEGIN@32
# spent 3µs making 1 call to UNIVERSAL::import |
33 | 2 | 53µs | 2 | 19µs | # spent 16µs (14+3) within installer::windows::mergemodule::BEGIN@33 which was called:
# once (14µs+3µs) by installer::BEGIN@74 at line 33 # spent 16µs making 1 call to installer::windows::mergemodule::BEGIN@33
# spent 3µs making 1 call to UNIVERSAL::import |
34 | 2 | 53µs | 2 | 19µs | # spent 16µs (14+3) within installer::windows::mergemodule::BEGIN@34 which was called:
# once (14µs+3µs) by installer::BEGIN@74 at line 34 # spent 16µs making 1 call to installer::windows::mergemodule::BEGIN@34
# spent 3µs making 1 call to UNIVERSAL::import |
35 | 2 | 51µs | 2 | 18µs | # spent 16µs (14+2) within installer::windows::mergemodule::BEGIN@35 which was called:
# once (14µs+2µs) by installer::BEGIN@74 at line 35 # spent 16µs making 1 call to installer::windows::mergemodule::BEGIN@35
# spent 2µs making 1 call to UNIVERSAL::import |
36 | 2 | 54µs | 2 | 70µs | # spent 42µs (15+27) within installer::windows::mergemodule::BEGIN@36 which was called:
# once (15µs+27µs) by installer::BEGIN@74 at line 36 # spent 42µs making 1 call to installer::windows::mergemodule::BEGIN@36
# spent 27µs making 1 call to Exporter::import |
37 | 2 | 60µs | 2 | 18µs | # spent 16µs (14+2) within installer::windows::mergemodule::BEGIN@37 which was called:
# once (14µs+2µs) by installer::BEGIN@74 at line 37 # spent 16µs making 1 call to installer::windows::mergemodule::BEGIN@37
# spent 2µs making 1 call to UNIVERSAL::import |
38 | 2 | 56µs | 2 | 22µs | # spent 19µs (17+3) within installer::windows::mergemodule::BEGIN@38 which was called:
# once (17µs+3µs) by installer::BEGIN@74 at line 38 # spent 19µs making 1 call to installer::windows::mergemodule::BEGIN@38
# spent 2µs making 1 call to UNIVERSAL::import |
39 | 2 | 54µs | 2 | 23µs | # spent 20µs (18+3) within installer::windows::mergemodule::BEGIN@39 which was called:
# once (18µs+3µs) by installer::BEGIN@74 at line 39 # spent 20µs making 1 call to installer::windows::mergemodule::BEGIN@39
# spent 3µs making 1 call to UNIVERSAL::import |
40 | 2 | 54µs | 2 | 20µs | # spent 19µs (17+1) within installer::windows::mergemodule::BEGIN@40 which was called:
# once (17µs+1µs) by installer::BEGIN@74 at line 40 # spent 19µs making 1 call to installer::windows::mergemodule::BEGIN@40
# spent 2µs making 1 call to UNIVERSAL::import |
41 | 2 | 55µs | 2 | 24µs | # spent 22µs (20+2) within installer::windows::mergemodule::BEGIN@41 which was called:
# once (20µs+2µs) by installer::BEGIN@74 at line 41 # spent 22µs making 1 call to installer::windows::mergemodule::BEGIN@41
# spent 2µs making 1 call to UNIVERSAL::import |
42 | 2 | 52µs | 2 | 18µs | # spent 16µs (14+2) within installer::windows::mergemodule::BEGIN@42 which was called:
# once (14µs+2µs) by installer::BEGIN@74 at line 42 # spent 16µs making 1 call to installer::windows::mergemodule::BEGIN@42
# spent 2µs making 1 call to UNIVERSAL::import |
43 | 2 | 17.4ms | 2 | 20µs | # spent 18µs (17+2) within installer::windows::mergemodule::BEGIN@43 which was called:
# once (17µs+2µs) by installer::BEGIN@74 at line 43 # spent 18µs making 1 call to installer::windows::mergemodule::BEGIN@43
# spent 2µs making 1 call to UNIVERSAL::import |
44 | |||||
45 | ################################################################# | ||||
46 | # Merging the Windows MergeModules into the msi database. | ||||
47 | ################################################################# | ||||
48 | |||||
49 | sub merge_mergemodules_into_msi_database | ||||
50 | # spent 101s (13.0ms+101) within installer::windows::mergemodule::merge_mergemodules_into_msi_database which was called:
# once (13.0ms+101s) by installer::run at line 1710 of /cygdrive/c/lo/libo-master/instsetoo_native/util/C:/lo/libo-master/solenv/bin/modules/installer.pm | ||||
51 | 5 | 25µs | my ($mergemodules, $filesref, $msifilename, $languagestringref, $allvariables, $includepatharrayref, $allupdatesequences, $allupdatelastsequences, $allupdatediskids) = @_; | ||
52 | |||||
53 | my $domerge = 0; | ||||
54 | if (( $#{$mergemodules} > -1 ) && ( ! $installer::globals::patch ) && ( ! $installer::globals::languagepack ) && ( ! $installer::globals::helppack )) { $domerge = 1; } | ||||
55 | |||||
56 | 14 | 40µs | if ( $domerge ) | ||
57 | { | ||||
58 | 1 | 210µs | installer::logger::include_header_into_logfile("Merging merge modules into msi database"); # spent 210µs making 1 call to installer::logger::include_header_into_logfile | ||
59 | 1 | 18µs | installer::logger::print_message( "... merging msm files into msi database ... \n" ); # spent 18µs making 1 call to installer::logger::print_message | ||
60 | 1 | 124µs | installer::logger::include_timestamp_into_logfile("\nPerformance Info: MergeModule into msi database, start"); # spent 124µs making 1 call to installer::logger::include_timestamp_into_logfile | ||
61 | |||||
62 | my $msidb = "msidb.exe"; # Has to be in the path | ||||
63 | my $cabinetfile = "MergeModule.CABinet"; # the name of each cabinet file in a merge file | ||||
64 | my $infoline = ""; | ||||
65 | my $systemcall = ""; | ||||
66 | my $returnvalue = ""; | ||||
67 | |||||
68 | # 1. Analyzing the MergeModule (has only to be done once) | ||||
69 | # a. -> Extracting cabinet file: msidb.exe -d <msmfile> -x MergeModule.CABinet | ||||
70 | # b. -> Number of files in cabinet file: msidb.exe -d <msmfile> -f <directory> -e File | ||||
71 | # c. -> List of components: msidb.exe -d <msmfile> -f <directory> -e Component | ||||
72 | |||||
73 | 13 | 33µs | if ( ! $installer::globals::mergemodules_analyzed ) | ||
74 | { | ||||
75 | 1 | 114µs | installer::logger::include_timestamp_into_logfile("\nPerformance Info: Analyzing MergeModules, start"); # spent 114µs making 1 call to installer::logger::include_timestamp_into_logfile | ||
76 | $infoline = "Analyzing all Merge Modules\n\n"; | ||||
77 | push( @installer::globals::logfileinfo, $infoline); | ||||
78 | |||||
79 | %installer::globals::mergemodules = (); | ||||
80 | |||||
81 | 1 | 466ms | my $mergemoduledir = installer::systemactions::create_directories("mergefiles", $languagestringref); # spent 466ms making 1 call to installer::systemactions::create_directories | ||
82 | |||||
83 | my $mergemodule; | ||||
84 | foreach $mergemodule ( @{$mergemodules} ) | ||||
85 | { | ||||
86 | 370 | 4.92s | my $filename = $mergemodule->{'Name'}; | ||
87 | 5 | 213µs | my $mergefile = installer::scriptitems::get_sourcepath_from_filename_and_includepath(\$filename, $includepatharrayref, 1); # spent 213µs making 5 calls to installer::scriptitems::get_sourcepath_from_filename_and_includepath, avg 43µs/call | ||
88 | |||||
89 | 5 | 1.13ms | if ( ! -f $$mergefile ) { installer::exiter::exit_program("ERROR: msm file not found: $filename !", "merge_mergemodules_into_msi_database"); } # spent 1.13ms making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 225µs/call | ||
90 | my $completesource = $$mergefile; | ||||
91 | |||||
92 | my $mergegid = $mergemodule->{'gid'}; | ||||
93 | my $workdir = $mergemoduledir . $installer::globals::separator . $mergegid; | ||||
94 | 10 | 6.05ms | if ( ! -d $workdir ) { installer::systemactions::create_directory($workdir); } # spent 5.05ms making 5 calls to installer::systemactions::create_directory, avg 1.01ms/call
# spent 1.00ms making 5 calls to installer::windows::mergemodule::CORE:ftdir, avg 200µs/call | ||
95 | |||||
96 | $infoline = "Analyzing Merge Module: $filename\n"; | ||||
97 | push( @installer::globals::logfileinfo, $infoline); | ||||
98 | |||||
99 | # copy msm file into working directory | ||||
100 | my $completedest = $workdir . $installer::globals::separator . $filename; | ||||
101 | 5 | 71.2ms | installer::systemactions::copy_one_file($completesource, $completedest); # spent 71.2ms making 5 calls to installer::systemactions::copy_one_file, avg 14.2ms/call | ||
102 | 5 | 914µs | if ( ! -f $completedest ) { installer::exiter::exit_program("ERROR: msm file not found: $completedest !", "merge_mergemodules_into_msi_database"); } # spent 914µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 183µs/call | ||
103 | |||||
104 | # changing directory | ||||
105 | 5 | 92µs | my $from = cwd(); # spent 92µs making 5 calls to Cwd::__ANON__[Cwd.pm:406], avg 18µs/call | ||
106 | my $to = $workdir; | ||||
107 | 5 | 626µs | chdir($to); # spent 626µs making 5 calls to installer::windows::mergemodule::CORE:chdir, avg 125µs/call | ||
108 | |||||
109 | # remove an existing cabinet file | ||||
110 | 5 | 953µs | if ( -f $cabinetfile ) { unlink($cabinetfile); } # spent 953µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 191µs/call | ||
111 | |||||
112 | # exclude cabinet file | ||||
113 | $systemcall = $msidb . " -d " . $filename . " -x " . $cabinetfile; | ||||
114 | 5 | 2.46s | $returnvalue = system($systemcall); # spent 2.46s making 5 calls to installer::windows::mergemodule::CORE:system, avg 493ms/call | ||
115 | |||||
116 | $infoline = "Systemcall: $systemcall\n"; | ||||
117 | push( @installer::globals::logfileinfo, $infoline); | ||||
118 | |||||
119 | 10 | 25µs | if ($returnvalue) | ||
120 | { | ||||
121 | $infoline = "ERROR: Could not execute $systemcall !\n"; | ||||
122 | push( @installer::globals::logfileinfo, $infoline); | ||||
123 | installer::exiter::exit_program("ERROR: Could not extract cabinet file from merge file: $completedest !", "merge_mergemodules_into_msi_database"); | ||||
124 | } | ||||
125 | else | ||||
126 | { | ||||
127 | $infoline = "Success: Executed $systemcall successfully!\n"; | ||||
128 | push( @installer::globals::logfileinfo, $infoline); | ||||
129 | } | ||||
130 | |||||
131 | # exclude tables from mergefile | ||||
132 | # Attention: All listed tables have to exist in the database. If they not exist, an error window pops up | ||||
133 | # and the return value of msidb.exe is not zero. The error window makes it impossible to check the existence | ||||
134 | # of a table with the help of the return value. | ||||
135 | # Solution: Export of all tables by using "*" . Some tables must exist (File Component Directory), other | ||||
136 | # tables do not need to exist (MsiAssembly). | ||||
137 | |||||
138 | 15 | 222µs | 5 | 85µs | if ( $^O =~ /cygwin/i ) { # spent 85µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 17µs/call |
139 | # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) | ||||
140 | my $localworkdir = $workdir; | ||||
141 | 5 | 135µs | $localworkdir =~ s/\//\\\\/g; # spent 135µs making 5 calls to installer::windows::mergemodule::CORE:subst, avg 27µs/call | ||
142 | $systemcall = $msidb . " -d " . $filename . " -f " . $localworkdir . " -e \\\*"; | ||||
143 | } | ||||
144 | else | ||||
145 | { | ||||
146 | $systemcall = $msidb . " -d " . $filename . " -f " . $workdir . " -e \*"; | ||||
147 | } | ||||
148 | |||||
149 | 5 | 2.44s | $returnvalue = system($systemcall); # spent 2.44s making 5 calls to installer::windows::mergemodule::CORE:system, avg 489ms/call | ||
150 | |||||
151 | $infoline = "Systemcall: $systemcall\n"; | ||||
152 | push( @installer::globals::logfileinfo, $infoline); | ||||
153 | |||||
154 | 10 | 33µs | if ($returnvalue) | ||
155 | { | ||||
156 | $infoline = "ERROR: Could not execute $systemcall !\n"; | ||||
157 | push( @installer::globals::logfileinfo, $infoline); | ||||
158 | installer::exiter::exit_program("ERROR: Could not exclude tables from merge file: $completedest !", "merge_mergemodules_into_msi_database"); | ||||
159 | } | ||||
160 | else | ||||
161 | { | ||||
162 | $infoline = "Success: Executed $systemcall successfully!\n"; | ||||
163 | push( @installer::globals::logfileinfo, $infoline); | ||||
164 | } | ||||
165 | |||||
166 | # Determining files | ||||
167 | my $idtfilename = "File.idt"; # must exist | ||||
168 | 5 | 1.16ms | if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: File \"$idtfilename\" not found in directory \"$workdir\" !", "merge_mergemodules_into_msi_database"); } # spent 1.16ms making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 232µs/call | ||
169 | 5 | 1.97ms | my $filecontent = installer::files::read_file($idtfilename); # spent 1.97ms making 5 calls to installer::files::read_file, avg 395µs/call | ||
170 | my @file_idt_content = (); | ||||
171 | my $filecounter = 0; | ||||
172 | my %mergefilesequence = (); | ||||
173 | 180 | 686µs | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||
174 | { | ||||
175 | 15 | 14µs | if ( $i <= 2 ) { next; } # ignoring first three lines | ||
176 | 33 | 121µs | if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines # spent 121µs making 33 calls to installer::windows::mergemodule::CORE:match, avg 4µs/call | ||
177 | $filecounter++; | ||||
178 | push(@file_idt_content, ${$filecontent}[$i]); | ||||
179 | 99 | 218µs | 33 | 174µs | if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.+?)\t(.+?)\t(.+?)\t(.*?)\t(.*?)\t(.*?)\t(\d+?)\s*$/ ) # spent 174µs making 33 calls to installer::windows::mergemodule::CORE:match, avg 5µs/call |
180 | { | ||||
181 | my $filename = $1; | ||||
182 | my $filesequence = $8; | ||||
183 | $mergefilesequence{$filename} = $filesequence; | ||||
184 | } | ||||
185 | else | ||||
186 | { | ||||
187 | my $linecount = $i + 1; | ||||
188 | installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "merge_mergemodules_into_msi_database"); | ||||
189 | } | ||||
190 | } | ||||
191 | |||||
192 | # Determining components | ||||
193 | $idtfilename = "Component.idt"; # must exist | ||||
194 | 5 | 696µs | if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: File \"$idtfilename\" not found in directory \"$workdir\" !", "merge_mergemodules_into_msi_database"); } # spent 696µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 139µs/call | ||
195 | 5 | 1.39ms | $filecontent = installer::files::read_file($idtfilename); # spent 1.39ms making 5 calls to installer::files::read_file, avg 278µs/call | ||
196 | my %componentnames = (); | ||||
197 | 54 | 249µs | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||
198 | { | ||||
199 | 15 | 9µs | if ( $i <= 2 ) { next; } # ignoring first three lines | ||
200 | 13 | 31µs | if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines # spent 31µs making 13 calls to installer::windows::mergemodule::CORE:match, avg 2µs/call | ||
201 | 13 | 38µs | if ( ${$filecontent}[$i] =~ /^\s*(\S+)\s+/ ) { $componentnames{$1} = 1; } # spent 38µs making 13 calls to installer::windows::mergemodule::CORE:match, avg 3µs/call | ||
202 | } | ||||
203 | |||||
204 | # Determining directories | ||||
205 | $idtfilename = "Directory.idt"; # must exist | ||||
206 | 5 | 492µs | if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: File \"$idtfilename\" not found in directory \"$workdir\" !", "merge_mergemodules_into_msi_database"); } # spent 492µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 98µs/call | ||
207 | 5 | 1.37ms | $filecontent = installer::files::read_file($idtfilename); # spent 1.37ms making 5 calls to installer::files::read_file, avg 273µs/call | ||
208 | my %mergedirectories = (); | ||||
209 | 117 | 501µs | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||
210 | { | ||||
211 | 15 | 8µs | if ( $i <= 2 ) { next; } # ignoring first three lines | ||
212 | 34 | 55µs | if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines # spent 55µs making 34 calls to installer::windows::mergemodule::CORE:match, avg 2µs/call | ||
213 | 34 | 73µs | if ( ${$filecontent}[$i] =~ /^\s*(\S+)\s+/ ) { $mergedirectories{$1} = 1; } # spent 73µs making 34 calls to installer::windows::mergemodule::CORE:match, avg 2µs/call | ||
214 | } | ||||
215 | |||||
216 | # Determining assemblies | ||||
217 | $idtfilename = "MsiAssembly.idt"; # does not need to exist | ||||
218 | my $hasmsiassemblies = 0; | ||||
219 | my %mergeassemblies = (); | ||||
220 | 12 | 61µs | 5 | 591µs | if ( -f $idtfilename ) # spent 591µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 118µs/call |
221 | { | ||||
222 | 4 | 985µs | $filecontent = installer::files::read_file($idtfilename); # spent 985µs making 4 calls to installer::files::read_file, avg 246µs/call | ||
223 | $hasmsiassemblies = 1; | ||||
224 | 24 | 93µs | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||
225 | { | ||||
226 | 12 | 8µs | if ( $i <= 2 ) { next; } # ignoring first three lines | ||
227 | 4 | 11µs | if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines # spent 11µs making 4 calls to installer::windows::mergemodule::CORE:match, avg 3µs/call | ||
228 | 4 | 12µs | if ( ${$filecontent}[$i] =~ /^\s*(\S+)\s+/ ) { $mergeassemblies{$1} = 1; } # spent 12µs making 4 calls to installer::windows::mergemodule::CORE:match, avg 3µs/call | ||
229 | } | ||||
230 | } | ||||
231 | |||||
232 | # It is possible, that other tables have to be checked here. This happens, if tables in the | ||||
233 | # merge module have to know the "Feature" or the "Directory", under which the content of the | ||||
234 | # msm file is integrated into the msi database. | ||||
235 | |||||
236 | # Determining name of cabinet file in installation set | ||||
237 | my $cabfilename = $mergemodule->{'Cabfilename'}; | ||||
238 | if ( $cabfilename ) { installer::packagelist::resolve_packagevariables(\$cabfilename, $allvariables, 0); } | ||||
239 | |||||
240 | # Analyzing styles | ||||
241 | # Flag REMOVE_FILE_TABLE is required for msvc9 Merge-Module, because otherwise msidb.exe | ||||
242 | # fails during integration of msm file into msi database. | ||||
243 | |||||
244 | my $styles = ""; | ||||
245 | my $removefiletable = 0; | ||||
246 | if ( $mergemodule->{'Styles'} ) { $styles = $mergemodule->{'Styles'}; } | ||||
247 | 5 | 4µs | if ( $styles =~ /\bREMOVE_FILE_TABLE\b/ ) { $removefiletable = 1; } # spent 4µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 760ns/call | ||
248 | |||||
249 | if ( $removefiletable ) | ||||
250 | { | ||||
251 | my $removeworkdir = $workdir . $installer::globals::separator . "remove_file_idt"; | ||||
252 | if ( ! -d $removeworkdir ) { installer::systemactions::create_directory($removeworkdir); } | ||||
253 | my $completeremovedest = $removeworkdir . $installer::globals::separator . $filename; | ||||
254 | installer::systemactions::copy_one_file($completedest, $completeremovedest); | ||||
255 | if ( ! -f $completeremovedest ) { installer::exiter::exit_program("ERROR: msm file not found: $completeremovedest !", "merge_mergemodules_into_msi_database"); } | ||||
256 | |||||
257 | # Unpacking msm file | ||||
258 | if ( $^O =~ /cygwin/i ) { | ||||
259 | # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) | ||||
260 | my $localcompleteremovedest = $completeremovedest; | ||||
261 | my $localremoveworkdir = $removeworkdir; | ||||
262 | $localcompleteremovedest =~ s/\//\\\\/g; | ||||
263 | $localremoveworkdir =~ s/\//\\\\/g; | ||||
264 | $systemcall = $msidb . " -d " . $localcompleteremovedest . " -f " . $localremoveworkdir . " -e \\\*"; | ||||
265 | } | ||||
266 | else | ||||
267 | { | ||||
268 | $systemcall = $msidb . " -d " . $completeremovedest . " -f " . $removeworkdir . " -e \*"; | ||||
269 | } | ||||
270 | |||||
271 | $returnvalue = system($systemcall); | ||||
272 | |||||
273 | my $idtfilename = $removeworkdir . $installer::globals::separator . "File.idt"; | ||||
274 | if ( -f $idtfilename ) { unlink $idtfilename; } | ||||
275 | unlink $completeremovedest; | ||||
276 | |||||
277 | # Packing msm file without "File.idt" | ||||
278 | if ( $^O =~ /cygwin/i ) { | ||||
279 | # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) | ||||
280 | my $localcompleteremovedest = $completeremovedest; | ||||
281 | my $localremoveworkdir = $removeworkdir; | ||||
282 | $localcompleteremovedest =~ s/\//\\\\/g; | ||||
283 | $localremoveworkdir =~ s/\//\\\\/g; | ||||
284 | $systemcall = $msidb . " -c -d " . $localcompleteremovedest . " -f " . $localremoveworkdir . " -i \\\*"; | ||||
285 | } | ||||
286 | else | ||||
287 | { | ||||
288 | $systemcall = $msidb . " -c -d " . $completeremovedest . " -f " . $removeworkdir . " -i \*"; | ||||
289 | } | ||||
290 | $returnvalue = system($systemcall); | ||||
291 | |||||
292 | # Using this msm file for merging | ||||
293 | if ( -f $completeremovedest ) { $completedest = $completeremovedest; } | ||||
294 | else { installer::exiter::exit_program("ERROR: Could not find msm file without File.idt: $completeremovedest !", "merge_mergemodules_into_msi_database"); } | ||||
295 | } | ||||
296 | |||||
297 | # Saving MergeModule info | ||||
298 | |||||
299 | my %onemergemodulehash = (); | ||||
300 | $onemergemodulehash{'mergefilepath'} = $completedest; | ||||
301 | $onemergemodulehash{'workdir'} = $workdir; | ||||
302 | $onemergemodulehash{'cabinetfile'} = $workdir . $installer::globals::separator . $cabinetfile; | ||||
303 | $onemergemodulehash{'filenumber'} = $filecounter; | ||||
304 | $onemergemodulehash{'componentnames'} = \%componentnames; | ||||
305 | $onemergemodulehash{'componentcondition'} = $mergemodule->{'ComponentCondition'}; | ||||
306 | $onemergemodulehash{'cabfilename'} = $cabfilename; | ||||
307 | $onemergemodulehash{'feature'} = $mergemodule->{'Feature'}; | ||||
308 | $onemergemodulehash{'rootdir'} = $mergemodule->{'RootDir'}; | ||||
309 | $onemergemodulehash{'name'} = $mergemodule->{'Name'}; | ||||
310 | $onemergemodulehash{'mergefilesequence'} = \%mergefilesequence; | ||||
311 | $onemergemodulehash{'mergeassemblies'} = \%mergeassemblies; | ||||
312 | $onemergemodulehash{'mergedirectories'} = \%mergedirectories; | ||||
313 | $onemergemodulehash{'hasmsiassemblies'} = $hasmsiassemblies; | ||||
314 | $onemergemodulehash{'removefiletable'} = $removefiletable; | ||||
315 | $onemergemodulehash{'fileidtcontent'} = \@file_idt_content; | ||||
316 | |||||
317 | $installer::globals::mergemodules{$mergegid} = \%onemergemodulehash; | ||||
318 | |||||
319 | # Collecting all cab files, to copy them into installation set | ||||
320 | if ( $cabfilename ) { $installer::globals::copy_msm_files{$cabfilename} = $onemergemodulehash{'cabinetfile'}; } | ||||
321 | |||||
322 | 5 | 596µs | chdir($from); # spent 596µs making 5 calls to installer::windows::mergemodule::CORE:chdir, avg 119µs/call | ||
323 | } | ||||
324 | |||||
325 | $infoline = "All Merge Modules successfully analyzed\n"; | ||||
326 | push( @installer::globals::logfileinfo, $infoline); | ||||
327 | |||||
328 | $installer::globals::mergemodules_analyzed = 1; | ||||
329 | 1 | 214µs | installer::logger::include_timestamp_into_logfile("\nPerformance Info: Analyzing MergeModules, stop"); # spent 214µs making 1 call to installer::logger::include_timestamp_into_logfile | ||
330 | |||||
331 | $infoline = "\n"; | ||||
332 | push( @installer::globals::logfileinfo, $infoline); | ||||
333 | } | ||||
334 | |||||
335 | # 2. Change msi database (has to be done for every msi database -> for every language) | ||||
336 | # a. Merge msm file into msi database: msidb.exe -d <msifile> -m <mergefile> | ||||
337 | # b. Extracting tables from msi database: msidb.exe -d <msifile> -f <directory> -e File Media, ... | ||||
338 | # c. Changing content of msi database in tables: File, Media, Directory, FeatureComponent | ||||
339 | # d. Including tables into msi database: msidb.exe -d <msifile> -f <directory> -i File Media, ... | ||||
340 | # e. Copying cabinet file into installation set (later) | ||||
341 | |||||
342 | my $counter = 0; | ||||
343 | my $mergemodulegid; | ||||
344 | foreach $mergemodulegid (keys %installer::globals::mergemodules) | ||||
345 | { | ||||
346 | 385 | 44.3s | my $mergemodulehash = $installer::globals::mergemodules{$mergemodulegid}; | ||
347 | $counter++; | ||||
348 | |||||
349 | 5 | 684µs | installer::logger::include_header_into_logfile("Merging Module: $mergemodulehash->{'name'}"); # spent 684µs making 5 calls to installer::logger::include_header_into_logfile, avg 137µs/call | ||
350 | 5 | 104µs | installer::logger::print_message( "\t... $mergemodulehash->{'name'} ... \n" ); # spent 104µs making 5 calls to installer::logger::print_message, avg 21µs/call | ||
351 | |||||
352 | 5 | 144µs | $msifilename = installer::converter::make_path_conform($msifilename); # spent 144µs making 5 calls to installer::converter::make_path_conform, avg 29µs/call | ||
353 | my $workdir = $msifilename; | ||||
354 | 5 | 234µs | installer::pathanalyzer::get_path_from_fullqualifiedname(\$workdir); # spent 234µs making 5 calls to installer::pathanalyzer::get_path_from_fullqualifiedname, avg 47µs/call | ||
355 | |||||
356 | # changing directory | ||||
357 | 5 | 78µs | my $from = cwd(); # spent 78µs making 5 calls to Cwd::__ANON__[Cwd.pm:406], avg 16µs/call | ||
358 | my $to = $workdir; | ||||
359 | 5 | 637µs | chdir($to); # spent 637µs making 5 calls to installer::windows::mergemodule::CORE:chdir, avg 127µs/call | ||
360 | |||||
361 | # Saving original msi database | ||||
362 | 5 | 112ms | installer::systemactions::copy_one_file($msifilename, "$msifilename\.$counter"); # spent 112ms making 5 calls to installer::systemactions::copy_one_file, avg 22.3ms/call | ||
363 | |||||
364 | # Merging msm file, this is the "real" merge command | ||||
365 | |||||
366 | 5 | 1.03ms | installer::logger::include_timestamp_into_logfile("\nPerformance Info: Before merging database"); # spent 1.03ms making 5 calls to installer::logger::include_timestamp_into_logfile, avg 206µs/call | ||
367 | |||||
368 | 25 | 316µs | 5 | 29µs | if ( $^O =~ /cygwin/i ) { # spent 29µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 6µs/call |
369 | # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) | ||||
370 | my $localmergemodulepath = $mergemodulehash->{'mergefilepath'}; | ||||
371 | my $localmsifilename = $msifilename; | ||||
372 | 5 | 119µs | $localmergemodulepath =~ s/\//\\\\/g; # spent 119µs making 5 calls to installer::windows::mergemodule::CORE:subst, avg 24µs/call | ||
373 | 5 | 82µs | $localmsifilename =~ s/\//\\\\/g; # spent 82µs making 5 calls to installer::windows::mergemodule::CORE:subst, avg 16µs/call | ||
374 | $systemcall = $msidb . " -d " . $localmsifilename . " -m " . $localmergemodulepath; | ||||
375 | } | ||||
376 | else | ||||
377 | { | ||||
378 | $systemcall = $msidb . " -d " . $msifilename . " -m " . $mergemodulehash->{'mergefilepath'}; | ||||
379 | } | ||||
380 | 5 | 3.68s | $returnvalue = system($systemcall); # spent 3.68s making 5 calls to installer::windows::mergemodule::CORE:system, avg 737ms/call | ||
381 | |||||
382 | $infoline = "Systemcall: $systemcall\n"; | ||||
383 | push( @installer::globals::logfileinfo, $infoline); | ||||
384 | |||||
385 | 10 | 31µs | if ($returnvalue) | ||
386 | { | ||||
387 | $infoline = "ERROR: Could not execute $systemcall . Returnvalue: $returnvalue!\n"; | ||||
388 | push( @installer::globals::logfileinfo, $infoline); | ||||
389 | installer::exiter::exit_program("ERROR: Could not merge msm file into database: $mergemodulehash->{'mergefilepath'} !", "merge_mergemodules_into_msi_database"); | ||||
390 | } | ||||
391 | else | ||||
392 | { | ||||
393 | $infoline = "Success: Executed $systemcall successfully!\n"; | ||||
394 | push( @installer::globals::logfileinfo, $infoline); | ||||
395 | } | ||||
396 | |||||
397 | 5 | 1.10ms | installer::logger::include_timestamp_into_logfile("\nPerformance Info: After merging database"); # spent 1.10ms making 5 calls to installer::logger::include_timestamp_into_logfile, avg 221µs/call | ||
398 | |||||
399 | # Saving original idt files | ||||
400 | 9 | 15.1ms | if ( -f "File.idt" ) { installer::systemactions::rename_one_file("File.idt", "old.File.idt.$counter"); } # spent 13.8ms making 4 calls to installer::systemactions::rename_one_file, avg 3.46ms/call
# spent 1.22ms making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 244µs/call | ||
401 | 9 | 3.37ms | if ( -f "Media.idt" ) { installer::systemactions::rename_one_file("Media.idt", "old.Media.idt.$counter"); } # spent 2.68ms making 4 calls to installer::systemactions::rename_one_file, avg 671µs/call
# spent 692µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 138µs/call | ||
402 | 5 | 942µs | if ( -f "Directory.idt" ) { installer::systemactions::rename_one_file("Directory.idt", "old.Directory.idt.$counter"); } # spent 942µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 188µs/call | ||
403 | 9 | 3.08ms | if ( -f "Director.idt" ) { installer::systemactions::rename_one_file("Director.idt", "old.Director.idt.$counter"); } # spent 2.56ms making 4 calls to installer::systemactions::rename_one_file, avg 640µs/call
# spent 519µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 104µs/call | ||
404 | 5 | 923µs | if ( -f "FeatureComponents.idt" ) { installer::systemactions::rename_one_file("FeatureComponents.idt", "old.FeatureComponents.idt.$counter"); } # spent 923µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 185µs/call | ||
405 | 9 | 10.2ms | if ( -f "FeatureC.idt" ) { installer::systemactions::rename_one_file("FeatureC.idt", "old.FeatureC.idt.$counter"); } # spent 9.69ms making 4 calls to installer::systemactions::rename_one_file, avg 2.42ms/call
# spent 516µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 103µs/call | ||
406 | 5 | 882µs | if ( -f "MsiAssembly.idt" ) { installer::systemactions::rename_one_file("MsiAssembly.idt", "old.MsiAssembly.idt.$counter"); } # spent 882µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 176µs/call | ||
407 | 9 | 3.72ms | if ( -f "MsiAssem.idt" ) { installer::systemactions::rename_one_file("MsiAssem.idt", "old.MsiAssem.idt.$counter"); } # spent 3.20ms making 4 calls to installer::systemactions::rename_one_file, avg 801µs/call
# spent 516µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 103µs/call | ||
408 | 9 | 17.0ms | if ( -f "Componen.idt" ) { installer::systemactions::rename_one_file("Componen.idt", "old.Componen.idt.$counter"); } # spent 16.5ms making 4 calls to installer::systemactions::rename_one_file, avg 4.12ms/call
# spent 531µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 106µs/call | ||
409 | |||||
410 | # Extracting tables | ||||
411 | |||||
412 | 5 | 940µs | installer::logger::include_timestamp_into_logfile("\nPerformance Info: Before extracting tables"); # spent 940µs making 5 calls to installer::logger::include_timestamp_into_logfile, avg 188µs/call | ||
413 | |||||
414 | my $workingtables = "File Media Directory FeatureComponents"; # required tables | ||||
415 | # Optional tables can be added now | ||||
416 | if ( $mergemodulehash->{'hasmsiassemblies'} ) { $workingtables = $workingtables . " MsiAssembly"; } | ||||
417 | if ( $mergemodulehash->{'componentcondition'} ) { $workingtables = $workingtables . " Component"; } | ||||
418 | |||||
419 | # Table "Feature" has to be exported, but it is not necessary to import it. | ||||
420 | 25 | 289µs | 5 | 27µs | if ( $^O =~ /cygwin/i ) { # spent 27µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 5µs/call |
421 | # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) | ||||
422 | my $localmsifilename = $msifilename; | ||||
423 | my $localworkdir = $workdir; | ||||
424 | 5 | 111µs | $localmsifilename =~ s/\//\\\\/g; # spent 111µs making 5 calls to installer::windows::mergemodule::CORE:subst, avg 22µs/call | ||
425 | 5 | 79µs | $localworkdir =~ s/\//\\\\/g; # spent 79µs making 5 calls to installer::windows::mergemodule::CORE:subst, avg 16µs/call | ||
426 | $systemcall = $msidb . " -d " . $localmsifilename . " -f " . $localworkdir . " -e " . "Feature " . $workingtables; | ||||
427 | } | ||||
428 | else | ||||
429 | { | ||||
430 | $systemcall = $msidb . " -d " . $msifilename . " -f " . $workdir . " -e " . "Feature " . $workingtables; | ||||
431 | } | ||||
432 | 5 | 34.0s | $returnvalue = system($systemcall); # spent 34.0s making 5 calls to installer::windows::mergemodule::CORE:system, avg 6.80s/call | ||
433 | |||||
434 | $infoline = "Systemcall: $systemcall\n"; | ||||
435 | push( @installer::globals::logfileinfo, $infoline); | ||||
436 | |||||
437 | 10 | 32µs | if ($returnvalue) | ||
438 | { | ||||
439 | $infoline = "ERROR: Could not execute $systemcall !\n"; | ||||
440 | push( @installer::globals::logfileinfo, $infoline); | ||||
441 | installer::exiter::exit_program("ERROR: Could not exclude tables from msi database: $msifilename !", "merge_mergemodules_into_msi_database"); | ||||
442 | } | ||||
443 | else | ||||
444 | { | ||||
445 | $infoline = "Success: Executed $systemcall successfully!\n"; | ||||
446 | push( @installer::globals::logfileinfo, $infoline); | ||||
447 | } | ||||
448 | |||||
449 | 5 | 1.11ms | installer::logger::include_timestamp_into_logfile("\nPerformance Info: After extracting tables"); # spent 1.11ms making 5 calls to installer::logger::include_timestamp_into_logfile, avg 222µs/call | ||
450 | |||||
451 | # Using 8+3 table names, that are used, when tables are integrated into database. The export of tables | ||||
452 | # creates idt-files, that have long names. | ||||
453 | |||||
454 | 10 | 10.4ms | if ( -f "Directory.idt" ) { installer::systemactions::rename_one_file("Directory.idt", "Director.idt"); } # spent 9.32ms making 5 calls to installer::systemactions::rename_one_file, avg 1.86ms/call
# spent 1.09ms making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 219µs/call | ||
455 | 10 | 21.7ms | if ( -f "FeatureComponents.idt" ) { installer::systemactions::rename_one_file("FeatureComponents.idt", "FeatureC.idt"); } # spent 21.0ms making 5 calls to installer::systemactions::rename_one_file, avg 4.20ms/call
# spent 657µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 131µs/call | ||
456 | 9 | 3.72ms | if ( -f "MsiAssembly.idt" ) { installer::systemactions::rename_one_file("MsiAssembly.idt", "MsiAssem.idt"); } # spent 3.16ms making 4 calls to installer::systemactions::rename_one_file, avg 791µs/call
# spent 556µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 111µs/call | ||
457 | 10 | 32.2ms | if ( -f "Component.idt" ) { installer::systemactions::rename_one_file("Component.idt", "Componen.idt"); } # spent 31.7ms making 5 calls to installer::systemactions::rename_one_file, avg 6.35ms/call
# spent 470µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 94µs/call | ||
458 | |||||
459 | # Changing content of tables: File, Media, Directory, FeatureComponent, MsiAssembly, Component | ||||
460 | 5 | 893µs | installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing Media table"); # spent 893µs making 5 calls to installer::logger::include_timestamp_into_logfile, avg 179µs/call | ||
461 | 5 | 5.22ms | change_media_table($mergemodulehash, $workdir, $mergemodulegid, $allupdatelastsequences, $allupdatediskids); # spent 5.22ms making 5 calls to installer::windows::mergemodule::change_media_table, avg 1.04ms/call | ||
462 | 5 | 590µs | installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing File table"); # spent 590µs making 5 calls to installer::logger::include_timestamp_into_logfile, avg 118µs/call | ||
463 | 5 | 12.1s | $filesref = change_file_table($mergemodulehash, $workdir, $allupdatesequences, $includepatharrayref, $filesref, $mergemodulegid); # spent 12.1s making 5 calls to installer::windows::mergemodule::change_file_table, avg 2.42s/call | ||
464 | 5 | 1.09ms | installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing FeatureComponent table"); # spent 1.09ms making 5 calls to installer::logger::include_timestamp_into_logfile, avg 218µs/call | ||
465 | 5 | 264ms | change_featurecomponent_table($mergemodulehash, $workdir); # spent 264ms making 5 calls to installer::windows::mergemodule::change_featurecomponent_table, avg 52.7ms/call | ||
466 | 5 | 1.06ms | installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing Directory table"); # spent 1.06ms making 5 calls to installer::logger::include_timestamp_into_logfile, avg 213µs/call | ||
467 | 5 | 54µs | change_directory_table($mergemodulehash, $workdir); # spent 54µs making 5 calls to installer::windows::mergemodule::change_directory_table, avg 11µs/call | ||
468 | 8 | 30µs | if ( $mergemodulehash->{'hasmsiassemblies'} ) | ||
469 | { | ||||
470 | 4 | 450µs | installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing MsiAssembly table"); # spent 450µs making 4 calls to installer::logger::include_timestamp_into_logfile, avg 112µs/call | ||
471 | 4 | 5.80ms | change_msiassembly_table($mergemodulehash, $workdir); # spent 5.80ms making 4 calls to installer::windows::mergemodule::change_msiassembly_table, avg 1.45ms/call | ||
472 | } | ||||
473 | |||||
474 | 10 | 40µs | if ( $mergemodulehash->{'componentcondition'} ) | ||
475 | { | ||||
476 | 5 | 607µs | installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing Component table"); # spent 607µs making 5 calls to installer::logger::include_timestamp_into_logfile, avg 121µs/call | ||
477 | 5 | 3.87s | change_component_table($mergemodulehash, $workdir); # spent 3.87s making 5 calls to installer::windows::mergemodule::change_component_table, avg 774ms/call | ||
478 | } | ||||
479 | |||||
480 | # msidb.exe does not merge InstallExecuteSequence, AdminExecuteSequence and AdvtExecuteSequence. Instead it creates | ||||
481 | # new tables ModuleInstallExecuteSequence, ModuleAdminExecuteSequence and ModuleAdvtExecuteSequence that need to be | ||||
482 | # merged into the three ExecuteSequences with the following process (also into InstallUISequence.idt). | ||||
483 | |||||
484 | # Saving original idt files | ||||
485 | 9 | 5.00ms | if ( -f "InstallE.idt" ) { installer::systemactions::rename_one_file("InstallE.idt", "old.InstallE.idt.$counter"); } # spent 3.82ms making 4 calls to installer::systemactions::rename_one_file, avg 955µs/call
# spent 1.18ms making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 236µs/call | ||
486 | 9 | 3.29ms | if ( -f "InstallU.idt" ) { installer::systemactions::rename_one_file("InstallU.idt", "old.InstallU.idt.$counter"); } # spent 2.66ms making 4 calls to installer::systemactions::rename_one_file, avg 666µs/call
# spent 624µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 125µs/call | ||
487 | 9 | 3.30ms | if ( -f "AdminExe.idt" ) { installer::systemactions::rename_one_file("AdminExe.idt", "old.AdminExe.idt.$counter"); } # spent 2.75ms making 4 calls to installer::systemactions::rename_one_file, avg 688µs/call
# spent 545µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 109µs/call | ||
488 | 9 | 3.08ms | if ( -f "AdvtExec.idt" ) { installer::systemactions::rename_one_file("AdvtExec.idt", "old.AdvtExec.idt.$counter"); } # spent 2.54ms making 4 calls to installer::systemactions::rename_one_file, avg 635µs/call
# spent 541µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 108µs/call | ||
489 | 9 | 3.15ms | if ( -f "ModuleInstallExecuteSequence.idt" ) { installer::systemactions::rename_one_file("ModuleInstallExecuteSequence.idt", "old.ModuleInstallExecuteSequence.idt.$counter"); } # spent 2.60ms making 4 calls to installer::systemactions::rename_one_file, avg 650µs/call
# spent 554µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 111µs/call | ||
490 | 9 | 3.19ms | if ( -f "ModuleAdminExecuteSequence.idt" ) { installer::systemactions::rename_one_file("ModuleAdminExecuteSequence.idt", "old.ModuleAdminExecuteSequence.idt.$counter"); } # spent 2.64ms making 4 calls to installer::systemactions::rename_one_file, avg 660µs/call
# spent 549µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 110µs/call | ||
491 | 9 | 3.39ms | if ( -f "ModuleAdvtExecuteSequence.idt" ) { installer::systemactions::rename_one_file("ModuleAdvtExecuteSequence.idt", "old.ModuleAdvtExecuteSequence.idt.$counter"); } # spent 2.84ms making 4 calls to installer::systemactions::rename_one_file, avg 711µs/call
# spent 547µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 109µs/call | ||
492 | |||||
493 | # Extracting tables | ||||
494 | my $moduleexecutetables = "ModuleInstallExecuteSequence ModuleAdminExecuteSequence ModuleAdvtExecuteSequence"; # new tables | ||||
495 | my $executetables = "InstallExecuteSequence InstallUISequence AdminExecuteSequence AdvtExecuteSequence"; # tables to be merged | ||||
496 | |||||
497 | |||||
498 | 25 | 301µs | 5 | 60µs | if ( $^O =~ /cygwin/i ) { # spent 60µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 12µs/call |
499 | # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) | ||||
500 | my $localmsifilename = $msifilename; | ||||
501 | my $localworkdir = $workdir; | ||||
502 | 5 | 127µs | $localmsifilename =~ s/\//\\\\/g; # spent 127µs making 5 calls to installer::windows::mergemodule::CORE:subst, avg 25µs/call | ||
503 | 5 | 76µs | $localworkdir =~ s/\//\\\\/g; # spent 76µs making 5 calls to installer::windows::mergemodule::CORE:subst, avg 15µs/call | ||
504 | $systemcall = $msidb . " -d " . $localmsifilename . " -f " . $localworkdir . " -e " . "Feature " . $moduleexecutetables; | ||||
505 | } | ||||
506 | else | ||||
507 | { | ||||
508 | $systemcall = $msidb . " -d " . $msifilename . " -f " . $workdir . " -e " . "Feature " . $moduleexecutetables; | ||||
509 | } | ||||
510 | 5 | 3.30s | $returnvalue = system($systemcall); # spent 3.30s making 5 calls to installer::windows::mergemodule::CORE:system, avg 659ms/call | ||
511 | |||||
512 | 25 | 376µs | 5 | 586µs | if ( $^O =~ /cygwin/i ) { # spent 586µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 117µs/call |
513 | # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) | ||||
514 | my $localmsifilename = $msifilename; | ||||
515 | my $localworkdir = $workdir; | ||||
516 | 5 | 166µs | $localmsifilename =~ s/\//\\\\/g; # spent 166µs making 5 calls to installer::windows::mergemodule::CORE:subst, avg 33µs/call | ||
517 | 5 | 79µs | $localworkdir =~ s/\//\\\\/g; # spent 79µs making 5 calls to installer::windows::mergemodule::CORE:subst, avg 16µs/call | ||
518 | $systemcall = $msidb . " -d " . $localmsifilename . " -f " . $localworkdir . " -e " . "Feature " . $executetables; | ||||
519 | } | ||||
520 | else | ||||
521 | { | ||||
522 | $systemcall = $msidb . " -d " . $msifilename . " -f " . $workdir . " -e " . "Feature " . $executetables; | ||||
523 | } | ||||
524 | 5 | 3.34s | $returnvalue = system($systemcall); # spent 3.34s making 5 calls to installer::windows::mergemodule::CORE:system, avg 667ms/call | ||
525 | |||||
526 | # Using 8+3 table names, that are used, when tables are integrated into database. The export of tables | ||||
527 | # creates idt-files, that have long names. | ||||
528 | |||||
529 | 10 | 7.73ms | if ( -f "InstallExecuteSequence.idt" ) { installer::systemactions::rename_one_file("InstallExecuteSequence.idt", "InstallE.idt"); } # spent 6.64ms making 5 calls to installer::systemactions::rename_one_file, avg 1.33ms/call
# spent 1.09ms making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 219µs/call | ||
530 | 10 | 5.98ms | if ( -f "InstallUISequence.idt" ) { installer::systemactions::rename_one_file("InstallUISequence.idt", "InstallU.idt"); } # spent 5.36ms making 5 calls to installer::systemactions::rename_one_file, avg 1.07ms/call
# spent 625µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 125µs/call | ||
531 | 10 | 4.36ms | if ( -f "AdminExecuteSequence.idt" ) { installer::systemactions::rename_one_file("AdminExecuteSequence.idt", "AdminExe.idt"); } # spent 3.83ms making 5 calls to installer::systemactions::rename_one_file, avg 766µs/call
# spent 535µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 107µs/call | ||
532 | 10 | 3.74ms | if ( -f "AdvtExecuteSequence.idt" ) { installer::systemactions::rename_one_file("AdvtExecuteSequence.idt", "AdvtExec.idt"); } # spent 3.27ms making 5 calls to installer::systemactions::rename_one_file, avg 655µs/call
# spent 462µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 92µs/call | ||
533 | |||||
534 | # Merging content of tables ModuleInstallExecuteSequence, ModuleAdminExecuteSequence and ModuleAdvtExecuteSequence | ||||
535 | # into tables InstallExecuteSequence, AdminExecuteSequence and AdvtExecuteSequence | ||||
536 | 20 | 101µs | 5 | 468µs | if ( -f "ModuleInstallExecuteSequence.idt" ) # spent 468µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 94µs/call |
537 | { | ||||
538 | 5 | 996µs | installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing InstallExecuteSequence table"); # spent 996µs making 5 calls to installer::logger::include_timestamp_into_logfile, avg 199µs/call | ||
539 | 5 | 22.8ms | change_executesequence_table($mergemodulehash, $workdir, "InstallE.idt", "ModuleInstallExecuteSequence.idt"); # spent 22.8ms making 5 calls to installer::windows::mergemodule::change_executesequence_table, avg 4.57ms/call | ||
540 | 5 | 641µs | installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing InstallUISequence table"); # spent 641µs making 5 calls to installer::logger::include_timestamp_into_logfile, avg 128µs/call | ||
541 | 5 | 13.0ms | change_executesequence_table($mergemodulehash, $workdir, "InstallU.idt", "ModuleInstallExecuteSequence.idt"); # spent 13.0ms making 5 calls to installer::windows::mergemodule::change_executesequence_table, avg 2.60ms/call | ||
542 | } | ||||
543 | |||||
544 | 10 | 37µs | 5 | 475µs | if ( -f "ModuleAdminExecuteSequence.idt" ) # spent 475µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 95µs/call |
545 | { | ||||
546 | 5 | 603µs | installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing AdminExecuteSequence table"); # spent 603µs making 5 calls to installer::logger::include_timestamp_into_logfile, avg 121µs/call | ||
547 | 5 | 8.19ms | change_executesequence_table($mergemodulehash, $workdir, "AdminExe.idt", "ModuleAdminExecuteSequence.idt"); # spent 8.19ms making 5 calls to installer::windows::mergemodule::change_executesequence_table, avg 1.64ms/call | ||
548 | } | ||||
549 | |||||
550 | 10 | 33µs | 5 | 469µs | if ( -f "ModuleAdvtExecuteSequence.idt" ) # spent 469µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 94µs/call |
551 | { | ||||
552 | 5 | 588µs | installer::logger::include_timestamp_into_logfile("\nPerformance Info: Changing AdvtExecuteSequence table"); # spent 588µs making 5 calls to installer::logger::include_timestamp_into_logfile, avg 118µs/call | ||
553 | 5 | 7.71ms | change_executesequence_table($mergemodulehash, $workdir, "AdvtExec.idt", "ModuleAdvtExecuteSequence.idt"); # spent 7.71ms making 5 calls to installer::windows::mergemodule::change_executesequence_table, avg 1.54ms/call | ||
554 | } | ||||
555 | |||||
556 | 5 | 583µs | installer::logger::include_timestamp_into_logfile("\nPerformance Info: All tables edited"); # spent 583µs making 5 calls to installer::logger::include_timestamp_into_logfile, avg 117µs/call | ||
557 | |||||
558 | # Including tables into msi database | ||||
559 | |||||
560 | 5 | 532µs | installer::logger::include_timestamp_into_logfile("\nPerformance Info: Before including tables"); # spent 532µs making 5 calls to installer::logger::include_timestamp_into_logfile, avg 106µs/call | ||
561 | |||||
562 | 25 | 305µs | 5 | 27µs | if ( $^O =~ /cygwin/i ) { # spent 27µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 5µs/call |
563 | # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) | ||||
564 | my $localmsifilename = $msifilename; | ||||
565 | my $localworkdir = $workdir; | ||||
566 | 5 | 101µs | $localmsifilename =~ s/\//\\\\/g; # spent 101µs making 5 calls to installer::windows::mergemodule::CORE:subst, avg 20µs/call | ||
567 | 5 | 76µs | $localworkdir =~ s/\//\\\\/g; # spent 76µs making 5 calls to installer::windows::mergemodule::CORE:subst, avg 15µs/call | ||
568 | foreach $table (split / /, $workingtables . ' ' . $executetables) { | ||||
569 | 245 | 34.9s | $systemcall = $msidb . " -d " . $localmsifilename . " -f " . $localworkdir . " -i " . $table; | ||
570 | 49 | 34.9s | my $retval = system($systemcall); # spent 34.9s making 49 calls to installer::windows::mergemodule::CORE:system, avg 712ms/call | ||
571 | $infoline = "Systemcall returned $retval: $systemcall\n"; | ||||
572 | push( @installer::globals::logfileinfo, $infoline); | ||||
573 | $returnvalue |= $retval; | ||||
574 | } | ||||
575 | } | ||||
576 | else | ||||
577 | { | ||||
578 | $systemcall = $msidb . " -d " . $msifilename . " -f " . $workdir . " -i " . $workingtables. " " . $executetables; | ||||
579 | $returnvalue = system($systemcall); | ||||
580 | $infoline = "Systemcall: $systemcall\n"; | ||||
581 | push( @installer::globals::logfileinfo, $infoline); | ||||
582 | |||||
583 | } | ||||
584 | |||||
585 | 10 | 22µs | if ($returnvalue) | ||
586 | { | ||||
587 | $infoline = "ERROR: Could not execute $systemcall !\n"; | ||||
588 | push( @installer::globals::logfileinfo, $infoline); | ||||
589 | installer::exiter::exit_program("ERROR: Could not include tables into msi database: $msifilename !", "merge_mergemodules_into_msi_database"); | ||||
590 | } | ||||
591 | else | ||||
592 | { | ||||
593 | $infoline = "Success: Executed $systemcall successfully!\n"; | ||||
594 | push( @installer::globals::logfileinfo, $infoline); | ||||
595 | } | ||||
596 | |||||
597 | 5 | 1.04ms | installer::logger::include_timestamp_into_logfile("\nPerformance Info: After including tables"); # spent 1.04ms making 5 calls to installer::logger::include_timestamp_into_logfile, avg 208µs/call | ||
598 | |||||
599 | 5 | 1.09ms | chdir($from); # spent 1.09ms making 5 calls to installer::windows::mergemodule::CORE:chdir, avg 217µs/call | ||
600 | } | ||||
601 | |||||
602 | 1 | 1µs | if ( ! $installer::globals::mergefiles_added_into_collector ) { $installer::globals::mergefiles_added_into_collector = 1; } # Now all mergemodules are merged for one language. | ||
603 | |||||
604 | 1 | 112µs | installer::logger::include_timestamp_into_logfile("\nPerformance Info: MergeModule into msi database, stop"); # spent 112µs making 1 call to installer::logger::include_timestamp_into_logfile | ||
605 | } | ||||
606 | |||||
607 | return $filesref; | ||||
608 | } | ||||
609 | |||||
610 | ######################################################################### | ||||
611 | # Analyzing the content of the media table. | ||||
612 | ######################################################################### | ||||
613 | |||||
614 | sub analyze_media_file | ||||
615 | # spent 373µs (320+54) within installer::windows::mergemodule::analyze_media_file which was called 5 times, avg 75µs/call:
# 5 times (320µs+54µs) by installer::windows::mergemodule::change_media_table at line 859, avg 75µs/call | ||||
616 | 35 | 112µs | my ($filecontent, $workdir) = @_; | ||
617 | |||||
618 | my %filehash = (); | ||||
619 | my $linecount = 0; | ||||
620 | my $counter = 0; | ||||
621 | my $filename = "Media.idt"; | ||||
622 | |||||
623 | 30 | 136µs | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||
624 | { | ||||
625 | 15 | 13µs | if ( $i <= 2 ) { next; } # ignoring first three lines | ||
626 | 5 | 24µs | if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines # spent 24µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 5µs/call | ||
627 | 45 | 123µs | 5 | 30µs | if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.+?)\t(.+?)\t(.+?)\t(.+?)\t(.*?)\s*$/ ) # spent 30µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 6µs/call |
628 | { | ||||
629 | my %line = (); | ||||
630 | # Format: DiskId LastSequence DiskPrompt Cabinet VolumeLabel Source | ||||
631 | $line{'DiskId'} = $1; | ||||
632 | $line{'LastSequence'} = $2; | ||||
633 | $line{'DiskPrompt'} = $3; | ||||
634 | $line{'Cabinet'} = $4; | ||||
635 | $line{'VolumeLabel'} = $5; | ||||
636 | $line{'Source'} = $6; | ||||
637 | |||||
638 | $counter++; | ||||
639 | $filehash{$counter} = \%line; | ||||
640 | } | ||||
641 | else | ||||
642 | { | ||||
643 | $linecount = $i + 1; | ||||
644 | installer::exiter::exit_program("ERROR: Unknown line format in table \"$filename\" in \"$workdir\" (line $linecount) !", "analyze_media_file"); | ||||
645 | } | ||||
646 | } | ||||
647 | |||||
648 | return \%filehash; | ||||
649 | } | ||||
650 | |||||
651 | ######################################################################### | ||||
652 | # Setting the DiskID for the new cabinet file | ||||
653 | ######################################################################### | ||||
654 | |||||
655 | sub get_diskid | ||||
656 | { | ||||
657 | my ($mediafile, $allupdatediskids, $cabfilename) = @_; | ||||
658 | |||||
659 | my $diskid = 0; | ||||
660 | my $line; | ||||
661 | |||||
662 | if (( $installer::globals::updatedatabase ) && ( exists($allupdatediskids->{$cabfilename}) )) | ||||
663 | { | ||||
664 | $diskid = $allupdatediskids->{$cabfilename}; | ||||
665 | } | ||||
666 | else | ||||
667 | { | ||||
668 | foreach $line ( keys %{$mediafile} ) | ||||
669 | { | ||||
670 | if ( $mediafile->{$line}->{'DiskId'} > $diskid ) { $diskid = $mediafile->{$line}->{'DiskId'}; } | ||||
671 | } | ||||
672 | |||||
673 | $diskid++; | ||||
674 | } | ||||
675 | |||||
676 | return $diskid; | ||||
677 | } | ||||
678 | |||||
679 | ######################################################################### | ||||
680 | # Setting the global LastSequence variable | ||||
681 | ######################################################################### | ||||
682 | |||||
683 | sub set_current_last_sequence | ||||
684 | # spent 98µs within installer::windows::mergemodule::set_current_last_sequence which was called 5 times, avg 20µs/call:
# 5 times (98µs+0s) by installer::windows::mergemodule::change_media_table at line 860, avg 20µs/call | ||||
685 | 25 | 89µs | my ($mediafile) = @_; | ||
686 | |||||
687 | my $lastsequence = 0; | ||||
688 | my $line; | ||||
689 | foreach $line ( keys %{$mediafile} ) | ||||
690 | { | ||||
691 | 5 | 28µs | if ( $mediafile->{$line}->{'LastSequence'} > $lastsequence ) { $lastsequence = $mediafile->{$line}->{'LastSequence'}; } | ||
692 | } | ||||
693 | |||||
694 | $installer::globals::lastsequence_before_merge = $lastsequence; | ||||
695 | } | ||||
696 | |||||
697 | ######################################################################### | ||||
698 | # Setting the LastSequence for the new cabinet file | ||||
699 | ######################################################################### | ||||
700 | |||||
701 | sub get_lastsequence | ||||
702 | { | ||||
703 | my ($mergemodulehash, $allupdatelastsequences) = @_; | ||||
704 | |||||
705 | my $lastsequence = 0; | ||||
706 | |||||
707 | if (( $installer::globals::updatedatabase ) && ( exists($allupdatelastsequences->{$mergemodulehash->{'cabfilename'}}) )) | ||||
708 | { | ||||
709 | $lastsequence = $allupdatelastsequences->{$mergemodulehash->{'cabfilename'}}; | ||||
710 | } | ||||
711 | else | ||||
712 | { | ||||
713 | $lastsequence = $installer::globals::lastsequence_before_merge + $mergemodulehash->{'filenumber'}; | ||||
714 | } | ||||
715 | |||||
716 | return $lastsequence; | ||||
717 | } | ||||
718 | |||||
719 | ######################################################################### | ||||
720 | # Setting the DiskPrompt for the new cabinet file | ||||
721 | ######################################################################### | ||||
722 | |||||
723 | sub get_diskprompt | ||||
724 | { | ||||
725 | my ($mediafile) = @_; | ||||
726 | |||||
727 | my $diskprompt = ""; | ||||
728 | my $line; | ||||
729 | foreach $line ( keys %{$mediafile} ) | ||||
730 | { | ||||
731 | if ( exists($mediafile->{$line}->{'DiskPrompt'}) ) | ||||
732 | { | ||||
733 | $diskprompt = $mediafile->{$line}->{'DiskPrompt'}; | ||||
734 | last; | ||||
735 | } | ||||
736 | } | ||||
737 | |||||
738 | return $diskprompt; | ||||
739 | } | ||||
740 | |||||
741 | ######################################################################### | ||||
742 | # Setting the VolumeLabel for the new cabinet file | ||||
743 | ######################################################################### | ||||
744 | |||||
745 | sub get_volumelabel | ||||
746 | { | ||||
747 | my ($mediafile) = @_; | ||||
748 | |||||
749 | my $volumelabel = ""; | ||||
750 | my $line; | ||||
751 | foreach $line ( keys %{$mediafile} ) | ||||
752 | { | ||||
753 | if ( exists($mediafile->{$line}->{'VolumeLabel'}) ) | ||||
754 | { | ||||
755 | $volumelabel = $mediafile->{$line}->{'VolumeLabel'}; | ||||
756 | last; | ||||
757 | } | ||||
758 | } | ||||
759 | |||||
760 | return $volumelabel; | ||||
761 | } | ||||
762 | |||||
763 | ######################################################################### | ||||
764 | # Setting the Source for the new cabinet file | ||||
765 | ######################################################################### | ||||
766 | |||||
767 | sub get_source | ||||
768 | { | ||||
769 | my ($mediafile) = @_; | ||||
770 | |||||
771 | my $source = ""; | ||||
772 | my $line; | ||||
773 | foreach $line ( keys %{$mediafile} ) | ||||
774 | { | ||||
775 | if ( exists($mediafile->{$line}->{'Source'}) ) | ||||
776 | { | ||||
777 | $diskprompt = $mediafile->{$line}->{'Source'}; | ||||
778 | last; | ||||
779 | } | ||||
780 | } | ||||
781 | |||||
782 | return $source; | ||||
783 | } | ||||
784 | |||||
785 | ######################################################################### | ||||
786 | # For each Merge Module one new line has to be included into the | ||||
787 | # media table. | ||||
788 | ######################################################################### | ||||
789 | |||||
790 | sub create_new_media_line | ||||
791 | { | ||||
792 | my ($mergemodulehash, $mediafile, $allupdatelastsequences, $allupdatediskids) = @_; | ||||
793 | |||||
794 | my $diskid = get_diskid($mediafile, $allupdatediskids, $mergemodulehash->{'cabfilename'}); | ||||
795 | my $lastsequence = get_lastsequence($mergemodulehash, $allupdatelastsequences); | ||||
796 | my $diskprompt = get_diskprompt($mediafile); | ||||
797 | my $cabinet = $mergemodulehash->{'cabfilename'}; | ||||
798 | my $volumelabel = get_volumelabel($mediafile); | ||||
799 | my $source = get_source($mediafile); | ||||
800 | |||||
801 | if ( $installer::globals::include_cab_in_msi ) { $cabinet = "\#" . $cabinet; } | ||||
802 | |||||
803 | my $newline = "$diskid\t$lastsequence\t$diskprompt\t$cabinet\t$volumelabel\t$source\n"; | ||||
804 | |||||
805 | return $newline; | ||||
806 | } | ||||
807 | |||||
808 | ######################################################################### | ||||
809 | # Setting the last diskid in media table. | ||||
810 | ######################################################################### | ||||
811 | |||||
812 | sub get_last_diskid | ||||
813 | # spent 63µs within installer::windows::mergemodule::get_last_diskid which was called 5 times, avg 13µs/call:
# 5 times (63µs+0s) by installer::windows::mergemodule::change_media_table at line 865, avg 13µs/call | ||||
814 | 25 | 63µs | my ($mediafile) = @_; | ||
815 | |||||
816 | my $lastdiskid = 0; | ||||
817 | my $line; | ||||
818 | foreach $line ( keys %{$mediafile} ) | ||||
819 | { | ||||
820 | 5 | 18µs | if ( $mediafile->{$line}->{'DiskId'} > $lastdiskid ) { $lastdiskid = $mediafile->{$line}->{'DiskId'}; } | ||
821 | } | ||||
822 | |||||
823 | return $lastdiskid; | ||||
824 | } | ||||
825 | |||||
826 | ######################################################################### | ||||
827 | # Setting global variable for last cab file name. | ||||
828 | ######################################################################### | ||||
829 | |||||
830 | sub set_last_cabfile_name | ||||
831 | # spent 19µs within installer::windows::mergemodule::set_last_cabfile_name which was called:
# once (19µs+0s) by installer::windows::mergemodule::change_media_table at line 866 | ||||
832 | 5 | 18µs | my ($mediafile, $lastdiskid) = @_; | ||
833 | |||||
834 | my $line; | ||||
835 | foreach $line ( keys %{$mediafile} ) | ||||
836 | { | ||||
837 | 2 | 6µs | if ( $mediafile->{$line}->{'DiskId'} == $lastdiskid ) { $installer::globals::lastcabfilename = $mediafile->{$line}->{'Cabinet'}; } | ||
838 | } | ||||
839 | my $infoline = "Setting last cabinet file: $installer::globals::lastcabfilename\n"; | ||||
840 | push( @installer::globals::logfileinfo, $infoline); | ||||
841 | } | ||||
842 | |||||
843 | ######################################################################### | ||||
844 | # In the media table the new cabinet file has to be added or the | ||||
845 | # number of the last cabinet file has to be increased. | ||||
846 | ######################################################################### | ||||
847 | |||||
848 | sub change_media_table | ||||
849 | # spent 5.22ms (602µs+4.62) within installer::windows::mergemodule::change_media_table which was called 5 times, avg 1.04ms/call:
# 5 times (602µs+4.62ms) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 461, avg 1.04ms/call | ||||
850 | 50 | 751µs | my ( $mergemodulehash, $workdir, $mergemodulegid, $allupdatelastsequences, $allupdatediskids ) = @_; | ||
851 | |||||
852 | my $infoline = "Changing content of table \"Media\"\n"; | ||||
853 | push( @installer::globals::logfileinfo, $infoline); | ||||
854 | |||||
855 | my $filename = "Media.idt"; | ||||
856 | 5 | 493µs | if ( ! -f $filename ) { installer::exiter::exit_program("ERROR: Could not find file \"$filename\" in \"$workdir\" !", "change_media_table"); } # spent 493µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 99µs/call | ||
857 | |||||
858 | 5 | 1.46ms | my $filecontent = installer::files::read_file($filename); # spent 1.46ms making 5 calls to installer::files::read_file, avg 292µs/call | ||
859 | 5 | 373µs | my $mediafile = analyze_media_file($filecontent, $workdir); # spent 373µs making 5 calls to installer::windows::mergemodule::analyze_media_file, avg 75µs/call | ||
860 | 5 | 98µs | set_current_last_sequence($mediafile); # spent 98µs making 5 calls to installer::windows::mergemodule::set_current_last_sequence, avg 20µs/call | ||
861 | |||||
862 | 20 | 80µs | if ( $installer::globals::fix_number_of_cab_files ) | ||
863 | { | ||||
864 | # Determining the line with the highest sequencenumber. That file needs to be updated. | ||||
865 | 5 | 63µs | my $lastdiskid = get_last_diskid($mediafile); # spent 63µs making 5 calls to installer::windows::mergemodule::get_last_diskid, avg 13µs/call | ||
866 | 1 | 19µs | if ( $installer::globals::lastcabfilename eq "" ) { set_last_cabfile_name($mediafile, $lastdiskid); } # spent 19µs making 1 call to installer::windows::mergemodule::set_last_cabfile_name | ||
867 | my $newmaxsequencenumber = $installer::globals::lastsequence_before_merge + $mergemodulehash->{'filenumber'}; | ||||
868 | |||||
869 | 30 | 398µs | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||
870 | { | ||||
871 | 15 | 8µs | if ( $i <= 2 ) { next; } # ignoring first three lines | ||
872 | 5 | 11µs | if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines # spent 11µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 2µs/call | ||
873 | 40 | 63µs | 10 | 266µs | if ( ${$filecontent}[$i] =~ /^\s*(\Q$lastdiskid\E\t)\Q$installer::globals::lastsequence_before_merge\E(\t.*)$/ ) # spent 244µs making 5 calls to installer::windows::mergemodule::CORE:regcomp, avg 49µs/call
# spent 22µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 4µs/call |
874 | { | ||||
875 | my $start = $1; | ||||
876 | my $final = $2; | ||||
877 | $infoline = "Merge: Old line in media table: ${$filecontent}[$i]\n"; | ||||
878 | push( @installer::globals::logfileinfo, $infoline); | ||||
879 | my $newline = $start . $newmaxsequencenumber . $final . "\n"; | ||||
880 | ${$filecontent}[$i] = $newline; | ||||
881 | $infoline = "Merge: Changed line in media table: ${$filecontent}[$i]\n"; | ||||
882 | push( @installer::globals::logfileinfo, $infoline); | ||||
883 | } | ||||
884 | } | ||||
885 | } | ||||
886 | else | ||||
887 | { | ||||
888 | # the new line is identical for all localized databases, but has to be created for each MergeModule ($mergemodulegid) | ||||
889 | if ( ! exists($installer::globals::merge_media_line{$mergemodulegid}) ) | ||||
890 | { | ||||
891 | $installer::globals::merge_media_line{$mergemodulegid} = create_new_media_line($mergemodulehash, $mediafile, $allupdatelastsequences, $allupdatediskids); | ||||
892 | } | ||||
893 | |||||
894 | $infoline = "Adding line: $installer::globals::merge_media_line{$mergemodulegid}\n"; | ||||
895 | push( @installer::globals::logfileinfo, $infoline); | ||||
896 | |||||
897 | # adding new line | ||||
898 | push(@{$filecontent}, $installer::globals::merge_media_line{$mergemodulegid}); | ||||
899 | } | ||||
900 | |||||
901 | # saving file | ||||
902 | 5 | 1.83ms | installer::files::save_file($filename, $filecontent); # spent 1.83ms making 5 calls to installer::files::save_file, avg 366µs/call | ||
903 | } | ||||
904 | |||||
905 | ######################################################################### | ||||
906 | # Putting the directory table content into a hash. | ||||
907 | ######################################################################### | ||||
908 | |||||
909 | sub analyze_directorytable_file | ||||
910 | { | ||||
911 | my ($filecontent, $idtfilename) = @_; | ||||
912 | |||||
913 | my %dirhash = (); | ||||
914 | # Iterating over the file content | ||||
915 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
916 | { | ||||
917 | if ( $i <= 2 ) { next; } # ignoring first three lines | ||||
918 | if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines | ||||
919 | if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.*?)\t(.*?)\s*$/ ) | ||||
920 | { | ||||
921 | my %line = (); | ||||
922 | # Format: Directory Directory_Parent DefaultDir | ||||
923 | $line{'Directory'} = $1; | ||||
924 | $line{'Directory_Parent'} = $2; | ||||
925 | $line{'DefaultDir'} = $3; | ||||
926 | $line{'linenumber'} = $i; # saving also the line number for direct access | ||||
927 | |||||
928 | my $uniquekey = $line{'Directory'}; | ||||
929 | $dirhash{$uniquekey} = \%line; | ||||
930 | } | ||||
931 | else | ||||
932 | { | ||||
933 | my $linecount = $i + 1; | ||||
934 | installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "analyze_directorytable_file"); | ||||
935 | } | ||||
936 | } | ||||
937 | |||||
938 | return \%dirhash; | ||||
939 | } | ||||
940 | |||||
941 | ######################################################################### | ||||
942 | # Putting the msi assembly table content into a hash. | ||||
943 | ######################################################################### | ||||
944 | |||||
945 | sub analyze_msiassemblytable_file | ||||
946 | # spent 1.46ms (1.19+270µs) within installer::windows::mergemodule::analyze_msiassemblytable_file which was called 4 times, avg 365µs/call:
# 4 times (1.19ms+270µs) by installer::windows::mergemodule::change_msiassembly_table at line 1524, avg 365µs/call | ||||
947 | 16 | 133µs | my ($filecontent, $idtfilename) = @_; | ||
948 | |||||
949 | my %assemblyhash = (); | ||||
950 | # Iterating over the file content | ||||
951 | 162 | 697µs | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||
952 | { | ||||
953 | 12 | 10µs | if ( $i <= 2 ) { next; } # ignoring first three lines | ||
954 | 50 | 88µs | if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines # spent 88µs making 50 calls to installer::windows::mergemodule::CORE:match, avg 2µs/call | ||
955 | 450 | 628µs | 50 | 182µs | if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.+?)\t(.+?)\t(.*?)\t(.*?)\s*$/ ) # spent 182µs making 50 calls to installer::windows::mergemodule::CORE:match, avg 4µs/call |
956 | { | ||||
957 | my %line = (); | ||||
958 | # Format: Component_ Feature_ File_Manifest File_Application Attributes | ||||
959 | $line{'Component'} = $1; | ||||
960 | $line{'Feature'} = $2; | ||||
961 | $line{'File_Manifest'} = $3; | ||||
962 | $line{'File_Application'} = $4; | ||||
963 | $line{'Attributes'} = $5; | ||||
964 | $line{'linenumber'} = $i; # saving also the line number for direct access | ||||
965 | |||||
966 | my $uniquekey = $line{'Component'}; | ||||
967 | $assemblyhash{$uniquekey} = \%line; | ||||
968 | } | ||||
969 | else | ||||
970 | { | ||||
971 | my $linecount = $i + 1; | ||||
972 | installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "analyze_msiassemblytable_file"); | ||||
973 | } | ||||
974 | } | ||||
975 | |||||
976 | return \%assemblyhash; | ||||
977 | } | ||||
978 | |||||
979 | ######################################################################### | ||||
980 | # Putting the file table content into a hash. | ||||
981 | ######################################################################### | ||||
982 | |||||
983 | sub analyze_filetable_file | ||||
984 | # spent 2.38s (1.96+427ms) within installer::windows::mergemodule::analyze_filetable_file which was called 5 times, avg 477ms/call:
# 5 times (1.96s+427ms) by installer::windows::mergemodule::change_file_table at line 1181, avg 477ms/call | ||||
985 | 20 | 118ms | my ( $filecontent, $idtfilename ) = @_; | ||
986 | |||||
987 | my %filehash = (); | ||||
988 | # Iterating over the file content | ||||
989 | 238617 | 1.06s | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||
990 | { | ||||
991 | 15 | 22µs | if ( $i <= 2 ) { next; } # ignoring first three lines | ||
992 | 79534 | 111ms | if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines # spent 111ms making 79534 calls to installer::windows::mergemodule::CORE:match, avg 1µs/call | ||
993 | 954408 | 1.20s | 79534 | 315ms | if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.+?)\t(.+?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.+?)\s*$/ ) # spent 315ms making 79534 calls to installer::windows::mergemodule::CORE:match, avg 4µs/call |
994 | { | ||||
995 | my %line = (); | ||||
996 | # Format: File Component_ FileName FileSize Version Language Attributes Sequence | ||||
997 | $line{'File'} = $1; | ||||
998 | $line{'Component'} = $2; | ||||
999 | $line{'FileName'} = $3; | ||||
1000 | $line{'FileSize'} = $4; | ||||
1001 | $line{'Version'} = $5; | ||||
1002 | $line{'Language'} = $6; | ||||
1003 | $line{'Attributes'} = $7; | ||||
1004 | $line{'Sequence'} = $8; | ||||
1005 | $line{'linenumber'} = $i; # saving also the line number for direct access | ||||
1006 | |||||
1007 | my $uniquekey = $line{'File'}; | ||||
1008 | $filehash{$uniquekey} = \%line; | ||||
1009 | } | ||||
1010 | else | ||||
1011 | { | ||||
1012 | my $linecount = $i + 1; | ||||
1013 | installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "analyze_filetable_file"); | ||||
1014 | } | ||||
1015 | } | ||||
1016 | |||||
1017 | return \%filehash; | ||||
1018 | } | ||||
1019 | |||||
1020 | ######################################################################### | ||||
1021 | # Creating a new line for the directory table. | ||||
1022 | ######################################################################### | ||||
1023 | |||||
1024 | sub get_new_line_for_directory_table | ||||
1025 | { | ||||
1026 | my ($dir) = @_; | ||||
1027 | |||||
1028 | my $newline = "$dir->{'Directory'}\t$dir->{'Directory_Parent'}\t$dir->{'DefaultDir'}\n"; | ||||
1029 | |||||
1030 | return $newline; | ||||
1031 | } | ||||
1032 | |||||
1033 | ######################################################################### | ||||
1034 | # Creating a new line for the file table. | ||||
1035 | ######################################################################### | ||||
1036 | |||||
1037 | sub get_new_line_for_file_table | ||||
1038 | # spent 477µs within installer::windows::mergemodule::get_new_line_for_file_table which was called 33 times, avg 14µs/call:
# 33 times (477µs+0s) by installer::windows::mergemodule::change_file_table at line 1213, avg 14µs/call | ||||
1039 | 99 | 538µs | my ($file) = @_; | ||
1040 | |||||
1041 | my $newline = "$file->{'File'}\t$file->{'Component'}\t$file->{'FileName'}\t$file->{'FileSize'}\t$file->{'Version'}\t$file->{'Language'}\t$file->{'Attributes'}\t$file->{'Sequence'}\n"; | ||||
1042 | |||||
1043 | return $newline; | ||||
1044 | } | ||||
1045 | |||||
1046 | ######################################################################### | ||||
1047 | # Creating a new line for the msiassembly table. | ||||
1048 | ######################################################################### | ||||
1049 | |||||
1050 | sub get_new_line_for_msiassembly_table | ||||
1051 | # spent 44µs within installer::windows::mergemodule::get_new_line_for_msiassembly_table which was called 4 times, avg 11µs/call:
# 4 times (44µs+0s) by installer::windows::mergemodule::change_msiassembly_table at line 1537, avg 11µs/call | ||||
1052 | 12 | 54µs | my ($assembly) = @_; | ||
1053 | |||||
1054 | my $newline = "$assembly->{'Component'}\t$assembly->{'Feature'}\t$assembly->{'File_Manifest'}\t$assembly->{'File_Application'}\t$assembly->{'Attributes'}\n"; | ||||
1055 | |||||
1056 | return $newline; | ||||
1057 | } | ||||
1058 | |||||
1059 | ######################################################################### | ||||
1060 | # Sorting the files collector, if there are files, following | ||||
1061 | # the merge module files. | ||||
1062 | ######################################################################### | ||||
1063 | |||||
1064 | sub sort_files_collector_for_sequence | ||||
1065 | { | ||||
1066 | my ($filesref) = @_; | ||||
1067 | |||||
1068 | my @sortarray = (); | ||||
1069 | my %helphash = (); | ||||
1070 | |||||
1071 | for ( my $i = 0; $i <= $#{$filesref}; $i++ ) | ||||
1072 | { | ||||
1073 | my $onefile = ${$filesref}[$i]; | ||||
1074 | if ( ! exists($onefile->{'sequencenumber'}) ) { installer::exiter::exit_program("ERROR: Could not find sequencenumber for file: $onefile->{'uniquename'} !", "sort_files_collector_for_sequence"); } | ||||
1075 | my $sequence = $onefile->{'sequencenumber'}; | ||||
1076 | $helphash{$sequence} = $onefile; | ||||
1077 | } | ||||
1078 | |||||
1079 | foreach my $seq ( sort { $a <=> $b } keys %helphash ) { push(@sortarray, $helphash{$seq}); } | ||||
1080 | |||||
1081 | return \@sortarray; | ||||
1082 | } | ||||
1083 | |||||
1084 | ######################################################################### | ||||
1085 | # In the file table "Sequence" and "Attributes" have to be changed. | ||||
1086 | ######################################################################### | ||||
1087 | |||||
1088 | sub change_file_table | ||||
1089 | # spent 12.1s (418ms+11.7) within installer::windows::mergemodule::change_file_table which was called 5 times, avg 2.42s/call:
# 5 times (418ms+11.7s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 463, avg 2.42s/call | ||||
1090 | 95 | 413ms | my ($mergemodulehash, $workdir, $allupdatesequenceshashref, $includepatharrayref, $filesref, $mergemodulegid) = @_; | ||
1091 | |||||
1092 | my $infoline = "Changing content of table \"File\"\n"; | ||||
1093 | push( @installer::globals::logfileinfo, $infoline); | ||||
1094 | |||||
1095 | my $idtfilename = "File.idt"; | ||||
1096 | 5 | 485µs | if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: Could not find file \"$idtfilename\" in \"$workdir\" !", "change_file_table"); } # spent 485µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 97µs/call | ||
1097 | |||||
1098 | 5 | 355ms | my $filecontent = installer::files::read_file($idtfilename); # spent 355ms making 5 calls to installer::files::read_file, avg 71.1ms/call | ||
1099 | |||||
1100 | # If File.idt needed to be removed before the msm database was merged into the msi database, | ||||
1101 | # now it is time to add the content into File.idt | ||||
1102 | if ( $mergemodulehash->{'removefiletable'} ) | ||||
1103 | { | ||||
1104 | for ( my $i = 0; $i <= $#{$mergemodulehash->{'fileidtcontent'}}; $i++ ) | ||||
1105 | { | ||||
1106 | push(@{$filecontent}, ${$mergemodulehash->{'fileidtcontent'}}[$i]); | ||||
1107 | } | ||||
1108 | } | ||||
1109 | |||||
1110 | # Unpacking the MergeModule.CABinet (only once) | ||||
1111 | # Unpacking into temp directory. Warning: expand.exe has problems with very long unpack directories. | ||||
1112 | |||||
1113 | 5 | 7.33ms | my $unpackdir = installer::systemactions::create_directories("cab", ""); # spent 7.33ms making 5 calls to installer::systemactions::create_directories, avg 1.47ms/call | ||
1114 | push(@installer::globals::removedirs, $unpackdir); | ||||
1115 | $unpackdir = $unpackdir . $installer::globals::separator . $mergemodulegid; | ||||
1116 | |||||
1117 | my %newfileshash = (); | ||||
1118 | 85 | 2.60s | if (( $installer::globals::fix_number_of_cab_files ) && ( ! $installer::globals::mergefiles_added_into_collector )) | ||
1119 | { | ||||
1120 | 10 | 5.62ms | if ( ! -d $unpackdir ) { installer::systemactions::create_directory($unpackdir); } # spent 4.66ms making 5 calls to installer::systemactions::create_directory, avg 933µs/call
# spent 961µs making 5 calls to installer::windows::mergemodule::CORE:ftdir, avg 192µs/call | ||
1121 | |||||
1122 | # changing directory | ||||
1123 | 5 | 84µs | my $from = cwd(); # spent 84µs making 5 calls to Cwd::__ANON__[Cwd.pm:406], avg 17µs/call | ||
1124 | my $to = $mergemodulehash->{'workdir'}; | ||||
1125 | 10 | 2.05s | 5 | 39µs | if ( $^O =~ /cygwin/i ) { # spent 39µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 8µs/call |
1126 | 5 | 2.05s | $to = qx(cygpath -u "$to"); # spent 2.05s making 5 calls to installer::windows::mergemodule::CORE:backtick, avg 411ms/call | ||
1127 | chomp $to; | ||||
1128 | } | ||||
1129 | |||||
1130 | 5 | 1.09ms | chdir($to) || die "Could not chdir to \"$to\"\n"; # spent 1.09ms making 5 calls to installer::windows::mergemodule::CORE:chdir, avg 219µs/call | ||
1131 | |||||
1132 | # Unpack the cab file, so that in can be included into the last office cabinet file. | ||||
1133 | # Not using cabarc.exe from cabsdk for unpacking cabinet files, but "expand.exe" that | ||||
1134 | # should be available on every Windows system. | ||||
1135 | |||||
1136 | $infoline = "Unpacking cabinet file: $mergemodulehash->{'cabinetfile'}\n"; | ||||
1137 | push( @installer::globals::logfileinfo, $infoline); | ||||
1138 | |||||
1139 | # Avoid the Cygwin expand command | ||||
1140 | my $expandfile = "expand.exe"; # Has to be in the path | ||||
1141 | 10 | 2.05s | 5 | 80µs | if ( $^O =~ /cygwin/i ) { # spent 80µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 16µs/call |
1142 | 5 | 2.05s | $expandfile = qx(cygpath -u "$ENV{WINDIR}"/System32/expand.exe); # spent 2.05s making 5 calls to installer::windows::mergemodule::CORE:backtick, avg 410ms/call | ||
1143 | chomp $expandfile; | ||||
1144 | } | ||||
1145 | |||||
1146 | my $cabfilename = "MergeModule.CABinet"; | ||||
1147 | |||||
1148 | my $systemcall = ""; | ||||
1149 | 15 | 2.10s | 5 | 88µs | if ( $^O =~ /cygwin/i ) { # spent 88µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 18µs/call |
1150 | 5 | 2.10s | my $localunpackdir = qx(cygpath -m "$unpackdir"); # spent 2.10s making 5 calls to installer::windows::mergemodule::CORE:backtick, avg 420ms/call | ||
1151 | chomp $localunpackdir; | ||||
1152 | $systemcall = $expandfile . " " . $cabfilename . " -F:\\\* " . $localunpackdir; | ||||
1153 | } | ||||
1154 | else | ||||
1155 | { | ||||
1156 | $systemcall = $expandfile . " " . $cabfilename . " -F:\* " . $unpackdir . " 2\>\&1"; | ||||
1157 | } | ||||
1158 | |||||
1159 | 5 | 2.59s | my $returnvalue = system($systemcall); # spent 2.59s making 5 calls to installer::windows::mergemodule::CORE:system, avg 519ms/call | ||
1160 | |||||
1161 | $infoline = "Systemcall: $systemcall\n"; | ||||
1162 | push( @installer::globals::logfileinfo, $infoline); | ||||
1163 | |||||
1164 | 10 | 33µs | if ($returnvalue) | ||
1165 | { | ||||
1166 | $infoline = "ERROR: Could not execute $systemcall !\n"; | ||||
1167 | push( @installer::globals::logfileinfo, $infoline); | ||||
1168 | installer::exiter::exit_program("ERROR: Could not extract cabinet file: $mergemodulehash->{'cabinetfile'} !", "change_file_table"); | ||||
1169 | } | ||||
1170 | else | ||||
1171 | { | ||||
1172 | $infoline = "Success: Executed $systemcall successfully!\n"; | ||||
1173 | push( @installer::globals::logfileinfo, $infoline); | ||||
1174 | } | ||||
1175 | |||||
1176 | 5 | 1.44ms | chdir($from); # spent 1.44ms making 5 calls to installer::windows::mergemodule::CORE:chdir, avg 289µs/call | ||
1177 | } | ||||
1178 | |||||
1179 | # For performance reasons creating a hash with file names and rows | ||||
1180 | # The content of File.idt is changed after every merge -> content cannot be saved in global hash | ||||
1181 | 5 | 2.38s | $merge_filetablehashref = analyze_filetable_file($filecontent, $idtfilename); # spent 2.38s making 5 calls to installer::windows::mergemodule::analyze_filetable_file, avg 477ms/call | ||
1182 | |||||
1183 | my $attributes = "16384"; # Always | ||||
1184 | |||||
1185 | my $filename; | ||||
1186 | foreach $filename (keys %{$mergemodulehash->{'mergefilesequence'}} ) | ||||
1187 | { | ||||
1188 | 528 | 1.01ms | my $mergefilesequence = $mergemodulehash->{'mergefilesequence'}->{$filename}; | ||
1189 | |||||
1190 | if ( ! exists($merge_filetablehashref->{$filename}) ) { installer::exiter::exit_program("ERROR: Could not find file \"$filename\" in \"$idtfilename\" !", "change_file_table"); } | ||||
1191 | my $filehash = $merge_filetablehashref->{$filename}; | ||||
1192 | my $linenumber = $filehash->{'linenumber'}; | ||||
1193 | |||||
1194 | # <- this line has to be changed concerning "Sequence" and "Attributes" | ||||
1195 | $filehash->{'Attributes'} = $attributes; | ||||
1196 | |||||
1197 | # If this is an update process, the sequence numbers have to be reused. | ||||
1198 | 33 | 107µs | if ( $installer::globals::updatedatabase ) | ||
1199 | { | ||||
1200 | if ( ! exists($allupdatesequenceshashref->{$filehash->{'File'}}) ) { installer::exiter::exit_program("ERROR: Sequence not defined for file \"$filehash->{'File'}\" !", "change_file_table"); } | ||||
1201 | $filehash->{'Sequence'} = $allupdatesequenceshashref->{$filehash->{'File'}}; | ||||
1202 | # Saving all mergemodule sequence numbers. This is important for creating ddf files | ||||
1203 | $installer::globals::allmergemodulefilesequences{$filehash->{'Sequence'}} = 1; | ||||
1204 | } | ||||
1205 | else | ||||
1206 | { | ||||
1207 | # Important saved data: $installer::globals::lastsequence_before_merge. | ||||
1208 | # This mechanism keeps the correct order inside the new cabinet file. | ||||
1209 | $filehash->{'Sequence'} = $filehash->{'Sequence'} + $installer::globals::lastsequence_before_merge; | ||||
1210 | } | ||||
1211 | |||||
1212 | my $oldline = ${$filecontent}[$linenumber]; | ||||
1213 | 33 | 477µs | my $newline = get_new_line_for_file_table($filehash); # spent 477µs making 33 calls to installer::windows::mergemodule::get_new_line_for_file_table, avg 14µs/call | ||
1214 | ${$filecontent}[$linenumber] = $newline; | ||||
1215 | |||||
1216 | $infoline = "Merge, replacing line:\n"; | ||||
1217 | push( @installer::globals::logfileinfo, $infoline); | ||||
1218 | $infoline = "Old: $oldline\n"; | ||||
1219 | push( @installer::globals::logfileinfo, $infoline); | ||||
1220 | $infoline = "New: $newline\n"; | ||||
1221 | push( @installer::globals::logfileinfo, $infoline); | ||||
1222 | |||||
1223 | # Adding files to the files collector (but only once) | ||||
1224 | 561 | 4.63ms | if (( $installer::globals::fix_number_of_cab_files ) && ( ! $installer::globals::mergefiles_added_into_collector )) | ||
1225 | { | ||||
1226 | # If the number of cabinet files is kept constant, | ||||
1227 | # all files from the mergemodule cabinet files will | ||||
1228 | # be integrated into the last office cabinet file | ||||
1229 | # (installer::globals::lastcabfilename). | ||||
1230 | # Therefore the files must now be added to the filescollector, | ||||
1231 | # so that they will be integrated into the ddf files. | ||||
1232 | |||||
1233 | # Problem with very long filenames -> copying to shorter filenames | ||||
1234 | my $newfilename = "f" . $filehash->{'Sequence'}; | ||||
1235 | my $completesource = $unpackdir . $installer::globals::separator . $filehash->{'File'}; | ||||
1236 | my $completedest = $unpackdir . $installer::globals::separator . $newfilename; | ||||
1237 | 33 | 88.9ms | installer::systemactions::copy_one_file($completesource, $completedest); # spent 88.9ms making 33 calls to installer::systemactions::copy_one_file, avg 2.69ms/call | ||
1238 | |||||
1239 | my $locallastcabfilename = $installer::globals::lastcabfilename; | ||||
1240 | 33 | 258µs | 66 | 413µs | if ( $locallastcabfilename =~ /^\s*\#/ ) { $locallastcabfilename =~ s/^\s*\#//; } # removing beginning hashes # spent 303µs making 33 calls to installer::windows::mergemodule::CORE:match, avg 9µs/call
# spent 110µs making 33 calls to installer::windows::mergemodule::CORE:subst, avg 3µs/call |
1241 | |||||
1242 | # Create new file hash for file collector | ||||
1243 | my %newfile = (); | ||||
1244 | $newfile{'sequencenumber'} = $filehash->{'Sequence'}; | ||||
1245 | $newfile{'assignedsequencenumber'} = $filehash->{'Sequence'}; | ||||
1246 | $newfile{'cabinet'} = $locallastcabfilename; | ||||
1247 | $newfile{'sourcepath'} = $completedest; | ||||
1248 | $newfile{'componentname'} = $filehash->{'Component'}; | ||||
1249 | $newfile{'uniquename'} = $filehash->{'File'}; | ||||
1250 | $newfile{'Name'} = $filehash->{'File'}; | ||||
1251 | |||||
1252 | # Saving in globals sequence hash | ||||
1253 | $installer::globals::uniquefilenamesequence{$filehash->{'File'}} = $filehash->{'Sequence'}; | ||||
1254 | |||||
1255 | 33 | 2.88ms | if ( ! -f $newfile{'sourcepath'} ) { installer::exiter::exit_program("ERROR: File \"$newfile{'sourcepath'}\" must exist!", "change_file_table"); } # spent 2.88ms making 33 calls to installer::windows::mergemodule::CORE:ftfile, avg 87µs/call | ||
1256 | |||||
1257 | # Collecting all new files. Attention: This files must be included into files collector in correct order! | ||||
1258 | $newfileshash{$filehash->{'Sequence'}} = \%newfile; | ||||
1259 | # push(@{$filesref}, \%newfile); -> this is not the correct order | ||||
1260 | } | ||||
1261 | } | ||||
1262 | |||||
1263 | # Now the files can be added to the files collector | ||||
1264 | # In the case of an update process, there can be new files, that have to be added after the merge module files. | ||||
1265 | # Warning: In multilingual installation sets, the files only have to be added once to the files collector! | ||||
1266 | |||||
1267 | 10 | 189µs | if ( ! $installer::globals::mergefiles_added_into_collector ) | ||
1268 | { | ||||
1269 | 33 | 49µs | 5 | 107µs | foreach my $localsequence ( sort { $a <=> $b } keys %newfileshash ) { push(@{$filesref}, $newfileshash{$localsequence}); } # spent 107µs making 5 calls to installer::windows::mergemodule::CORE:sort, avg 21µs/call |
1270 | if ( $installer::globals::newfilesexist ) { $filesref = sort_files_collector_for_sequence($filesref); } | ||||
1271 | # $installer::globals::mergefiles_added_into_collector = 1; -> Not yet. Only if all mergemodules are merged for one language. | ||||
1272 | } | ||||
1273 | |||||
1274 | # Saving the idt file (for every language) | ||||
1275 | 5 | 40.8ms | installer::files::save_file($idtfilename, $filecontent); # spent 40.8ms making 5 calls to installer::files::save_file, avg 8.16ms/call | ||
1276 | |||||
1277 | return $filesref; | ||||
1278 | } | ||||
1279 | |||||
1280 | ######################################################################### | ||||
1281 | # Reading the file "Director.idt". The Directory, that is defined in scp | ||||
1282 | # has to be defined in this table. | ||||
1283 | ######################################################################### | ||||
1284 | |||||
1285 | sub collect_directories | ||||
1286 | { | ||||
1287 | my $idtfilename = "Director.idt"; | ||||
1288 | my $filecontent = installer::files::read_file($idtfilename); | ||||
1289 | |||||
1290 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
1291 | { | ||||
1292 | if ( $i <= 2 ) { next; } # ignoring first three lines | ||||
1293 | if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines | ||||
1294 | # Format: Directory Directory_Parent DefaultDir | ||||
1295 | if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.*?)\t(.*?)\s*$/ ) | ||||
1296 | { | ||||
1297 | $installer::globals::merge_alldirectory_hash{$1} = 1; | ||||
1298 | } | ||||
1299 | else | ||||
1300 | { | ||||
1301 | my $linecount = $i + 1; | ||||
1302 | installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "collect_directories"); | ||||
1303 | } | ||||
1304 | } | ||||
1305 | } | ||||
1306 | |||||
1307 | ######################################################################### | ||||
1308 | # Reading the file "Feature.idt". The Feature, that is defined in scp | ||||
1309 | # has to be defined in this table. | ||||
1310 | ######################################################################### | ||||
1311 | |||||
1312 | sub collect_feature | ||||
1313 | # spent 31.4ms (16.9+14.5) within installer::windows::mergemodule::collect_feature which was called:
# once (16.9ms+14.5ms) by installer::windows::mergemodule::change_featurecomponent_table at line 1356 | ||||
1314 | 4 | 2.76ms | my $idtfilename = "Feature.idt"; | ||
1315 | 1 | 170µs | if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: Could not find file \"$idtfilename\" in \"$workdir\" !", "collect_feature"); } # spent 170µs making 1 call to installer::windows::mergemodule::CORE:ftfile | ||
1316 | 1 | 6.93ms | my $filecontent = installer::files::read_file($idtfilename); # spent 6.93ms making 1 call to installer::files::read_file | ||
1317 | |||||
1318 | 4662 | 21.7ms | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||
1319 | { | ||||
1320 | 3 | 2µs | if ( $i <= 2 ) { next; } # ignoring first three lines | ||
1321 | 1553 | 1.77ms | if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines # spent 1.77ms making 1553 calls to installer::windows::mergemodule::CORE:match, avg 1µs/call | ||
1322 | # Format: Feature Feature_Parent Title Description Display Level Directory_ Attributes | ||||
1323 | 1553 | 5.63ms | if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) # spent 5.63ms making 1553 calls to installer::windows::mergemodule::CORE:match, avg 4µs/call | ||
1324 | { | ||||
1325 | $installer::globals::merge_allfeature_hash{$1} = 1; | ||||
1326 | } | ||||
1327 | else | ||||
1328 | { | ||||
1329 | my $linecount = $i + 1; | ||||
1330 | installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "collect_feature"); | ||||
1331 | } | ||||
1332 | } | ||||
1333 | } | ||||
1334 | |||||
1335 | ######################################################################### | ||||
1336 | # In the featurecomponent table, the new connections have to be added. | ||||
1337 | ######################################################################### | ||||
1338 | |||||
1339 | sub change_featurecomponent_table | ||||
1340 | # spent 264ms (19.6+244) within installer::windows::mergemodule::change_featurecomponent_table which was called 5 times, avg 52.7ms/call:
# 5 times (19.6ms+244ms) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 465, avg 52.7ms/call | ||||
1341 | 60 | 20.8ms | my ($mergemodulehash, $workdir) = @_; | ||
1342 | |||||
1343 | my $infoline = "Changing content of table \"FeatureComponents\"\n"; | ||||
1344 | push( @installer::globals::logfileinfo, $infoline); | ||||
1345 | |||||
1346 | my $idtfilename = "FeatureC.idt"; | ||||
1347 | 5 | 1.37ms | if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: Could not find file \"$idtfilename\" in \"$workdir\" !", "change_featurecomponent_table"); } # spent 1.37ms making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 274µs/call | ||
1348 | |||||
1349 | 5 | 191ms | my $filecontent = installer::files::read_file($idtfilename); # spent 191ms making 5 calls to installer::files::read_file, avg 38.3ms/call | ||
1350 | |||||
1351 | # Simply adding for each new component one line. The Feature has to be defined in scp project. | ||||
1352 | my $feature = $mergemodulehash->{'feature'}; | ||||
1353 | |||||
1354 | 2 | 8µs | if ( ! $installer::globals::mergefeaturecollected ) | ||
1355 | { | ||||
1356 | 1 | 31.4ms | collect_feature(); # putting content into hash %installer::globals::merge_allfeature_hash # spent 31.4ms making 1 call to installer::windows::mergemodule::collect_feature | ||
1357 | $installer::globals::mergefeaturecollected = 1; | ||||
1358 | } | ||||
1359 | |||||
1360 | if ( ! exists($installer::globals::merge_allfeature_hash{$feature}) ) | ||||
1361 | { | ||||
1362 | installer::exiter::exit_program("ERROR: Unknown feature defined in scp: \"$feature\" . Not defined in table \"Feature\" !", "change_featurecomponent_table"); | ||||
1363 | } | ||||
1364 | |||||
1365 | my $component; | ||||
1366 | foreach $component ( keys %{$mergemodulehash->{'componentnames'}} ) | ||||
1367 | { | ||||
1368 | 52 | 82µs | my $line = "$feature\t$component\n"; | ||
1369 | push(@{$filecontent}, $line); | ||||
1370 | $infoline = "Adding line: $line\n"; | ||||
1371 | push( @installer::globals::logfileinfo, $infoline); | ||||
1372 | } | ||||
1373 | |||||
1374 | # saving file | ||||
1375 | 5 | 20.0ms | installer::files::save_file($idtfilename, $filecontent); # spent 20.0ms making 5 calls to installer::files::save_file, avg 4.00ms/call | ||
1376 | } | ||||
1377 | |||||
1378 | ############################################################################### | ||||
1379 | # In the components table, the conditions of merge modules should be updated | ||||
1380 | ############################################################################### | ||||
1381 | |||||
1382 | sub change_component_table | ||||
1383 | # spent 3.87s (1.14+2.73) within installer::windows::mergemodule::change_component_table which was called 5 times, avg 774ms/call:
# 5 times (1.14s+2.73s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 477, avg 774ms/call | ||||
1384 | 40 | 110ms | my ($mergemodulehash, $workdir) = @_; | ||
1385 | |||||
1386 | my $infoline = "Changing content of table \"Component\"\n"; | ||||
1387 | push( @installer::globals::logfileinfo, $infoline); | ||||
1388 | |||||
1389 | my $idtfilename = "Componen.idt"; | ||||
1390 | 5 | 753µs | if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: Could not find file \"$idtfilename\" in \"$workdir\" !", "change_component_table"); } # spent 753µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 151µs/call | ||
1391 | |||||
1392 | 5 | 201ms | my $filecontent = installer::files::read_file($idtfilename); # spent 201ms making 5 calls to installer::files::read_file, avg 40.3ms/call | ||
1393 | |||||
1394 | 90704 | 107ms | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||
1395 | { | ||||
1396 | my $component; | ||||
1397 | foreach $component ( keys %{$mergemodulehash->{'componentnames'}} ) | ||||
1398 | { | ||||
1399 | 117935 | 3.42s | 235844 | 2.50s | if ( ${$filecontent}[$i] =~ /^\s*$component/) # spent 2.40s making 117922 calls to installer::windows::mergemodule::CORE:regcomp, avg 20µs/call
# spent 101ms making 117922 calls to installer::windows::mergemodule::CORE:match, avg 860ns/call |
1400 | { | ||||
1401 | 39 | 147µs | 13 | 214µs | if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.*?)\t(.+?)\t(.+?)\t(.*?)\t(.*?)\s*$/ ) # spent 214µs making 13 calls to installer::windows::mergemodule::CORE:match, avg 16µs/call |
1402 | { | ||||
1403 | $infoline = "Adding condition ($mergemodulehash->{'componentcondition'}) from scp2 to component $1\n"; | ||||
1404 | push( @installer::globals::logfileinfo, $infoline); | ||||
1405 | 39 | 174µs | if ($5) | ||
1406 | { | ||||
1407 | $infoline = "Old condition: $5\nNew condition: ($5) AND ($mergemodulehash->{'componentcondition'})\n"; | ||||
1408 | push( @installer::globals::logfileinfo, $infoline); | ||||
1409 | ${$filecontent}[$i] = "$1\t$2\t$3\t$4\t($5) AND ($mergemodulehash->{'componentcondition'})\t$6\n"; | ||||
1410 | } | ||||
1411 | else | ||||
1412 | { | ||||
1413 | $infoline = "Old condition: <none>\nNew condition: $mergemodulehash->{'componentcondition'}\n"; | ||||
1414 | push( @installer::globals::logfileinfo, $infoline); | ||||
1415 | ${$filecontent}[$i] = "$1\t$2\t$3\t$4\t$mergemodulehash->{'componentcondition'}\t$6\n"; | ||||
1416 | } | ||||
1417 | } | ||||
1418 | } | ||||
1419 | } | ||||
1420 | } | ||||
1421 | |||||
1422 | # saving file | ||||
1423 | 5 | 28.7ms | installer::files::save_file($idtfilename, $filecontent); # spent 28.7ms making 5 calls to installer::files::save_file, avg 5.73ms/call | ||
1424 | } | ||||
1425 | |||||
1426 | ######################################################################### | ||||
1427 | # In the directory table, the directory parent has to be changed, | ||||
1428 | # if it is not TARGETDIR. | ||||
1429 | ######################################################################### | ||||
1430 | |||||
1431 | sub change_directory_table | ||||
1432 | # spent 54µs within installer::windows::mergemodule::change_directory_table which was called 5 times, avg 11µs/call:
# 5 times (54µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 467, avg 11µs/call | ||||
1433 | 15 | 60µs | my ($mergemodulehash, $workdir) = @_; | ||
1434 | |||||
1435 | # directory for MergeModule has to be defined in scp project | ||||
1436 | my $scpdirectory = $mergemodulehash->{'rootdir'}; | ||||
1437 | |||||
1438 | if ( $scpdirectory ne "TARGETDIR" ) # TARGETDIR works fine, when using msidb.exe | ||||
1439 | { | ||||
1440 | my $infoline = "Changing content of table \"Directory\"\n"; | ||||
1441 | push( @installer::globals::logfileinfo, $infoline); | ||||
1442 | |||||
1443 | my $idtfilename = "Director.idt"; | ||||
1444 | if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: Could not find file \"$idtfilename\" in \"$workdir\" !", "change_directory_table"); } | ||||
1445 | |||||
1446 | my $filecontent = installer::files::read_file($idtfilename); | ||||
1447 | |||||
1448 | if ( ! $installer::globals::mergedirectoriescollected ) | ||||
1449 | { | ||||
1450 | collect_directories(); # putting content into %installer::globals::merge_alldirectory_hash, only first column! | ||||
1451 | $installer::globals::mergedirectoriescollected = 1; | ||||
1452 | } | ||||
1453 | |||||
1454 | if ( ! exists($installer::globals::merge_alldirectory_hash{$scpdirectory}) ) | ||||
1455 | { | ||||
1456 | installer::exiter::exit_program("ERROR: Unknown directory defined in scp: \"$scpdirectory\" . Not defined in table \"Directory\" !", "change_directory_table"); | ||||
1457 | } | ||||
1458 | |||||
1459 | # If the definition in scp is okay, now the complete content of "Director.idt" can be analyzed | ||||
1460 | my $merge_directorytablehashref = analyze_directorytable_file($filecontent, $idtfilename); | ||||
1461 | |||||
1462 | my $directory; | ||||
1463 | foreach $directory (keys %{$mergemodulehash->{'mergedirectories'}} ) | ||||
1464 | { | ||||
1465 | if ( ! exists($merge_directorytablehashref->{$directory}) ) { installer::exiter::exit_program("ERROR: Could not find directory \"$directory\" in \"$idtfilename\" !", "change_directory_table"); } | ||||
1466 | my $dirhash = $merge_directorytablehashref->{$directory}; | ||||
1467 | my $linenumber = $dirhash->{'linenumber'}; | ||||
1468 | |||||
1469 | # <- this line has to be changed concerning "Directory_Parent", | ||||
1470 | # if the current value is "TARGETDIR", which is the default value from msidb.exe | ||||
1471 | |||||
1472 | if ( $dirhash->{'Directory_Parent'} eq "TARGETDIR" ) | ||||
1473 | { | ||||
1474 | $dirhash->{'Directory_Parent'} = $scpdirectory; | ||||
1475 | |||||
1476 | my $oldline = ${$filecontent}[$linenumber]; | ||||
1477 | my $newline = get_new_line_for_directory_table($dirhash); | ||||
1478 | ${$filecontent}[$linenumber] = $newline; | ||||
1479 | |||||
1480 | $infoline = "Merge, replacing line:\n"; | ||||
1481 | push( @installer::globals::logfileinfo, $infoline); | ||||
1482 | $infoline = "Old: $oldline\n"; | ||||
1483 | push( @installer::globals::logfileinfo, $infoline); | ||||
1484 | $infoline = "New: $newline\n"; | ||||
1485 | push( @installer::globals::logfileinfo, $infoline); | ||||
1486 | } | ||||
1487 | } | ||||
1488 | |||||
1489 | # saving file | ||||
1490 | installer::files::save_file($idtfilename, $filecontent); | ||||
1491 | } | ||||
1492 | } | ||||
1493 | |||||
1494 | ######################################################################### | ||||
1495 | # In the msiassembly table, the feature has to be changed. | ||||
1496 | ######################################################################### | ||||
1497 | |||||
1498 | sub change_msiassembly_table | ||||
1499 | # spent 5.80ms (449µs+5.35) within installer::windows::mergemodule::change_msiassembly_table which was called 4 times, avg 1.45ms/call:
# 4 times (449µs+5.35ms) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 471, avg 1.45ms/call | ||||
1500 | 52 | 1.27ms | my ($mergemodulehash, $workdir) = @_; | ||
1501 | |||||
1502 | my $infoline = "Changing content of table \"MsiAssembly\"\n"; | ||||
1503 | push( @installer::globals::logfileinfo, $infoline); | ||||
1504 | |||||
1505 | my $idtfilename = "MsiAssem.idt"; | ||||
1506 | 4 | 921µs | if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: Could not find file \"$idtfilename\" in \"$workdir\" !", "change_msiassembly_table"); } # spent 921µs making 4 calls to installer::windows::mergemodule::CORE:ftfile, avg 230µs/call | ||
1507 | |||||
1508 | 4 | 1.45ms | my $filecontent = installer::files::read_file($idtfilename); # spent 1.45ms making 4 calls to installer::files::read_file, avg 361µs/call | ||
1509 | |||||
1510 | # feature has to be defined in scp project | ||||
1511 | my $feature = $mergemodulehash->{'feature'}; | ||||
1512 | |||||
1513 | if ( ! $installer::globals::mergefeaturecollected ) | ||||
1514 | { | ||||
1515 | collect_feature(); # putting content into hash %installer::globals::merge_allfeature_hash | ||||
1516 | $installer::globals::mergefeaturecollected = 1; | ||||
1517 | } | ||||
1518 | |||||
1519 | if ( ! exists($installer::globals::merge_allfeature_hash{$feature}) ) | ||||
1520 | { | ||||
1521 | installer::exiter::exit_program("ERROR: Unknown feature defined in scp: \"$feature\" . Not defined in table \"Feature\" !", "change_msiassembly_table"); | ||||
1522 | } | ||||
1523 | |||||
1524 | 4 | 1.46ms | my $merge_msiassemblytablehashref = analyze_msiassemblytable_file($filecontent, $idtfilename); # spent 1.46ms making 4 calls to installer::windows::mergemodule::analyze_msiassemblytable_file, avg 365µs/call | ||
1525 | |||||
1526 | my $component; | ||||
1527 | foreach $component (keys %{$mergemodulehash->{'mergeassemblies'}} ) | ||||
1528 | { | ||||
1529 | 52 | 79µs | if ( ! exists($merge_msiassemblytablehashref->{$component}) ) { installer::exiter::exit_program("ERROR: Could not find component \"$component\" in \"$idtfilename\" !", "change_msiassembly_table"); } | ||
1530 | my $assemblyhash = $merge_msiassemblytablehashref->{$component}; | ||||
1531 | my $linenumber = $assemblyhash->{'linenumber'}; | ||||
1532 | |||||
1533 | # <- this line has to be changed concerning "Feature" | ||||
1534 | $assemblyhash->{'Feature'} = $feature; | ||||
1535 | |||||
1536 | my $oldline = ${$filecontent}[$linenumber]; | ||||
1537 | 4 | 44µs | my $newline = get_new_line_for_msiassembly_table($assemblyhash); # spent 44µs making 4 calls to installer::windows::mergemodule::get_new_line_for_msiassembly_table, avg 11µs/call | ||
1538 | ${$filecontent}[$linenumber] = $newline; | ||||
1539 | |||||
1540 | $infoline = "Merge, replacing line:\n"; | ||||
1541 | push( @installer::globals::logfileinfo, $infoline); | ||||
1542 | $infoline = "Old: $oldline\n"; | ||||
1543 | push( @installer::globals::logfileinfo, $infoline); | ||||
1544 | $infoline = "New: $newline\n"; | ||||
1545 | push( @installer::globals::logfileinfo, $infoline); | ||||
1546 | } | ||||
1547 | |||||
1548 | # saving file | ||||
1549 | 4 | 1.48ms | installer::files::save_file($idtfilename, $filecontent); # spent 1.48ms making 4 calls to installer::files::save_file, avg 370µs/call | ||
1550 | } | ||||
1551 | |||||
1552 | ######################################################################### | ||||
1553 | # Creating file content hash | ||||
1554 | ######################################################################### | ||||
1555 | |||||
1556 | sub make_executeidtcontent_hash | ||||
1557 | # spent 18.2ms (14.6+3.65) within installer::windows::mergemodule::make_executeidtcontent_hash which was called 20 times, avg 912µs/call:
# 20 times (14.6ms+3.65ms) by installer::windows::mergemodule::change_executesequence_table at line 1640, avg 912µs/call | ||||
1558 | 80 | 1.41ms | my ($filecontent, $idtfilename) = @_; | ||
1559 | |||||
1560 | my %newhash = (); | ||||
1561 | |||||
1562 | 2529 | 10.5ms | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||
1563 | { | ||||
1564 | 60 | 43µs | if ( $i <= 2 ) { next; } # ignoring first three lines | ||
1565 | 823 | 1.06ms | if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines # spent 1.06ms making 823 calls to installer::windows::mergemodule::CORE:match, avg 1µs/call | ||
1566 | # Format for all sequence tables: Action Condition Sequence | ||||
1567 | 4115 | 6.32ms | 823 | 2.59ms | if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.*?)\t(.*?)\s*$/ ) # spent 2.59ms making 823 calls to installer::windows::mergemodule::CORE:match, avg 3µs/call |
1568 | { | ||||
1569 | my %onehash = (); | ||||
1570 | $onehash{'Action'} = $1; | ||||
1571 | $onehash{'Condition'} = $2; | ||||
1572 | $onehash{'Sequence'} = $3; | ||||
1573 | $newhash{$onehash{'Action'}} = \%onehash; | ||||
1574 | } | ||||
1575 | else | ||||
1576 | { | ||||
1577 | my $linecount = $i + 1; | ||||
1578 | installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "make_executeidtcontent_hash"); | ||||
1579 | } | ||||
1580 | } | ||||
1581 | |||||
1582 | return \%newhash; | ||||
1583 | } | ||||
1584 | |||||
1585 | ######################################################################### | ||||
1586 | # Creating file content hash | ||||
1587 | ######################################################################### | ||||
1588 | |||||
1589 | sub make_moduleexecuteidtcontent_hash | ||||
1590 | # spent 4.52ms (3.60+919µs) within installer::windows::mergemodule::make_moduleexecuteidtcontent_hash which was called 20 times, avg 226µs/call:
# 20 times (3.60ms+919µs) by installer::windows::mergemodule::change_executesequence_table at line 1641, avg 226µs/call | ||||
1591 | 80 | 458µs | my ($filecontent, $idtfilename) = @_; | ||
1592 | |||||
1593 | my %newhash = (); | ||||
1594 | |||||
1595 | 573 | 2.40ms | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||
1596 | { | ||||
1597 | 60 | 31µs | if ( $i <= 2 ) { next; } # ignoring first three lines | ||
1598 | 171 | 239µs | if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines # spent 239µs making 171 calls to installer::windows::mergemodule::CORE:match, avg 1µs/call | ||
1599 | # Format for all module sequence tables: Action Sequence BaseAction After Condition | ||||
1600 | 1197 | 1.68ms | 171 | 680µs | if ( ${$filecontent}[$i] =~ /^\s*(.+?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) # spent 680µs making 171 calls to installer::windows::mergemodule::CORE:match, avg 4µs/call |
1601 | { | ||||
1602 | my %onehash = (); | ||||
1603 | $onehash{'Action'} = $1; | ||||
1604 | $onehash{'Sequence'} = $2; | ||||
1605 | $onehash{'BaseAction'} = $3; | ||||
1606 | $onehash{'After'} = $4; | ||||
1607 | $onehash{'Condition'} = $5; | ||||
1608 | $newhash{$onehash{'Action'}} = \%onehash; | ||||
1609 | } | ||||
1610 | else | ||||
1611 | { | ||||
1612 | my $linecount = $i + 1; | ||||
1613 | installer::exiter::exit_program("ERROR: Unknown line format in table \"$idtfilename\" (line $linecount) !", "make_executeidtcontent_hash"); | ||||
1614 | } | ||||
1615 | } | ||||
1616 | |||||
1617 | return \%newhash; | ||||
1618 | } | ||||
1619 | |||||
1620 | ######################################################################### | ||||
1621 | # ExecuteSequence tables need to be merged with | ||||
1622 | # ModuleExecuteSequence tables created by msidb.exe. | ||||
1623 | ######################################################################### | ||||
1624 | |||||
1625 | sub change_executesequence_table | ||||
1626 | # spent 51.8ms (4.48+47.3) within installer::windows::mergemodule::change_executesequence_table which was called 20 times, avg 2.59ms/call:
# 5 times (2.08ms+20.8ms) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 539, avg 4.57ms/call
# 5 times (1.27ms+11.7ms) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 541, avg 2.60ms/call
# 5 times (635µs+7.56ms) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 547, avg 1.64ms/call
# 5 times (497µs+7.22ms) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 553, avg 1.54ms/call | ||||
1627 | 220 | 7.35ms | my ($mergemodulehash, $workdir, $idtfilename, $moduleidtfilename) = @_; | ||
1628 | |||||
1629 | my $infoline = "Changing content of table \"$idtfilename\"\n"; | ||||
1630 | push( @installer::globals::logfileinfo, $infoline); | ||||
1631 | |||||
1632 | 20 | 2.14ms | if ( ! -f $idtfilename ) { installer::exiter::exit_program("ERROR: Could not find file \"$idtfilename\" in \"$workdir\" !", "change_executesequence_table"); } # spent 2.14ms making 20 calls to installer::windows::mergemodule::CORE:ftfile, avg 107µs/call | ||
1633 | 20 | 1.72ms | if ( ! -f $moduleidtfilename ) { installer::exiter::exit_program("ERROR: Could not find file \"$moduleidtfilename\" in \"$workdir\" !", "change_executesequence_table"); } # spent 1.72ms making 20 calls to installer::windows::mergemodule::CORE:ftfile, avg 86µs/call | ||
1634 | |||||
1635 | # Reading file content | ||||
1636 | 20 | 8.45ms | my $idtfilecontent = installer::files::read_file($idtfilename); # spent 8.45ms making 20 calls to installer::files::read_file, avg 422µs/call | ||
1637 | 20 | 5.44ms | my $moduleidtfilecontent = installer::files::read_file($moduleidtfilename); # spent 5.44ms making 20 calls to installer::files::read_file, avg 272µs/call | ||
1638 | |||||
1639 | # Converting to hash | ||||
1640 | 20 | 18.2ms | my $idtcontenthash = make_executeidtcontent_hash($idtfilecontent, $idtfilename); # spent 18.2ms making 20 calls to installer::windows::mergemodule::make_executeidtcontent_hash, avg 912µs/call | ||
1641 | 20 | 4.52ms | my $moduleidtcontenthash = make_moduleexecuteidtcontent_hash($moduleidtfilecontent, $moduleidtfilename); # spent 4.52ms making 20 calls to installer::windows::mergemodule::make_moduleexecuteidtcontent_hash, avg 226µs/call | ||
1642 | |||||
1643 | # Merging | ||||
1644 | foreach my $action ( keys %{$moduleidtcontenthash} ) | ||||
1645 | { | ||||
1646 | 382 | 525µs | if ( exists($idtcontenthash->{$action}) ) { next; } # Action already exists, can be ignored | ||
1647 | |||||
1648 | 52 | 24µs | 56 | 45µs | if (( $idtfilename eq "InstallU.idt" ) && ( ! ( $action =~ /^\s*WindowsFolder\./ ))) { next; } # Only "WindowsFolder.*" CustomActions for UI Sequence table # spent 45µs making 56 calls to installer::windows::mergemodule::CORE:match, avg 804ns/call |
1649 | |||||
1650 | my $actionhashref = $moduleidtcontenthash->{$action}; | ||||
1651 | 240 | 306µs | if ( $actionhashref->{'Sequence'} ne "" ) | ||
1652 | { | ||||
1653 | # Format for all sequence tables: Action Condition Sequence | ||||
1654 | my $newline = $actionhashref->{'Action'} . "\t" . $actionhashref->{'Condition'} . "\t" . $actionhashref->{'Sequence'} . "\n"; | ||||
1655 | # Adding to table | ||||
1656 | push(@{$idtfilecontent}, $newline); | ||||
1657 | # Also adding to hash | ||||
1658 | my %idttablehash = (); | ||||
1659 | $idttablehash{'Action'} = $actionhashref->{'Action'}; | ||||
1660 | $idttablehash{'Condition'} = $actionhashref->{'Condition'}; | ||||
1661 | $idttablehash{'Sequence'} = $actionhashref->{'Sequence'}; | ||||
1662 | $idtcontenthash->{$action} = \%idttablehash; | ||||
1663 | |||||
1664 | } | ||||
1665 | else # no sequence defined, using syntax "BaseAction" and "After" | ||||
1666 | { | ||||
1667 | my $baseactionname = $actionhashref->{'BaseAction'}; | ||||
1668 | # If this baseactionname is not defined in execute idt file, it is not possible to merge | ||||
1669 | if ( ! exists($idtcontenthash->{$baseactionname}) ) { installer::exiter::exit_program("ERROR: Merge problem: Could not find action \"$baseactionname\" in file \"$idtfilename\" !", "change_executesequence_table"); } | ||||
1670 | |||||
1671 | my $baseaction = $idtcontenthash->{$baseactionname}; | ||||
1672 | my $sequencenumber = $baseaction->{'Sequence'}; | ||||
1673 | 19 | 19µs | if ( $actionhashref->{'After'} == 1 ) { $sequencenumber = $sequencenumber + 1; } | ||
1674 | else { $sequencenumber = $sequencenumber - 1; } | ||||
1675 | |||||
1676 | # Format for all sequence tables: Action Condition Sequence | ||||
1677 | my $newline = $actionhashref->{'Action'} . "\t" . $actionhashref->{'Condition'} . "\t" . $sequencenumber . "\n"; | ||||
1678 | # Adding to table | ||||
1679 | push(@{$idtfilecontent}, $newline); | ||||
1680 | # Also adding to hash | ||||
1681 | my %idttablehash = (); | ||||
1682 | $idttablehash{'Action'} = $actionhashref->{'Action'}; | ||||
1683 | $idttablehash{'Condition'} = $actionhashref->{'Condition'}; | ||||
1684 | $idttablehash{'Sequence'} = $sequencenumber; | ||||
1685 | $idtcontenthash->{$action} = \%idttablehash; | ||||
1686 | } | ||||
1687 | } | ||||
1688 | |||||
1689 | # saving file | ||||
1690 | 20 | 6.73ms | installer::files::save_file($idtfilename, $idtfilecontent); # spent 6.73ms making 20 calls to installer::files::save_file, avg 336µs/call | ||
1691 | } | ||||
1692 | |||||
1693 | |||||
1694 | 1 | 8µs | 1; | ||
# spent 6.20s within installer::windows::mergemodule::CORE:backtick which was called 15 times, avg 413ms/call:
# 5 times (2.10s+0s) by installer::windows::mergemodule::change_file_table at line 1150, avg 420ms/call
# 5 times (2.05s+0s) by installer::windows::mergemodule::change_file_table at line 1126, avg 411ms/call
# 5 times (2.05s+0s) by installer::windows::mergemodule::change_file_table at line 1142, avg 410ms/call | |||||
# spent 5.48ms within installer::windows::mergemodule::CORE:chdir which was called 30 times, avg 183µs/call:
# 5 times (1.44ms+0s) by installer::windows::mergemodule::change_file_table at line 1176, avg 289µs/call
# 5 times (1.09ms+0s) by installer::windows::mergemodule::change_file_table at line 1130, avg 219µs/call
# 5 times (1.09ms+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 599, avg 217µs/call
# 5 times (637µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 359, avg 127µs/call
# 5 times (626µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 107, avg 125µs/call
# 5 times (596µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 322, avg 119µs/call | |||||
# spent 1.96ms within installer::windows::mergemodule::CORE:ftdir which was called 10 times, avg 196µs/call:
# 5 times (1.00ms+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 94, avg 200µs/call
# 5 times (961µs+0s) by installer::windows::mergemodule::change_file_table at line 1120, avg 192µs/call | |||||
# spent 35.0ms within installer::windows::mergemodule::CORE:ftfile which was called 268 times, avg 131µs/call:
# 33 times (2.88ms+0s) by installer::windows::mergemodule::change_file_table at line 1255, avg 87µs/call
# 20 times (2.14ms+0s) by installer::windows::mergemodule::change_executesequence_table at line 1632, avg 107µs/call
# 20 times (1.72ms+0s) by installer::windows::mergemodule::change_executesequence_table at line 1633, avg 86µs/call
# 5 times (1.37ms+0s) by installer::windows::mergemodule::change_featurecomponent_table at line 1347, avg 274µs/call
# 5 times (1.22ms+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 400, avg 244µs/call
# 5 times (1.18ms+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 485, avg 236µs/call
# 5 times (1.16ms+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 168, avg 232µs/call
# 5 times (1.13ms+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 89, avg 225µs/call
# 5 times (1.09ms+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 454, avg 219µs/call
# 5 times (1.09ms+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 529, avg 219µs/call
# 5 times (953µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 110, avg 191µs/call
# 5 times (942µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 402, avg 188µs/call
# 5 times (923µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 404, avg 185µs/call
# 5 times (914µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 102, avg 183µs/call
# 5 times (882µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 406, avg 176µs/call
# 5 times (753µs+0s) by installer::windows::mergemodule::change_component_table at line 1390, avg 151µs/call
# 5 times (696µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 194, avg 139µs/call
# 5 times (692µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 401, avg 138µs/call
# 5 times (657µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 455, avg 131µs/call
# 5 times (625µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 530, avg 125µs/call
# 5 times (624µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 486, avg 125µs/call
# 5 times (591µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 220, avg 118µs/call
# 5 times (556µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 456, avg 111µs/call
# 5 times (554µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 489, avg 111µs/call
# 5 times (549µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 490, avg 110µs/call
# 5 times (547µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 491, avg 109µs/call
# 5 times (545µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 487, avg 109µs/call
# 5 times (541µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 488, avg 108µs/call
# 5 times (535µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 531, avg 107µs/call
# 5 times (531µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 408, avg 106µs/call
# 5 times (519µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 403, avg 104µs/call
# 5 times (516µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 407, avg 103µs/call
# 5 times (516µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 405, avg 103µs/call
# 5 times (493µs+0s) by installer::windows::mergemodule::change_media_table at line 856, avg 99µs/call
# 5 times (492µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 206, avg 98µs/call
# 5 times (485µs+0s) by installer::windows::mergemodule::change_file_table at line 1096, avg 97µs/call
# 5 times (475µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 544, avg 95µs/call
# 5 times (470µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 457, avg 94µs/call
# 5 times (469µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 550, avg 94µs/call
# 5 times (468µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 536, avg 94µs/call
# 5 times (462µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 532, avg 92µs/call
# 4 times (921µs+0s) by installer::windows::mergemodule::change_msiassembly_table at line 1506, avg 230µs/call
# once (170µs+0s) by installer::windows::mergemodule::collect_feature at line 1315 | |||||
# spent 542ms within installer::windows::mergemodule::CORE:match which was called 282524 times, avg 2µs/call:
# 117922 times (101ms+0s) by installer::windows::mergemodule::change_component_table at line 1399, avg 860ns/call
# 79534 times (315ms+0s) by installer::windows::mergemodule::analyze_filetable_file at line 993, avg 4µs/call
# 79534 times (111ms+0s) by installer::windows::mergemodule::analyze_filetable_file at line 992, avg 1µs/call
# 1553 times (5.63ms+0s) by installer::windows::mergemodule::collect_feature at line 1323, avg 4µs/call
# 1553 times (1.77ms+0s) by installer::windows::mergemodule::collect_feature at line 1321, avg 1µs/call
# 823 times (2.59ms+0s) by installer::windows::mergemodule::make_executeidtcontent_hash at line 1567, avg 3µs/call
# 823 times (1.06ms+0s) by installer::windows::mergemodule::make_executeidtcontent_hash at line 1565, avg 1µs/call
# 171 times (680µs+0s) by installer::windows::mergemodule::make_moduleexecuteidtcontent_hash at line 1600, avg 4µs/call
# 171 times (239µs+0s) by installer::windows::mergemodule::make_moduleexecuteidtcontent_hash at line 1598, avg 1µs/call
# 56 times (45µs+0s) by installer::windows::mergemodule::change_executesequence_table at line 1648, avg 804ns/call
# 50 times (182µs+0s) by installer::windows::mergemodule::analyze_msiassemblytable_file at line 955, avg 4µs/call
# 50 times (88µs+0s) by installer::windows::mergemodule::analyze_msiassemblytable_file at line 954, avg 2µs/call
# 34 times (73µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 213, avg 2µs/call
# 34 times (55µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 212, avg 2µs/call
# 33 times (303µs+0s) by installer::windows::mergemodule::change_file_table at line 1240, avg 9µs/call
# 33 times (174µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 179, avg 5µs/call
# 33 times (121µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 176, avg 4µs/call
# 13 times (214µs+0s) by installer::windows::mergemodule::change_component_table at line 1401, avg 16µs/call
# 13 times (38µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 201, avg 3µs/call
# 13 times (31µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 200, avg 2µs/call
# 5 times (586µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 512, avg 117µs/call
# 5 times (88µs+0s) by installer::windows::mergemodule::change_file_table at line 1149, avg 18µs/call
# 5 times (85µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 138, avg 17µs/call
# 5 times (80µs+0s) by installer::windows::mergemodule::change_file_table at line 1141, avg 16µs/call
# 5 times (60µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 498, avg 12µs/call
# 5 times (39µs+0s) by installer::windows::mergemodule::change_file_table at line 1125, avg 8µs/call
# 5 times (30µs+0s) by installer::windows::mergemodule::analyze_media_file at line 627, avg 6µs/call
# 5 times (29µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 368, avg 6µs/call
# 5 times (27µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 420, avg 5µs/call
# 5 times (27µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 562, avg 5µs/call
# 5 times (24µs+0s) by installer::windows::mergemodule::analyze_media_file at line 626, avg 5µs/call
# 5 times (22µs+0s) by installer::windows::mergemodule::change_media_table at line 873, avg 4µs/call
# 5 times (11µs+0s) by installer::windows::mergemodule::change_media_table at line 872, avg 2µs/call
# 5 times (4µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 247, avg 760ns/call
# 4 times (12µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 228, avg 3µs/call
# 4 times (11µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 227, avg 3µs/call | |||||
# spent 2.40s within installer::windows::mergemodule::CORE:regcomp which was called 117927 times, avg 20µs/call:
# 117922 times (2.40s+0s) by installer::windows::mergemodule::change_component_table at line 1399, avg 20µs/call
# 5 times (244µs+0s) by installer::windows::mergemodule::change_media_table at line 873, avg 49µs/call | |||||
# spent 107µs within installer::windows::mergemodule::CORE:sort which was called 5 times, avg 21µs/call:
# 5 times (107µs+0s) by installer::windows::mergemodule::change_file_table at line 1269, avg 21µs/call | |||||
# spent 1.26ms within installer::windows::mergemodule::CORE:subst which was called 88 times, avg 14µs/call:
# 33 times (110µs+0s) by installer::windows::mergemodule::change_file_table at line 1240, avg 3µs/call
# 5 times (166µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 516, avg 33µs/call
# 5 times (135µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 141, avg 27µs/call
# 5 times (127µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 502, avg 25µs/call
# 5 times (119µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 372, avg 24µs/call
# 5 times (111µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 424, avg 22µs/call
# 5 times (101µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 566, avg 20µs/call
# 5 times (82µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 373, avg 16µs/call
# 5 times (79µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 425, avg 16µs/call
# 5 times (79µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 517, avg 16µs/call
# 5 times (76µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 503, avg 15µs/call
# 5 times (76µs+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 567, avg 15µs/call | |||||
# spent 86.7s within installer::windows::mergemodule::CORE:system which was called 84 times, avg 1.03s/call:
# 49 times (34.9s+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 570, avg 712ms/call
# 5 times (34.0s+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 432, avg 6.80s/call
# 5 times (3.68s+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 380, avg 737ms/call
# 5 times (3.34s+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 524, avg 667ms/call
# 5 times (3.30s+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 510, avg 659ms/call
# 5 times (2.59s+0s) by installer::windows::mergemodule::change_file_table at line 1159, avg 519ms/call
# 5 times (2.46s+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 114, avg 493ms/call
# 5 times (2.44s+0s) by installer::windows::mergemodule::merge_mergemodules_into_msi_database at line 149, avg 489ms/call |