← Index
NYTProf Performance Profile   « block view • line view • sub view »
For C:/lo/libo-master/solenv/bin/make_installer.pl
  Run on Mon Sep 24 00:52:54 2012
Reported on Mon Sep 24 07:34:43 2012

Filename/cygdrive/c/lo/libo-master/instsetoo_native/util/C:/lo/libo-master/solenv/bin/modules/installer/windows/mergemodule.pm
StatementsExecuted 1420700 statements in 99.5s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
848186.7s86.7sinstaller::windows::mergemodule::::CORE:systeminstaller::windows::mergemodule::CORE:system (opcode)
15316.20s6.20sinstaller::windows::mergemodule::::CORE:backtickinstaller::windows::mergemodule::CORE:backtick (opcode)
117927212.40s2.40sinstaller::windows::mergemodule::::CORE:regcompinstaller::windows::mergemodule::CORE:regcomp (opcode)
5111.96s2.38sinstaller::windows::mergemodule::::analyze_filetable_fileinstaller::windows::mergemodule::analyze_filetable_file
5111.14s3.87sinstaller::windows::mergemodule::::change_component_tableinstaller::windows::mergemodule::change_component_table
282524361542ms542msinstaller::windows::mergemodule::::CORE:matchinstaller::windows::mergemodule::CORE:match (opcode)
511418ms12.1sinstaller::windows::mergemodule::::change_file_tableinstaller::windows::mergemodule::change_file_table
26843135.0ms35.0msinstaller::windows::mergemodule::::CORE:ftfileinstaller::windows::mergemodule::CORE:ftfile (opcode)
51119.6ms264msinstaller::windows::mergemodule::::change_featurecomponent_tableinstaller::windows::mergemodule::change_featurecomponent_table
11116.9ms31.4msinstaller::windows::mergemodule::::collect_featureinstaller::windows::mergemodule::collect_feature
201114.6ms18.2msinstaller::windows::mergemodule::::make_executeidtcontent_hashinstaller::windows::mergemodule::make_executeidtcontent_hash
11113.0ms101sinstaller::windows::mergemodule::::merge_mergemodules_into_msi_databaseinstaller::windows::mergemodule::merge_mergemodules_into_msi_database
30615.48ms5.48msinstaller::windows::mergemodule::::CORE:chdirinstaller::windows::mergemodule::CORE:chdir (opcode)
20414.48ms51.8msinstaller::windows::mergemodule::::change_executesequence_tableinstaller::windows::mergemodule::change_executesequence_table
20113.60ms4.52msinstaller::windows::mergemodule::::make_moduleexecuteidtcontent_hashinstaller::windows::mergemodule::make_moduleexecuteidtcontent_hash
10211.96ms1.96msinstaller::windows::mergemodule::::CORE:ftdirinstaller::windows::mergemodule::CORE:ftdir (opcode)
881211.26ms1.26msinstaller::windows::mergemodule::::CORE:substinstaller::windows::mergemodule::CORE:subst (opcode)
4111.19ms1.46msinstaller::windows::mergemodule::::analyze_msiassemblytable_fileinstaller::windows::mergemodule::analyze_msiassemblytable_file
511602µs5.22msinstaller::windows::mergemodule::::change_media_tableinstaller::windows::mergemodule::change_media_table
3311477µs477µsinstaller::windows::mergemodule::::get_new_line_for_file_tableinstaller::windows::mergemodule::get_new_line_for_file_table
411449µs5.80msinstaller::windows::mergemodule::::change_msiassembly_tableinstaller::windows::mergemodule::change_msiassembly_table
111362µs463µsinstaller::windows::mergemodule::::BEGIN@30installer::windows::mergemodule::BEGIN@30
511320µs373µsinstaller::windows::mergemodule::::analyze_media_fileinstaller::windows::mergemodule::analyze_media_file
511107µs107µsinstaller::windows::mergemodule::::CORE:sortinstaller::windows::mergemodule::CORE:sort (opcode)
51198µs98µsinstaller::windows::mergemodule::::set_current_last_sequenceinstaller::windows::mergemodule::set_current_last_sequence
51163µs63µsinstaller::windows::mergemodule::::get_last_diskidinstaller::windows::mergemodule::get_last_diskid
51154µs54µsinstaller::windows::mergemodule::::change_directory_tableinstaller::windows::mergemodule::change_directory_table
41144µs44µsinstaller::windows::mergemodule::::get_new_line_for_msiassembly_tableinstaller::windows::mergemodule::get_new_line_for_msiassembly_table
11121µs24µsinstaller::windows::mergemodule::::BEGIN@32installer::windows::mergemodule::BEGIN@32
11120µs22µsinstaller::windows::mergemodule::::BEGIN@41installer::windows::mergemodule::BEGIN@41
11119µs19µsinstaller::windows::mergemodule::::set_last_cabfile_nameinstaller::windows::mergemodule::set_last_cabfile_name
11118µs20µsinstaller::windows::mergemodule::::BEGIN@39installer::windows::mergemodule::BEGIN@39
11117µs19µsinstaller::windows::mergemodule::::BEGIN@40installer::windows::mergemodule::BEGIN@40
11117µs19µsinstaller::windows::mergemodule::::BEGIN@38installer::windows::mergemodule::BEGIN@38
11117µs18µsinstaller::windows::mergemodule::::BEGIN@43installer::windows::mergemodule::BEGIN@43
11116µs41µsinstaller::windows::mergemodule::::BEGIN@31installer::windows::mergemodule::BEGIN@31
11115µs42µsinstaller::windows::mergemodule::::BEGIN@36installer::windows::mergemodule::BEGIN@36
11114µs16µsinstaller::windows::mergemodule::::BEGIN@33installer::windows::mergemodule::BEGIN@33
11114µs16µsinstaller::windows::mergemodule::::BEGIN@34installer::windows::mergemodule::BEGIN@34
11114µs16µsinstaller::windows::mergemodule::::BEGIN@37installer::windows::mergemodule::BEGIN@37
11114µs16µsinstaller::windows::mergemodule::::BEGIN@35installer::windows::mergemodule::BEGIN@35
11114µs16µsinstaller::windows::mergemodule::::BEGIN@42installer::windows::mergemodule::BEGIN@42
0000s0sinstaller::windows::mergemodule::::analyze_directorytable_fileinstaller::windows::mergemodule::analyze_directorytable_file
0000s0sinstaller::windows::mergemodule::::collect_directoriesinstaller::windows::mergemodule::collect_directories
0000s0sinstaller::windows::mergemodule::::create_new_media_lineinstaller::windows::mergemodule::create_new_media_line
0000s0sinstaller::windows::mergemodule::::get_diskidinstaller::windows::mergemodule::get_diskid
0000s0sinstaller::windows::mergemodule::::get_diskpromptinstaller::windows::mergemodule::get_diskprompt
0000s0sinstaller::windows::mergemodule::::get_lastsequenceinstaller::windows::mergemodule::get_lastsequence
0000s0sinstaller::windows::mergemodule::::get_new_line_for_directory_tableinstaller::windows::mergemodule::get_new_line_for_directory_table
0000s0sinstaller::windows::mergemodule::::get_sourceinstaller::windows::mergemodule::get_source
0000s0sinstaller::windows::mergemodule::::get_volumelabelinstaller::windows::mergemodule::get_volumelabel
0000s0sinstaller::windows::mergemodule::::sort_files_collector_for_sequenceinstaller::windows::mergemodule::sort_files_collector_for_sequence
Call graph for these subroutines as a Graphviz dot language file.
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
28package installer::windows::mergemodule;
29
30265µs2564µ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
use Cwd;
# spent 463µs making 1 call to installer::windows::mergemodule::BEGIN@30 # spent 101µs making 1 call to Exporter::import
31258µs266µ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
use Digest::MD5;
# spent 41µs making 1 call to installer::windows::mergemodule::BEGIN@31 # spent 25µs making 1 call to Exporter::import
32255µs226µ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
use installer::converter;
# spent 24µs making 1 call to installer::windows::mergemodule::BEGIN@32 # spent 3µs making 1 call to UNIVERSAL::import
33253µs219µ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
use installer::exiter;
# spent 16µs making 1 call to installer::windows::mergemodule::BEGIN@33 # spent 3µs making 1 call to UNIVERSAL::import
34253µs219µ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
use installer::files;
# spent 16µs making 1 call to installer::windows::mergemodule::BEGIN@34 # spent 3µs making 1 call to UNIVERSAL::import
35251µs218µ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
use installer::globals;
# spent 16µs making 1 call to installer::windows::mergemodule::BEGIN@35 # spent 2µs making 1 call to UNIVERSAL::import
36254µs270µ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
use installer::logger;
# spent 42µs making 1 call to installer::windows::mergemodule::BEGIN@36 # spent 27µs making 1 call to Exporter::import
37260µs218µ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
use installer::pathanalyzer;
# spent 16µs making 1 call to installer::windows::mergemodule::BEGIN@37 # spent 2µs making 1 call to UNIVERSAL::import
38256µs222µ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
use installer::remover;
# spent 19µs making 1 call to installer::windows::mergemodule::BEGIN@38 # spent 2µs making 1 call to UNIVERSAL::import
39254µs223µ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
use installer::scriptitems;
# spent 20µs making 1 call to installer::windows::mergemodule::BEGIN@39 # spent 3µs making 1 call to UNIVERSAL::import
40254µs220µ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
use installer::systemactions;
# spent 19µs making 1 call to installer::windows::mergemodule::BEGIN@40 # spent 2µs making 1 call to UNIVERSAL::import
41255µs224µ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
use installer::worker;
# spent 22µs making 1 call to installer::windows::mergemodule::BEGIN@41 # spent 2µs making 1 call to UNIVERSAL::import
42252µs218µ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
use installer::windows::idtglobal;
# spent 16µs making 1 call to installer::windows::mergemodule::BEGIN@42 # spent 2µs making 1 call to UNIVERSAL::import
43217.4ms220µ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
use installer::windows::language;
# 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
49sub 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
{
51525µs my ($mergemodules, $filesref, $msifilename, $languagestringref, $allvariables, $includepatharrayref, $allupdatesequences, $allupdatelastsequences, $allupdatediskids) = @_;
52
53 my $domerge = 0;
54 if (( $#{$mergemodules} > -1 ) && ( ! $installer::globals::patch ) && ( ! $installer::globals::languagepack ) && ( ! $installer::globals::helppack )) { $domerge = 1; }
55
561440µs if ( $domerge )
57 {
581210µ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
59118µs installer::logger::print_message( "... merging msm files into msi database ... \n" );
# spent 18µs making 1 call to installer::logger::print_message
601124µ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
731333µs if ( ! $installer::globals::mergemodules_analyzed )
74 {
751114µ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
811466ms 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 {
863704.92s my $filename = $mergemodule->{'Name'};
875213µ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
8951.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;
94106.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;
101571.2ms installer::systemactions::copy_one_file($completesource, $completedest);
# spent 71.2ms making 5 calls to installer::systemactions::copy_one_file, avg 14.2ms/call
1025914µ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
105592µs my $from = cwd();
# spent 92µs making 5 calls to Cwd::__ANON__[Cwd.pm:406], avg 18µs/call
106 my $to = $workdir;
1075626µ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
1105953µ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;
11452.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
1191025µs if ($returnvalue)
120 {
121 $infoline = "ERROR: Could not execute $systemcall !\n";
122 push( @installer::globals::logfileinfo, $infoline);
123 installer::exiter::exit_program("ERROR: Could not extract cabinet file from merge file: $completedest !", "merge_mergemodules_into_msi_database");
124 }
125 else
126 {
127 $infoline = "Success: Executed $systemcall successfully!\n";
128 push( @installer::globals::logfileinfo, $infoline);
129 }
130
131 # exclude tables from mergefile
132 # Attention: All listed tables have to exist in the database. If they not exist, an error window pops up
133 # and the return value of msidb.exe is not zero. The error window makes it impossible to check the existence
134 # of a table with the help of the return value.
135 # Solution: Export of all tables by using "*" . Some tables must exist (File Component Directory), other
136 # tables do not need to exist (MsiAssembly).
137
13815222µs585µ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;
1415135µ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
14952.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
1541033µs if ($returnvalue)
155 {
156 $infoline = "ERROR: Could not execute $systemcall !\n";
157 push( @installer::globals::logfileinfo, $infoline);
158 installer::exiter::exit_program("ERROR: Could not exclude tables from merge file: $completedest !", "merge_mergemodules_into_msi_database");
159 }
160 else
161 {
162 $infoline = "Success: Executed $systemcall successfully!\n";
163 push( @installer::globals::logfileinfo, $infoline);
164 }
165
166 # Determining files
167 my $idtfilename = "File.idt"; # must exist
16851.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
16951.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 = ();
173180686µs for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
174 {
1751514µs if ( $i <= 2 ) { next; } # ignoring first three lines
17633121µ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]);
17999218µs33174µ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
1945696µ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
19551.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 = ();
19754249µs for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
198 {
199159µs if ( $i <= 2 ) { next; } # ignoring first three lines
2001331µ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
2011338µ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
2065492µ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
20751.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 = ();
209117501µs for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
210 {
211158µs if ( $i <= 2 ) { next; } # ignoring first three lines
2123455µ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
2133473µ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 = ();
2201261µs5591µs if ( -f $idtfilename )
# spent 591µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 118µs/call
221 {
2224985µ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;
2242493µs for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
225 {
226128µs if ( $i <= 2 ) { next; } # ignoring first three lines
227411µ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
228412µ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'}; }
24754µ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
3225596µ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;
3291214µ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 {
34638544.3s my $mergemodulehash = $installer::globals::mergemodules{$mergemodulegid};
347 $counter++;
348
3495684µ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
3505104µ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
3525144µ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;
3545234µ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
357578µs my $from = cwd();
# spent 78µs making 5 calls to Cwd::__ANON__[Cwd.pm:406], avg 16µs/call
358 my $to = $workdir;
3595637µ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
3625112ms 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
36651.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
36825316µs529µ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;
3725119µs $localmergemodulepath =~ s/\//\\\\/g;
# spent 119µs making 5 calls to installer::windows::mergemodule::CORE:subst, avg 24µs/call
373582µ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 }
38053.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
3851031µs if ($returnvalue)
386 {
387 $infoline = "ERROR: Could not execute $systemcall . Returnvalue: $returnvalue!\n";
388 push( @installer::globals::logfileinfo, $infoline);
389 installer::exiter::exit_program("ERROR: Could not merge msm file into database: $mergemodulehash->{'mergefilepath'} !", "merge_mergemodules_into_msi_database");
390 }
391 else
392 {
393 $infoline = "Success: Executed $systemcall successfully!\n";
394 push( @installer::globals::logfileinfo, $infoline);
395 }
396
39751.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
400915.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
40193.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
4025942µ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
40393.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
4045923µ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
405910.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
4065882µ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
40793.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
408917.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
4125940µ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.
42025289µs527µ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;
4245111µs $localmsifilename =~ s/\//\\\\/g;
# spent 111µs making 5 calls to installer::windows::mergemodule::CORE:subst, avg 22µs/call
425579µ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 }
432534.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
4371032µs if ($returnvalue)
438 {
439 $infoline = "ERROR: Could not execute $systemcall !\n";
440 push( @installer::globals::logfileinfo, $infoline);
441 installer::exiter::exit_program("ERROR: Could not exclude tables from msi database: $msifilename !", "merge_mergemodules_into_msi_database");
442 }
443 else
444 {
445 $infoline = "Success: Executed $systemcall successfully!\n";
446 push( @installer::globals::logfileinfo, $infoline);
447 }
448
44951.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
4541010.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
4551021.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
45693.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
4571032.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
4605893µ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
46155.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
4625590µ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
463512.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
46451.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
4655264ms change_featurecomponent_table($mergemodulehash, $workdir);
# spent 264ms making 5 calls to installer::windows::mergemodule::change_featurecomponent_table, avg 52.7ms/call
46651.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
467554µs change_directory_table($mergemodulehash, $workdir);
# spent 54µs making 5 calls to installer::windows::mergemodule::change_directory_table, avg 11µs/call
468830µs if ( $mergemodulehash->{'hasmsiassemblies'} )
469 {
4704450µ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
47145.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
4741040µs if ( $mergemodulehash->{'componentcondition'} )
475 {
4765607µ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
47753.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
48595.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
48693.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
48793.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
48893.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
48993.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
49093.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
49193.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
49825301µs560µ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;
5025127µs $localmsifilename =~ s/\//\\\\/g;
# spent 127µs making 5 calls to installer::windows::mergemodule::CORE:subst, avg 25µs/call
503576µ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 }
51053.30s $returnvalue = system($systemcall);
# spent 3.30s making 5 calls to installer::windows::mergemodule::CORE:system, avg 659ms/call
511
51225376µs5586µ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;
5165166µs $localmsifilename =~ s/\//\\\\/g;
# spent 166µs making 5 calls to installer::windows::mergemodule::CORE:subst, avg 33µs/call
517579µ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 }
52453.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
529107.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
530105.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
531104.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
532103.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
53620101µs5468µs if ( -f "ModuleInstallExecuteSequence.idt" )
# spent 468µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 94µs/call
537 {
5385996µ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
539522.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
5405641µ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
541513.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
5441037µs5475µs if ( -f "ModuleAdminExecuteSequence.idt" )
# spent 475µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 95µs/call
545 {
5465603µ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
54758.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
5501033µs5469µs if ( -f "ModuleAdvtExecuteSequence.idt" )
# spent 469µs making 5 calls to installer::windows::mergemodule::CORE:ftfile, avg 94µs/call
551 {
5525588µ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
55357.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
5565583µ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
5605532µ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
56225305µs527µ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;
5665101µs $localmsifilename =~ s/\//\\\\/g;
# spent 101µs making 5 calls to installer::windows::mergemodule::CORE:subst, avg 20µs/call
567576µ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) {
56924534.9s $systemcall = $msidb . " -d " . $localmsifilename . " -f " . $localworkdir . " -i " . $table;
5704934.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
5851022µs if ($returnvalue)
586 {
587 $infoline = "ERROR: Could not execute $systemcall !\n";
588 push( @installer::globals::logfileinfo, $infoline);
589 installer::exiter::exit_program("ERROR: Could not include tables into msi database: $msifilename !", "merge_mergemodules_into_msi_database");
590 }
591 else
592 {
593 $infoline = "Success: Executed $systemcall successfully!\n";
594 push( @installer::globals::logfileinfo, $infoline);
595 }
596
59751.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
59951.09ms chdir($from);
# spent 1.09ms making 5 calls to installer::windows::mergemodule::CORE:chdir, avg 217µs/call
600 }
601
60211µs if ( ! $installer::globals::mergefiles_added_into_collector ) { $installer::globals::mergefiles_added_into_collector = 1; } # Now all mergemodules are merged for one language.
603
6041112µ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
614sub 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
{
61635112µs my ($filecontent, $workdir) = @_;
617
618 my %filehash = ();
619 my $linecount = 0;
620 my $counter = 0;
621 my $filename = "Media.idt";
622
62330136µs for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
624 {
6251513µs if ( $i <= 2 ) { next; } # ignoring first three lines
626524µ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
62745123µs530µ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
655sub 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
683sub 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
{
6852589µs my ($mediafile) = @_;
686
687 my $lastsequence = 0;
688 my $line;
689 foreach $line ( keys %{$mediafile} )
690 {
691528µs if ( $mediafile->{$line}->{'LastSequence'} > $lastsequence ) { $lastsequence = $mediafile->{$line}->{'LastSequence'}; }
692 }
693
694 $installer::globals::lastsequence_before_merge = $lastsequence;
695}
696
697#########################################################################
698# Setting the LastSequence for the new cabinet file
699#########################################################################
700
701sub 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
723sub 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
745sub 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
767sub 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
790sub 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
812sub 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
{
8142563µs my ($mediafile) = @_;
815
816 my $lastdiskid = 0;
817 my $line;
818 foreach $line ( keys %{$mediafile} )
819 {
820518µs if ( $mediafile->{$line}->{'DiskId'} > $lastdiskid ) { $lastdiskid = $mediafile->{$line}->{'DiskId'}; }
821 }
822
823 return $lastdiskid;
824}
825
826#########################################################################
827# Setting global variable for last cab file name.
828#########################################################################
829
830sub 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
{
832518µs my ($mediafile, $lastdiskid) = @_;
833
834 my $line;
835 foreach $line ( keys %{$mediafile} )
836 {
83726µs if ( $mediafile->{$line}->{'DiskId'} == $lastdiskid ) { $installer::globals::lastcabfilename = $mediafile->{$line}->{'Cabinet'}; }
838 }
839 my $infoline = "Setting last cabinet file: $installer::globals::lastcabfilename\n";
840 push( @installer::globals::logfileinfo, $infoline);
841}
842
843#########################################################################
844# In the media table the new cabinet file has to be added or the
845# number of the last cabinet file has to be increased.
846#########################################################################
847
848sub 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
{
85050751µs my ( $mergemodulehash, $workdir, $mergemodulegid, $allupdatelastsequences, $allupdatediskids ) = @_;
851
852 my $infoline = "Changing content of table \"Media\"\n";
853 push( @installer::globals::logfileinfo, $infoline);
854
855 my $filename = "Media.idt";
8565493µ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
85851.46ms my $filecontent = installer::files::read_file($filename);
# spent 1.46ms making 5 calls to installer::files::read_file, avg 292µs/call
8595373µ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
860598µ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
8622080µs if ( $installer::globals::fix_number_of_cab_files )
863 {
864 # Determining the line with the highest sequencenumber. That file needs to be updated.
865563µs my $lastdiskid = get_last_diskid($mediafile);
# spent 63µs making 5 calls to installer::windows::mergemodule::get_last_diskid, avg 13µs/call
866119µs if ( $installer::globals::lastcabfilename eq "" ) { set_last_cabfile_name($mediafile, $lastdiskid); }
867 my $newmaxsequencenumber = $installer::globals::lastsequence_before_merge + $mergemodulehash->{'filenumber'};
868
86930398µs for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
870 {
871158µs if ( $i <= 2 ) { next; } # ignoring first three lines
872511µ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
8734063µs10266µ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
90251.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
909sub 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
945sub 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
{
94716133µs my ($filecontent, $idtfilename) = @_;
948
949 my %assemblyhash = ();
950 # Iterating over the file content
951162697µs for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
952 {
9531210µs if ( $i <= 2 ) { next; } # ignoring first three lines
9545088µ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
955450628µs50182µ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
983sub 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
{
98520118ms my ( $filecontent, $idtfilename ) = @_;
986
987 my %filehash = ();
988 # Iterating over the file content
9892386171.06s for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
990 {
9911522µs if ( $i <= 2 ) { next; } # ignoring first three lines
99279534111ms if ( ${$filecontent}[$i] =~ /^\s*$/ ) { next; } # ignoring empty lines
# spent 111ms making 79534 calls to installer::windows::mergemodule::CORE:match, avg 1µs/call
9939544081.20s79534315ms 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
1024sub 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
1037sub 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
{
103999538µ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
1050sub 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
{
10521254µ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
1064sub 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
1088sub 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
{
109095413ms 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";
10965485µ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
10985355ms 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
111357.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 = ();
1118852.60s if (( $installer::globals::fix_number_of_cab_files ) && ( ! $installer::globals::mergefiles_added_into_collector ))
1119 {
1120105.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
1123584µ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'};
1125102.05s539µs if ( $^O =~ /cygwin/i ) {
# spent 39µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 8µs/call
112652.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
113051.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
1141102.05s580µs if ( $^O =~ /cygwin/i ) {
# spent 80µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 16µs/call
114252.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 = "";
1149152.10s588µs if ( $^O =~ /cygwin/i ) {
# spent 88µs making 5 calls to installer::windows::mergemodule::CORE:match, avg 18µs/call
115052.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
115952.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
11641033µs if ($returnvalue)
1165 {
1166 $infoline = "ERROR: Could not execute $systemcall !\n";
1167 push( @installer::globals::logfileinfo, $infoline);
1168 installer::exiter::exit_program("ERROR: Could not extract cabinet file: $mergemodulehash->{'cabinetfile'} !", "change_file_table");
1169 }
1170 else
1171 {
1172 $infoline = "Success: Executed $systemcall successfully!\n";
1173 push( @installer::globals::logfileinfo, $infoline);
1174 }
1175
117651.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
118152.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 {
11885281.01ms my $mergefilesequence = $mergemodulehash->{'mergefilesequence'}->{$filename};
1189
1190 if ( ! exists($merge_filetablehashref->{$filename}) ) { installer::exiter::exit_program("ERROR: Could not find file \"$filename\" in \"$idtfilename\" !", "change_file_table"); }
1191 my $filehash = $merge_filetablehashref->{$filename};
1192 my $linenumber = $filehash->{'linenumber'};
1193
1194 # <- this line has to be changed concerning "Sequence" and "Attributes"
1195 $filehash->{'Attributes'} = $attributes;
1196
1197 # If this is an update process, the sequence numbers have to be reused.
119833107µs if ( $installer::globals::updatedatabase )
1199 {
1200 if ( ! exists($allupdatesequenceshashref->{$filehash->{'File'}}) ) { installer::exiter::exit_program("ERROR: Sequence not defined for file \"$filehash->{'File'}\" !", "change_file_table"); }
1201 $filehash->{'Sequence'} = $allupdatesequenceshashref->{$filehash->{'File'}};
1202 # Saving all mergemodule sequence numbers. This is important for creating ddf files
1203 $installer::globals::allmergemodulefilesequences{$filehash->{'Sequence'}} = 1;
1204 }
1205 else
1206 {
1207 # Important saved data: $installer::globals::lastsequence_before_merge.
1208 # This mechanism keeps the correct order inside the new cabinet file.
1209 $filehash->{'Sequence'} = $filehash->{'Sequence'} + $installer::globals::lastsequence_before_merge;
1210 }
1211
1212 my $oldline = ${$filecontent}[$linenumber];
121333477µ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)
12245614.63ms if (( $installer::globals::fix_number_of_cab_files ) && ( ! $installer::globals::mergefiles_added_into_collector ))
1225 {
1226 # If the number of cabinet files is kept constant,
1227 # all files from the mergemodule cabinet files will
1228 # be integrated into the last office cabinet file
1229 # (installer::globals::lastcabfilename).
1230 # Therefore the files must now be added to the filescollector,
1231 # so that they will be integrated into the ddf files.
1232
1233 # Problem with very long filenames -> copying to shorter filenames
1234 my $newfilename = "f" . $filehash->{'Sequence'};
1235 my $completesource = $unpackdir . $installer::globals::separator . $filehash->{'File'};
1236 my $completedest = $unpackdir . $installer::globals::separator . $newfilename;
12373388.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;
124033258µs66413µ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
1255332.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
126710189µs if ( ! $installer::globals::mergefiles_added_into_collector )
1268 {
12693349µs5107µ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)
1275540.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
1285sub 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
1312sub 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
{
131442.76ms my $idtfilename = "Feature.idt";
13151170µ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
131616.93ms my $filecontent = installer::files::read_file($idtfilename);
# spent 6.93ms making 1 call to installer::files::read_file
1317
1318466221.7ms for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
1319 {
132032µs if ( $i <= 2 ) { next; } # ignoring first three lines
132115531.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
132315535.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
1339sub 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
{
13416020.8ms my ($mergemodulehash, $workdir) = @_;
1342
1343 my $infoline = "Changing content of table \"FeatureComponents\"\n";
1344 push( @installer::globals::logfileinfo, $infoline);
1345
1346 my $idtfilename = "FeatureC.idt";
134751.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
13495191ms 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
135428µs if ( ! $installer::globals::mergefeaturecollected )
1355 {
1356131.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 {
13685282µs my $line = "$feature\t$component\n";
1369 push(@{$filecontent}, $line);
1370 $infoline = "Adding line: $line\n";
1371 push( @installer::globals::logfileinfo, $infoline);
1372 }
1373
1374 # saving file
1375520.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
1382sub 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
{
138440110ms 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";
13905753µ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
13925201ms my $filecontent = installer::files::read_file($idtfilename);
# spent 201ms making 5 calls to installer::files::read_file, avg 40.3ms/call
1393
139490704107ms for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
1395 {
1396 my $component;
1397 foreach $component ( keys %{$mergemodulehash->{'componentnames'}} )
1398 {
13991179353.42s2358442.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 {
140139147µs13214µ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);
140539174µs if ($5)
1406 {
1407 $infoline = "Old condition: $5\nNew condition: ($5) AND ($mergemodulehash->{'componentcondition'})\n";
1408 push( @installer::globals::logfileinfo, $infoline);
1409 ${$filecontent}[$i] = "$1\t$2\t$3\t$4\t($5) AND ($mergemodulehash->{'componentcondition'})\t$6\n";
1410 }
1411 else
1412 {
1413 $infoline = "Old condition: <none>\nNew condition: $mergemodulehash->{'componentcondition'}\n";
1414 push( @installer::globals::logfileinfo, $infoline);
1415 ${$filecontent}[$i] = "$1\t$2\t$3\t$4\t$mergemodulehash->{'componentcondition'}\t$6\n";
1416 }
1417 }
1418 }
1419 }
1420 }
1421
1422 # saving file
1423528.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
1431sub 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
{
14331560µ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
1498sub 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
{
1500521.27ms my ($mergemodulehash, $workdir) = @_;
1501
1502 my $infoline = "Changing content of table \"MsiAssembly\"\n";
1503 push( @installer::globals::logfileinfo, $infoline);
1504
1505 my $idtfilename = "MsiAssem.idt";
15064921µ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
150841.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
152441.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 {
15295279µs if ( ! exists($merge_msiassemblytablehashref->{$component}) ) { installer::exiter::exit_program("ERROR: Could not find component \"$component\" in \"$idtfilename\" !", "change_msiassembly_table"); }
1530 my $assemblyhash = $merge_msiassemblytablehashref->{$component};
1531 my $linenumber = $assemblyhash->{'linenumber'};
1532
1533 # <- this line has to be changed concerning "Feature"
1534 $assemblyhash->{'Feature'} = $feature;
1535
1536 my $oldline = ${$filecontent}[$linenumber];
1537444µ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
154941.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
1556sub 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
{
1558801.41ms my ($filecontent, $idtfilename) = @_;
1559
1560 my %newhash = ();
1561
1562252910.5ms for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
1563 {
15646043µs if ( $i <= 2 ) { next; } # ignoring first three lines
15658231.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
156741156.32ms8232.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
1589sub 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
{
159180458µs my ($filecontent, $idtfilename) = @_;
1592
1593 my %newhash = ();
1594
15955732.40ms for ( my $i = 0; $i <= $#{$filecontent}; $i++ )
1596 {
15976031µs if ( $i <= 2 ) { next; } # ignoring first three lines
1598171239µ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
160011971.68ms171680µ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
1625sub 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
{
16272207.35ms my ($mergemodulehash, $workdir, $idtfilename, $moduleidtfilename) = @_;
1628
1629 my $infoline = "Changing content of table \"$idtfilename\"\n";
1630 push( @installer::globals::logfileinfo, $infoline);
1631
1632202.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
1633201.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
1636208.45ms my $idtfilecontent = installer::files::read_file($idtfilename);
# spent 8.45ms making 20 calls to installer::files::read_file, avg 422µs/call
1637205.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
16402018.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
1641204.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 {
1646382525µs if ( exists($idtcontenthash->{$action}) ) { next; } # Action already exists, can be ignored
1647
16485224µs5645µ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};
1651240306µs if ( $actionhashref->{'Sequence'} ne "" )
1652 {
1653 # Format for all sequence tables: Action Condition Sequence
1654 my $newline = $actionhashref->{'Action'} . "\t" . $actionhashref->{'Condition'} . "\t" . $actionhashref->{'Sequence'} . "\n";
1655 # Adding to table
1656 push(@{$idtfilecontent}, $newline);
1657 # Also adding to hash
1658 my %idttablehash = ();
1659 $idttablehash{'Action'} = $actionhashref->{'Action'};
1660 $idttablehash{'Condition'} = $actionhashref->{'Condition'};
1661 $idttablehash{'Sequence'} = $actionhashref->{'Sequence'};
1662 $idtcontenthash->{$action} = \%idttablehash;
1663
1664 }
1665 else # no sequence defined, using syntax "BaseAction" and "After"
1666 {
1667 my $baseactionname = $actionhashref->{'BaseAction'};
1668 # If this baseactionname is not defined in execute idt file, it is not possible to merge
1669 if ( ! exists($idtcontenthash->{$baseactionname}) ) { installer::exiter::exit_program("ERROR: Merge problem: Could not find action \"$baseactionname\" in file \"$idtfilename\" !", "change_executesequence_table"); }
1670
1671 my $baseaction = $idtcontenthash->{$baseactionname};
1672 my $sequencenumber = $baseaction->{'Sequence'};
16731919µs if ( $actionhashref->{'After'} == 1 ) { $sequencenumber = $sequencenumber + 1; }
1674 else { $sequencenumber = $sequencenumber - 1; }
1675
1676 # Format for all sequence tables: Action Condition Sequence
1677 my $newline = $actionhashref->{'Action'} . "\t" . $actionhashref->{'Condition'} . "\t" . $sequencenumber . "\n";
1678 # Adding to table
1679 push(@{$idtfilecontent}, $newline);
1680 # Also adding to hash
1681 my %idttablehash = ();
1682 $idttablehash{'Action'} = $actionhashref->{'Action'};
1683 $idttablehash{'Condition'} = $actionhashref->{'Condition'};
1684 $idttablehash{'Sequence'} = $sequencenumber;
1685 $idtcontenthash->{$action} = \%idttablehash;
1686 }
1687 }
1688
1689 # saving file
1690206.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
169418µs1;
 
# 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
sub installer::windows::mergemodule::CORE:backtick; # opcode
# 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
sub installer::windows::mergemodule::CORE:chdir; # opcode
# 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
sub installer::windows::mergemodule::CORE:ftdir; # opcode
# 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
sub installer::windows::mergemodule::CORE:ftfile; # opcode
# 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
sub installer::windows::mergemodule::CORE:match; # opcode
# 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
sub installer::windows::mergemodule::CORE:regcomp; # opcode
# 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
sub installer::windows::mergemodule::CORE:sort; # opcode
# 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
sub installer::windows::mergemodule::CORE:subst; # opcode
# 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
sub installer::windows::mergemodule::CORE:system; # opcode