Error Handling in Custom Actions

Windows Installer automatically manages most error handling in deployment; however, errors in custom actions can cause an installer to fail. All custom actions contain code; as with any code, error handling is an essential part of the process. For example, if a custom action includes code that opens a file and the file is missing, an error handler is necessary to report the error back to Windows Installer so that the installation can be rolled back.

Note

For custom actions that are written using JScript or VBScript, the error will not be returned to Windows Installer and the installation cannot be rolled back; an error dialog can be displayed to the user. Custom actions that are critical to an installation should be written in Visual Basic, Visual C#, or Visual C++ in order to pass the error to Windows Installer.

Trap the Error

To handle an error in a custom action, you need to add code to trap the error and pass the information back to Windows Installer. The following examples show how to handle an error in Visual Basic, Visual C#, Visual C++, JScript, and VBScript code:

' Uses System.IO and System.Configuration.Install
Dim Info As New FileInfo("MyFile.txt")
If Not Info.Exists Then
    Throw New InstallException("File does not exist")
End If
// Uses System.IO and System.Configuration.Install
FileInfo Info = new FileInfo("MyFile.txt");
if (Info.Exists == false)
   throw new InstallException("File does not exist");
'VBScript
msiMessageTypeError = &H01000000 
Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FileExists("c:\MyFile.txt") Then
   Set record = Session.Installer.CreateRecord(0)
   record.StringData(0) = "File not found."
   Session.Message msiMessageTypeError, record
End If
var msiMessageTypeError = 0x01000000;
var fso = new ActiveXObject("Scripting.FileSystemObject");
if (!fso.FileExists("c:\\MyFile.txt"))
{
   var record = Session.Installer.CreateRecord(0);
   record.StringData(0) = "File not found.";
   Session.Message(msiMessageTypeError, record);
}
#pragma comment(lib, "msi.lib")

#include <windows.h>
#include <msiquery.h>

BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD fdwREason, LPVOID lpReserved)
{
   return TRUE;
}

extern "C" __declspec(dllexport) __stdcall Install(MSIHANDLE hInstall)
{
   if (GetFileAttributes(TEXT("c:\\MyFile.txt")) == -1)
   {
      PMSIHANDLE hRecord = MsiCreateRecord(0);
      MsiRecordSetString(hRecord, 0, TEXT("File does not exist."));
      MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_ERROR + MB_OK), hRecord);
      return ERROR_INSTALL_USEREXIT;
   }
   
   return ERROR_SUCCESS;
}

See Also

Other Resources

Custom Actions Management in Deployment