Tuesday, March 29, 2016

Msi custom action pass parameter for C# custom action and c++ custom action

C# custom action is very simple,
read : var = Session["PROPERTYNAME"]
write : Session["PROPERTYNAME"] = var

C++ custom action is different, we could get msi handle, but can not read public property directly, we should pass the data as CustomActionData  property , read the customActionData as below:

unsigned long nBufLen = 256UL;
CHAR *wszValue = new CHAR[nBufLen];
DWORD trueLength = 0UL;
UINT result = MsiGetProperty(hInstall, "CustomActionData", "", &trueLength); // Get the size of the property value first to see if there is enough storage allocated.
if (ERROR_MORE_DATA == result || nBufLen <= trueLength)
{
if (NULL != wszValue)
{
delete[] wszValue;
}
WcaLog(LOGMSG_STANDARD, "the length we get for CustomActionData %lu", trueLength);
// Allocate more memory for the property adding one for the null terminator.
nBufLen = trueLength + 1;
wszValue = new CHAR[nBufLen];
}

if (NULL == wszValue)
{
err = ERROR_NOT_ENOUGH_MEMORY;
WcaLog(LOGMSG_STANDARD, "Unable to determine the CustomActionData the MSI is being run with because we were unable to allocate storage for accessing the 'CustomActionData' property.");
goto LExit;
}

memset(wszValue, L'\0', nBufLen * sizeof(CHAR));
result = MsiGetProperty(hInstall, "CustomActionData", wszValue, &trueLength);
if (ERROR_SUCCESS != result)
{
err = result;

WcaLog(LOGMSG_STANDARD, "Unable to determine the CustomActionData, error code = '%lu'.", result);
delete[] wszValue;
goto LExit;
}


In Wix project, we should pass the value to custom action data as below:
1: add customaction dll to binary table.
2: create 2 custom action,  us SetProperty to set the CustomActionData.
3: InstallExecuteSequence to create the events order.

<Binary Id="CA" SourceFile="$(var.SourceDir)CA.dll"/>
<CustomAction Id="CA" BinaryKey="CA" DllEntry="CA" Execute="deferred" Impersonate="no" Return="check" PatchUninstall="no" HideTarget="yes" />
        <CustomAction Id="CA.SetProperty" Return="check" Property="CA" Value="[PROPERTYNAME]" />

<InstallExecuteSequence>
<Custom Action="CA.SetProperty" After="InstallFiles">NOT Installed</Custom>
            <Custom Action="CA" After="CA.SetProperty"  >NOT Installed</Custom>
</InstallExecuteSequence>



Below link is the empty project for create custom action:
(The VS Express not support the template, but we could use msbuild command line to build the wix project)

https://drive.google.com/folderview?id=0B7dEKLhQos-wTWNXTkRGY2hqaUU&usp=sharing

Custom Action empty project to download