I have a C++ application in Visual Studio 2010 and I have a Windows Installer (i.e. setup project) to install it. I want to be able to invoke the installer like this:
Setup1.msi MYPROPERTY=MyValue
And then be able to extract the value "MyValue" from the property from within my custom action. I tried to get it working by following this tutorial(C++ custom actions) and this tutorial (passing arguments to custom actions, but in C#) combined with some MSDN searches to get this code:
#define WINDOWS_LEAN_AND_MEAN
#include <Windows.h>
#include <msi.h>
#include <msiquery.h>
#include <stdio.h>
BOOL APIENTRY DllMain(HANDLE, DWORD, LPVOID) {
return TRUE;
}
UINT APIENTRY InstallCustomAction(MSIHANDLE install_handle) {
static const wchar_t* kPropertyName = L"MYPROPERTY";
//auto msi_handle = MsiGetActiveDatabase(install_handle);
DWORD n = 0;
//auto result = MsiGetProperty(msi_handle, kPropertyName, L"", &n);
auto result = MsiGetProperty(install_handle, kPropertyName, L"", &n);
wchar_t* value = nullptr;
if (result == ERROR_MORE_DATA) {
++n;
value = new wchar_t[n];
//result = MsiGetProperty(msi_handle, kPropertyName, value, &n);
result = MsiGetProperty(install_handle, kPropertyName, value, &n);
}
if (result == ERROR_SUCCESS) {
wchar_t buffer[128];
swprintf_s(buffer, L"n = %d, value = %s", n, value);
MessageBox(nullptr, buffer, L"CustomAction", MB_OK);
} else {
MessageBox(nullptr, L"Error reading property", L"Error", MB_OK);
}
delete value;
//MsiCloseHandle(msi_handle);
return ERROR_SUCCESS;
}
I'm following the C# tutorial exactly in terms of the IDE (I have Entry Point
set to InstallCustomAction
and Custom Action
Data set to /MYPROPERTY=[MYPROPERTY]
) The custom action fires correctly but I don't get the parameter.
With the code as-is, I get n=0. If I use the msi_handle
from MsiGetActiveDatabase
I get an error (i.e. MsiGetProperty returns something other than ErrorSuccess).
How can I get the property that the user passes in on the command line from within my custom action?