1+ // EnableLaaunchApplication.js <msi-file>
2+ // Performs a post-build fixup of an msi to launch a specific file when the install has completed
3+
4+
5+ // Configurable values
6+ var checkboxChecked = true ; // Is the checkbox on the finished dialog checked by default?
7+ var checkboxText = "Launch [ProductName]" ; // Text for the checkbox on the finished dialog
8+ var filename = "IPAnalyzer.exe" ; // The name of the executable to launch - change this to match the file you want to launch at the end of your setup
9+
10+
11+ // Constant values from Windows Installer
12+ var msiOpenDatabaseModeTransact = 1 ;
13+
14+ var msiViewModifyInsert = 1
15+ var msiViewModifyUpdate = 2
16+ var msiViewModifyAssign = 3
17+ var msiViewModifyReplace = 4
18+ var msiViewModifyDelete = 6
19+
20+
21+
22+ if ( WScript . Arguments . Length != 1 )
23+ {
24+ WScript . StdErr . WriteLine ( WScript . ScriptName + " file" ) ;
25+ WScript . Quit ( 1 ) ;
26+ }
27+
28+ var filespec = WScript . Arguments ( 0 ) ;
29+ var installer = WScript . CreateObject ( "WindowsInstaller.Installer" ) ;
30+ var database = installer . OpenDatabase ( filespec , msiOpenDatabaseModeTransact ) ;
31+
32+ var sql
33+ var view
34+ var record
35+
36+ try
37+ {
38+ var fileId = FindFileIdentifier ( database , filename ) ;
39+ if ( ! fileId )
40+ throw "Unable to find '" + filename + "' in File table" ;
41+
42+
43+ WScript . Echo ( "Updating the Control table..." ) ;
44+ // Modify the Control_Next of BannerBmp control to point to the new CheckBox
45+ sql = "SELECT `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_`='FinishedForm' AND `Control`='BannerBmp'" ;
46+ view = database . OpenView ( sql ) ;
47+ view . Execute ( ) ;
48+ record = view . Fetch ( ) ;
49+ record . StringData ( 11 ) = "CheckboxLaunch" ;
50+ view . Modify ( msiViewModifyReplace , record ) ;
51+ view . Close ( ) ;
52+
53+ // Resize the BodyText and BodyTextRemove controls to be reasonable
54+ sql = "SELECT `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_`='FinishedForm' AND `Control`='BodyTextRemove'" ;
55+ view = database . OpenView ( sql ) ;
56+ view . Execute ( ) ;
57+ record = view . Fetch ( ) ;
58+ record . IntegerData ( 7 ) = 33 ;
59+ view . Modify ( msiViewModifyReplace , record ) ;
60+ view . Close ( ) ;
61+
62+ sql = "SELECT `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_`='FinishedForm' AND `Control`='BodyText'" ;
63+ view = database . OpenView ( sql ) ;
64+ view . Execute ( ) ;
65+ record = view . Fetch ( ) ;
66+ record . IntegerData ( 7 ) = 33 ;
67+ view . Modify ( msiViewModifyReplace , record ) ;
68+ view . Close ( ) ;
69+
70+ // Insert the new CheckBox control
71+ sql = "INSERT INTO `Control` (`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help`) VALUES ('FinishedForm', 'CheckboxLaunch', 'CheckBox', '18', '117', '343', '12', '3', 'LAUNCHAPP', '{\\VSI_MS_Sans_Serif13.0_0_0}" + checkboxText + "', 'Line1', '|')" ;
72+ view = database . OpenView ( sql ) ;
73+ view . Execute ( ) ;
74+ view . Close ( ) ;
75+
76+
77+
78+ WScript . Echo ( "Updating the ControlEvent table..." ) ;
79+ // Modify the Order of the EndDialog event of the FinishedForm to 1
80+ sql = "SELECT `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering` FROM `ControlEvent` WHERE `Dialog_`='FinishedForm' AND `Event`='EndDialog'" ;
81+ view = database . OpenView ( sql ) ;
82+ view . Execute ( ) ;
83+ record = view . Fetch ( ) ;
84+ record . IntegerData ( 6 ) = 1 ;
85+ view . Modify ( msiViewModifyReplace , record ) ;
86+ view . Close ( ) ;
87+
88+ // Insert the Event to launch the application
89+ sql = "INSERT INTO `ControlEvent` (`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES ('FinishedForm', 'CloseButton', 'DoAction', 'VSDCA_Launch', 'LAUNCHAPP=1', '0')" ;
90+ view = database . OpenView ( sql ) ;
91+ view . Execute ( ) ;
92+ view . Close ( ) ;
93+
94+
95+
96+ WScript . Echo ( "Updating the CustomAction table..." ) ;
97+ // Insert the custom action to launch the application when finished
98+ sql = "INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) VALUES ('VSDCA_Launch', '210', '" + fileId + "', '')" ;
99+ view = database . OpenView ( sql ) ;
100+ view . Execute ( ) ;
101+ view . Close ( ) ;
102+
103+
104+
105+ if ( checkboxChecked )
106+ {
107+ WScript . Echo ( "Updating the Property table..." ) ;
108+ // Set the default value of the CheckBox
109+ sql = "INSERT INTO `Property` (`Property`, `Value`) VALUES ('LAUNCHAPP', '1')" ;
110+ view = database . OpenView ( sql ) ;
111+ view . Execute ( ) ;
112+ view . Close ( ) ;
113+ }
114+
115+
116+
117+ database . Commit ( ) ;
118+ }
119+ catch ( e )
120+ {
121+ WScript . StdErr . WriteLine ( e ) ;
122+ WScript . Quit ( 1 ) ;
123+ }
124+
125+
126+
127+ function FindFileIdentifier ( database , fileName )
128+ {
129+ var sql
130+ var view
131+ var record
132+
133+ // First, try to find the exact file name
134+ sql = "SELECT `File` FROM `File` WHERE `FileName`='" + fileName + "'" ;
135+ view = database . OpenView ( sql ) ;
136+ view . Execute ( ) ;
137+ record = view . Fetch ( ) ;
138+ if ( record )
139+ {
140+ var value = record . StringData ( 1 ) ;
141+ view . Close ( ) ;
142+ return value ;
143+ }
144+ view . Close ( ) ;
145+
146+ // The file may be in SFN|LFN format. Look for a filename in this case next
147+ sql = "SELECT `File`, `FileName` FROM `File`" ;
148+ view = database . OpenView ( sql ) ;
149+ view . Execute ( ) ;
150+ record = view . Fetch ( ) ;
151+ while ( record )
152+ {
153+ if ( StringEndsWith ( record . StringData ( 2 ) , "|" + fileName ) )
154+ {
155+ var value = record . StringData ( 1 ) ;
156+ view . Close ( ) ;
157+ return value ;
158+ }
159+
160+ record = view . Fetch ( ) ;
161+ }
162+ view . Close ( ) ;
163+
164+ }
165+
166+ function StringEndsWith ( str , value )
167+ {
168+ if ( str . length < value . length )
169+ return false ;
170+
171+ return ( str . indexOf ( value , str . length - value . length ) != - 1 ) ;
172+ }
0 commit comments