| 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 | installer::windows::mergemodule::CORE:system (opcode) |
| 15 | 3 | 1 | 6.20s | 6.20s | installer::windows::mergemodule::CORE:backtick (opcode) |
| 117927 | 2 | 1 | 2.40s | 2.40s | installer::windows::mergemodule::CORE:regcomp (opcode) |
| 5 | 1 | 1 | 1.96s | 2.38s | installer::windows::mergemodule::analyze_filetable_file |
| 5 | 1 | 1 | 1.14s | 3.87s | installer::windows::mergemodule::change_component_table |
| 282524 | 36 | 1 | 542ms | 542ms | installer::windows::mergemodule::CORE:match (opcode) |
| 5 | 1 | 1 | 418ms | 12.1s | installer::windows::mergemodule::change_file_table |
| 268 | 43 | 1 | 35.0ms | 35.0ms | installer::windows::mergemodule::CORE:ftfile (opcode) |
| 5 | 1 | 1 | 19.6ms | 264ms | installer::windows::mergemodule::change_featurecomponent_table |
| 1 | 1 | 1 | 16.9ms | 31.4ms | installer::windows::mergemodule::collect_feature |
| 20 | 1 | 1 | 14.6ms | 18.2ms | installer::windows::mergemodule::make_executeidtcontent_hash |
| 1 | 1 | 1 | 13.0ms | 101s | installer::windows::mergemodule::merge_mergemodules_into_msi_database |
| 30 | 6 | 1 | 5.48ms | 5.48ms | installer::windows::mergemodule::CORE:chdir (opcode) |
| 20 | 4 | 1 | 4.48ms | 51.8ms | installer::windows::mergemodule::change_executesequence_table |
| 20 | 1 | 1 | 3.60ms | 4.52ms | installer::windows::mergemodule::make_moduleexecuteidtcontent_hash |
| 10 | 2 | 1 | 1.96ms | 1.96ms | installer::windows::mergemodule::CORE:ftdir (opcode) |
| 88 | 12 | 1 | 1.26ms | 1.26ms | installer::windows::mergemodule::CORE:subst (opcode) |
| 4 | 1 | 1 | 1.19ms | 1.46ms | installer::windows::mergemodule::analyze_msiassemblytable_file |
| 5 | 1 | 1 | 602µs | 5.22ms | installer::windows::mergemodule::change_media_table |
| 33 | 1 | 1 | 477µs | 477µs | installer::windows::mergemodule::get_new_line_for_file_table |
| 4 | 1 | 1 | 449µs | 5.80ms | installer::windows::mergemodule::change_msiassembly_table |
| 1 | 1 | 1 | 362µs | 463µs | installer::windows::mergemodule::BEGIN@30 |
| 5 | 1 | 1 | 320µs | 373µs | installer::windows::mergemodule::analyze_media_file |
| 5 | 1 | 1 | 107µs | 107µs | installer::windows::mergemodule::CORE:sort (opcode) |
| 5 | 1 | 1 | 98µs | 98µs | installer::windows::mergemodule::set_current_last_sequence |
| 5 | 1 | 1 | 63µs | 63µs | installer::windows::mergemodule::get_last_diskid |
| 5 | 1 | 1 | 54µs | 54µs | installer::windows::mergemodule::change_directory_table |
| 4 | 1 | 1 | 44µs | 44µs | installer::windows::mergemodule::get_new_line_for_msiassembly_table |
| 1 | 1 | 1 | 21µs | 24µs | installer::windows::mergemodule::BEGIN@32 |
| 1 | 1 | 1 | 20µs | 22µs | installer::windows::mergemodule::BEGIN@41 |
| 1 | 1 | 1 | 19µs | 19µs | installer::windows::mergemodule::set_last_cabfile_name |
| 1 | 1 | 1 | 18µs | 20µs | installer::windows::mergemodule::BEGIN@39 |
| 1 | 1 | 1 | 17µs | 19µs | installer::windows::mergemodule::BEGIN@40 |
| 1 | 1 | 1 | 17µs | 19µs | installer::windows::mergemodule::BEGIN@38 |
| 1 | 1 | 1 | 17µs | 18µs | installer::windows::mergemodule::BEGIN@43 |
| 1 | 1 | 1 | 16µs | 41µs | installer::windows::mergemodule::BEGIN@31 |
| 1 | 1 | 1 | 15µs | 42µs | installer::windows::mergemodule::BEGIN@36 |
| 1 | 1 | 1 | 14µs | 16µs | installer::windows::mergemodule::BEGIN@33 |
| 1 | 1 | 1 | 14µs | 16µs | installer::windows::mergemodule::BEGIN@34 |
| 1 | 1 | 1 | 14µs | 16µs | installer::windows::mergemodule::BEGIN@37 |
| 1 | 1 | 1 | 14µs | 16µs | installer::windows::mergemodule::BEGIN@35 |
| 1 | 1 | 1 | 14µs | 16µs | installer::windows::mergemodule::BEGIN@42 |
| 0 | 0 | 0 | 0s | 0s | installer::windows::mergemodule::analyze_directorytable_file |
| 0 | 0 | 0 | 0s | 0s | installer::windows::mergemodule::collect_directories |
| 0 | 0 | 0 | 0s | 0s | installer::windows::mergemodule::create_new_media_line |
| 0 | 0 | 0 | 0s | 0s | installer::windows::mergemodule::get_diskid |
| 0 | 0 | 0 | 0s | 0s | installer::windows::mergemodule::get_diskprompt |
| 0 | 0 | 0 | 0s | 0s | installer::windows::mergemodule::get_lastsequence |
| 0 | 0 | 0 | 0s | 0s | installer::windows::mergemodule::get_new_line_for_directory_table |
| 0 | 0 | 0 | 0s | 0s | installer::windows::mergemodule::get_source |
| 0 | 0 | 0 | 0s | 0s | installer::windows::mergemodule::get_volumelabel |
| 0 | 0 | 0 | 0s | 0s | installer::windows::mergemodule::sort_files_collector_for_sequence |
| 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 | 1824 | 84.2s | 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 | 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 | 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 | 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 | 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 | 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 | 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 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
| 174 | { | ||||
| 175 | 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 | 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 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
| 198 | { | ||||
| 199 | 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 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
| 210 | { | ||||
| 211 | 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 | 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 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
| 225 | { | ||||
| 226 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | $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 | 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 | 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 | 125 | 384µs | my ($filecontent, $workdir) = @_; | ||
| 617 | |||||
| 618 | my %filehash = (); | ||||
| 619 | my $linecount = 0; | ||||
| 620 | my $counter = 0; | ||||
| 621 | my $filename = "Media.idt"; | ||||
| 622 | |||||
| 623 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
| 624 | { | ||||
| 625 | 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 | 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 | 30 | 116µs | my ($mediafile) = @_; | ||
| 686 | |||||
| 687 | my $lastsequence = 0; | ||||
| 688 | my $line; | ||||
| 689 | foreach $line ( keys %{$mediafile} ) | ||||
| 690 | { | ||||
| 691 | 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 | 30 | 81µs | my ($mediafile) = @_; | ||
| 815 | |||||
| 816 | my $lastdiskid = 0; | ||||
| 817 | my $line; | ||||
| 818 | foreach $line ( keys %{$mediafile} ) | ||||
| 819 | { | ||||
| 820 | 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 | 7 | 24µs | my ($mediafile, $lastdiskid) = @_; | ||
| 833 | |||||
| 834 | my $line; | ||||
| 835 | foreach $line ( keys %{$mediafile} ) | ||||
| 836 | { | ||||
| 837 | 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 | 155 | 1.30ms | 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 | 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 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
| 870 | { | ||||
| 871 | 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 | 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 | 640 | 1.47ms | my ($filecontent, $idtfilename) = @_; | ||
| 948 | |||||
| 949 | my %assemblyhash = (); | ||||
| 950 | # Iterating over the file content | ||||
| 951 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
| 952 | { | ||||
| 953 | 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 | 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 | 1193060 | 2.38s | my ( $filecontent, $idtfilename ) = @_; | ||
| 986 | |||||
| 987 | my %filehash = (); | ||||
| 988 | # Iterating over the file content | ||||
| 989 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
| 990 | { | ||||
| 991 | 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 | 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 | 1423 | 9.22s | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | if ( ! $installer::globals::mergefiles_added_into_collector ) | ||||
| 1268 | { | ||||
| 1269 | 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 | 4669 | 24.4ms | 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 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
| 1319 | { | ||||
| 1320 | 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 | 114 | 20.9ms | 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 | 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 | 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 | 208757 | 3.64s | 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 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
| 1395 | { | ||||
| 1396 | my $component; | ||||
| 1397 | foreach $component ( keys %{$mergemodulehash->{'componentnames'}} ) | ||||
| 1398 | { | ||||
| 1399 | 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 | 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 | 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 | 104 | 1.35ms | 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 | 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 | 6784 | 18.3ms | my ($filecontent, $idtfilename) = @_; | ||
| 1559 | |||||
| 1560 | my %newhash = (); | ||||
| 1561 | |||||
| 1562 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
| 1563 | { | ||||
| 1564 | 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 | 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 | 1910 | 4.57ms | my ($filecontent, $idtfilename) = @_; | ||
| 1592 | |||||
| 1593 | my %newhash = (); | ||||
| 1594 | |||||
| 1595 | for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) | ||||
| 1596 | { | ||||
| 1597 | 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 | 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 | 913 | 8.23ms | 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 | if ( exists($idtcontenthash->{$action}) ) { next; } # Action already exists, can be ignored | ||||
| 1647 | |||||
| 1648 | 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 | 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 | 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 |