I am relatively new to MSI and also just started (self) learning C++. I have been writing custom ICE in VBScript succesfully and wanted to see if I could achieve similar in C++.
Attempting to write a custom ICE cub file that will validate an msi (+msts) (I am validating via Orca). I have managed to open an msi external to the cub and read tables and can read the properties from th cub database within the ICE CA, also sending messages out for errors warnings and info. Code is put together from what I have managed to find in terms of decent examples.
I thought that when orca validated it merged the databases together, so hoped the database object would return something I can read.
My latest attempt is to read the tmp files that are being created during the validation hoping they are the merged msi so I can validate against that.
Any hints on where I am going wrong would be appreciated. Here's some of the code from the DLL (it a bit messy as I have been going roud in circles trying various things...
; MyCustomAction.def
;
; defines the exported functions which will be available to the MSI engine
LIBRARY "MyCustomAction"
DESCRIPTION 'Custom Action DLL created for CodeProject.com'
EXPORTS
SampleFunction
SampleFunction2
SampleFunction3
ReadDatabase
ReadDatabaseMe
#include "stdafx.h"
#include "MSI_Logging.h"
#include "msiQuery.h"
include <windows.h>
#include <stdio.h>
#include <tchar.h>
BOOL APIENTRY DllMain( HANDLE hInstall,
DWORD ul_reason_for_call,
LPVOID lpReserved )
{
return TRUE;
}
UINT __stdcall ReadDatabaseMe ( MSIHANDLE hInstall )
{
char szIceName[255];
sprintf(szIceName, "ICEC++01");
PumpMessage( hInstall, szIceName, UI_MSI_MESSAGE_TYPE_ERROR, "Description", "HelpURL", "TableName", "ColumnName", "PrimaryKeys");
// This function opens up the current MSI database and reads in the column values from a table
TCHAR szFilePath[MAX_PATH] = {'0'};
char *sFilePath;
DWORD dwLen = MAX_PATH;
MsiGetProperty(hInstall, "OriginalDatabase", szFilePath, &dwLen); // get the file path and name of this database
TCHAR szProductCode[MAX_PATH] = {'0'};
MsiGetProperty(hInstall, "ProductCode", szProductCode, &dwLen); // get the product code
PumpMessage(hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, szProductCode, "", "", "", "");
MSIHANDLE hDb;
hDb = MsiGetActiveDatabase(hInstall);
if (hDb == 0)
{
PumpMessage(hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, "Not got Acvtive Database", "", "", "", "");
}else{
PumpMessage(hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, "Got Active Database", "", "", "", "");
MsiGetProperty(hDb, "ProductName", szProductCode, &dwLen);
PumpMessage(hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, szProductCode, "", "", "", "");
}
/*
MSIHANDLE hPackage;
if (::MsiOpenPackage("#0001", &hPackage) != ERROR_SUCCESS)
{
PumpMessage(hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, "Cannot open package.", "", "", "", "");
}else{
PumpMessage(hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, "Opened package.", "", "", "", "");
}
*/
TCHAR szFilePathParsed[520] = {'0'};
//C:\Documents and Settings\Administrator\Local Settings\Temp
int iCheck; // used to check each character in source string
int y = 0; // used to build final string
int z; // used to find end point
int j; // used to find last backslash
for(int x=0; x<MAX_PATH; x++)
{
iCheck = szFilePath[x]; // find the internal number stored at memory location for char
if(iCheck == 0)
{
z = x;
x = MAX_PATH;
goto endloop;
}
//if(szFilePath[x] == 92)
if(iCheck == 92) // check for backslash then replace with double backslash
{
j = x;
szFilePathParsed[y] = 92;
y++;
szFilePathParsed[y] = 92;
}else{
szFilePathParsed[y] = szFilePath[x];
}
y++;
endloop:;
}
szFilePathParsed[y] = 0;
PumpMessage(hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, szFilePathParsed, "", "", "", "");
TCHAR szFileNameParsed[520] = {'0'};
int p = 0;
for(int x=j+1; x<z+1; x++)
{
szFileNameParsed[p] = szFilePath[x];
p++;
}
PumpMessage(hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, szFileNameParsed, "", "", "", "");
////sFilePath = "C:\\Documents and Settings\\Administrator\\Desktop\\C++\\example.msi";
TCHAR sProductCode[MAX_PATH] = {'0'};
MsiGetProperty(hInstall, "ProductCode", sProductCode, &dwLen);
MSIHANDLE hDatabase, hView, hRecord, hProduct; //define handles to database, view and record
////if(::MsiOpenProduct(sProductCode, &hProduct) != ERROR_SUCCESS)
////{
//// PumpMessage( hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, "Cannot Open Product.", "", "", "", "");
////return FALSE;
////}
////PumpMessage( hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, "Opened Product.", "", "", "", "");
char szFilePathFinal[560];
sprintf(szFilePathFinal, "C:\\\\Documents and Settings\\\\Administrator\\\\Local Settings\\\\Temp\\\\%s", szFileNameParsed);
PumpMessage(hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, szFilePathFinal, "", "", "", "");
/*
if (::MsiOpenDatabase(szFilePathFinal, MSIDBOPEN_READONLY, &hDatabase) != ERROR_SUCCESS) // now open this database to read the tables
{
PumpMessage( hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, "Cannot Open database.", "", "", "", "");
return FALSE;
}
*/
//LogString(hInstall, "Opened database.");
PumpMessage( hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, "Opened database.", "", "", "", "");
char szSelect[256];
char *sTableName;
sTableName = "CustomAction"; //define table to read
wsprintf(szSelect, "SELECT * FROM %s", sTableName); //define query
//if (MsiDatabaseOpenView(hDatabase, szSelect, &hView) != ERROR_SUCCESS)
if (MsiDatabaseOpenView(hInstall, szSelect, &hView) != ERROR_SUCCESS)
{
PumpMessage( hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, "Cannot open view.", "", "", "", "");
return FALSE;
}
PumpMessage( hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, "Opened view.", "", "", "", "");
if (MsiViewExecute(hView, NULL) != ERROR_SUCCESS)
{
PumpMessage(hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, "Cannot execute view.", "", "", "", "");
return FALSE;
}
PumpMessage(hInstall, szIceName, UI_MSI_MESSAGE_TYPE_INFORMATION, "Executed view.", "", "", "", "");
>>>>>>>>>>>.etc.
}
This is a ready-only archive of the InstallSite Forum. You cannot post any new content here. / Dies ist ein Archiv des InstallSite Forums. Hier können keine neuen Beiträge veröffentlicht werden.

Custom ICE in C++ Reading Database
Started by
nga
, Jan 11 2006 14:34
1 reply to this topic