How to create MSI Custom Actions
Published: 2004 - Last update: 2004 (c) Nicolai Kjaer / Spinner Software B.V.
For more information, see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/using_custom_actions.asp.
Creating the VBScript
First, let's create a very basic script and make sure you can run it. Create the following two files:
test.cmd: @ECHO OFF @ECHO Test.cmd: @ECHO Running test.vbs CScript //nologo test.vbs @ECHO Test.vbs returned %ERRORLEVEL% PAUSE
test.vbs: WScript.Echo "This is my first vbs script" WScript.Quit 1
Doubleclick on the test.cmd script you just created. This will run your script, and if all goes ok, the output should look like this:
Test.cmd: Running test.vbs This is my first vbs script Test.vbs returned 1 Press any key to continue . . .
Make sure you can run test.cmd succesfully as described above before you continue.
Writing a registry key in Vbs
Now, let's create a script that writes something to the HKEY_LOCAL_MACHINE registry hive:
Test.vbs: ' Get the Shell object Dim oShell Set oShell = CreateObject("WScript.Shell") If Not oShell Is Nothing Then ' Write a string value to the registry oShell.RegWrite "HKLM\SOFTWARE\MyMSI\MyRegistryKey\MyString", "Enter value here", "REG_SZ" ' Free object again Set oShell = Nothing End If
If you wanted to write an integer value instead, you can replace RegWrite like this:
' Write a dword (unsigned integer) value to the registry oShell.RegWrite "HKLM\SOFTWARE\MyMSI\MyRegistryKey\MyInteger", 1, "REG_DWORD"
For more information on the RegWrite and WScript.Shell object, please see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/wsmthregwrite.asp
If you wanted to run a program, replace RegWrite with a command line this:
' Run parameters: path\filename, ShowState (1 = normal), Wait for program to finish (True/False) ' Open Notepad and wait for the user to close it oShell.Run "%WINDIR%\Notepad.exe " & WScript.ScriptFullName, 1, True
For more information on the WScript.Shell.Run method, see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/wsmthrun.asp
Including the script in the MSI
Including a script as binary
Open your MSI file with Orca, and go to the Binary table. Create a new record:
Name: TestVbs Data: drive:\path\test.vbs
The script you point to is then loaded into the record.
You need a custom action to call the script. Go to the CustomActions table and create a new record:
Action=RunTestVbs Type=6 Source=TestVbs Target=NULL (leave blank)
Type 6 specifies that it's a VbScript that can be found in the Binary table. The Source then points to the Name primary key in the Binary table.
Create a new record in the InstallExecuteSequence table:
Action=RunTestVbs Condition=NOT Installed Sequence=6500
The Sequence should be just before the InstallFinalize action (6600 if using default sequencing).
The result: during installation, the RunTestVbs custom action is called as specified by the sequencing, and if the Condition is met (not evaluated to FALSE). The RunTestVbs custom action points to a VBScript in the Binary Table, the record that matches the Name field to "TestVbs". The content of the Data field is then executed.
Tip: If you get an error, enable logging (add a /L*v "path\logfile.txt" parameter to your MSIExec statement). You can then see the precise VbScript error.
Tip: You cannot use the WScript object in scripts that are called by MSIExec. Make sure you haven't left a WScript.Quit statement in your scripts. Use the Session object to interact with the MSI Installer, for example to return error messages or update properties or the progress bar. For more information on the Session object, see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/session_object.asp.
Including the script as a CustomAction text
Another method of doing this (if it's a short script) is to include the VBScript text directly in the custom action:
Create a new script file to hold you script source:
OpenNotepad.vbs: ' Get the Shell object Dim oShell Set oShell = CreateObject("WScript.Shell") If Not oShell Is Nothing Then ' Run Notepad oShell.Run "%WINDIR%\Notepad.exe", 1, False ' Free object again Set oShell = Nothing End If
This will simply start Notepad when called (run "cscript //nologo opennotepad.vbs" to test).
Now, create a new CustomAction record:
Action=OpenNotepad Type=38 (VBScript text found in sequence table) Source=NULL (blank) Target=NULL (blank). The script actually goes here, but we'll update it in a second.
Now add it to the sequencing table ((InstallExecuteSequence):
Action=OpenNotepad Condition=NOT Installed Sequence=6501
Now you're ready to read the Opennotepad.vbs script into the CustomAction table. Copy the WiTextIn.vbs script from the ProgramFilesFolder\MSIntel.sdk\Samples\Scripts\ folder. This script will import a text file (such as a .vbs script :-) into an MSI database.
Run this command to import OpenNotepad.vbs into the MSI:
CScript WiTextIn.vbs mymsi.msi CustomAction OpenNotepad Target OpenNotepad.vbs
This will update the CustomAction record with a primary key ("Action") value of OpenNotepad in the mymsi.msi file ; the Target field is updated to contain the content of OpenNotepad.vbs. Voila, you have your script.
Test the MSI. It should now write the registry value(s) and start notepad during installation.
(c) 2004 Nicolai Kjaer, Spinner Software B.V.