In case you want to know my implementation of using the customactiondata property, I have included my getter and setter.
function CA_SetProperty(hMSI, sCustomActioName, sPropName)
STRING sCAData, sPropValue;
NUMBER nLength;
begin
nLength = MAX_PATH;
MsiGetProperty(hMSI, sPropName, sPropValue, nLength);
nLength = MAX_PATH;
MsiGetProperty(hMSI, sCustomActioName, sCAData, nLength);
if (StrLength(sCAData) > 0) then
sCAData = sCAData + "|";
endif;
sCAData = sCAData + sPropName + "=" + sPropValue;
MsiSetProperty(hMSI, sCustomActioName, sCAData);
end;
function CA_GetProperty(hMSI, sPropName, sPropValue)
STRING sCAData, sPropPair, sName, sValue;
NUMBER nResult, nLength;
INT nMode;
LIST listProps, listPropPair;
LIST listPropNames;
LIST listPropValues;
begin
nLength = MAX_PATH;
nResult = MsiGetProperty(hMSI, "CustomActionData", sCAData, nLength);
if (nResult < 0) then
//ReportError(hMSI, "The CustomActionData property does not exist.");
return -1;
else
listProps = ListCreate (STRINGLIST);
listPropNames = ListCreate (STRINGLIST);
listPropValues = ListCreate (STRINGLIST);
// Get each path from the search path into the list.
if (StrGetTokens (listProps, sCAData, "|") < 0) then
// Report the error.
//ReportError(hMSI, "StrGetTokens on listProps failed.");
return -1;
else
// Display the individual paths from the list.
nResult = ListGetFirstString (listProps, sPropPair);
// Loop while list items continue to be retrieved.
while (nResult != END_OF_LIST)
// Display the current element.
listPropPair = ListCreate (STRINGLIST);
if (StrGetTokens (listPropPair, sPropPair, "=") > 0) then
// Report the error.
//ReportError(hMSI, "StrGetTokens on ListPropPair failed.");
return -1;
else
if (ListGetFirstString(listPropPair, sName) != END_OF_LIST) then
ListAddString(listPropNames, sName, AFTER);
if (ListGetNextString (listPropPair, sValue) == END_OF_LIST) then
sValue = "";
endif;
ListAddString(listPropValues, sValue, AFTER);
endif;
endif;
ListDestroy(listPropPair);
// Get the next string in the list.
nResult = ListGetNextString (listProps, sPropPair);
endwhile;
endif;
endif;
// Remove the list from memory.
ListDestroy (listProps);
if (ListFindKeyValueString(listPropNames, listPropValues, sPropName, sPropValue) != 0) then
return -1;
endif;
return 0;
end;
In order to use this code, somewhere before the installExecute sequence, I set all my properties.
Example:
CA_SetProperty(hMSI, "Your Custom Action Name", "YOURPUBLICPROPERTY");
Then in the deferred CA I get the value.
Example: In the customer action that matches the above "Your Custom Action Name" I call
CA_GetProperty(hMSI, "YOURPUBLICPROPERTY", svSomeVariable);
I can now use the property in my CA.
If memory serves, only 3 properties are available to you in a deferred CA. Only 1 is useful and that is CustomActionData.
Use it like a mailbox for data.