Update MSI table using MSI programming API
I need to update an 开发者_StackOverflowAttributes column in an MSI file. Unfortunately, I am unable to find any documentation (esp. for C++).
Here is a code snippet of what I am trying to do:
DatabasePtr db = /* opening db succeeds*/
ViewPtr view = db->OpenView(_bstr_t("SELECT Attributes FROM Component"));
view->Execute(NULL);
RecordPtr record=view->Fetch();
record->PutIntegerData(2, record->GetIntegerData(1)|2048);
// I do not exactly understand the next 2 lines
// Should I really call Execute before Modify?
record->Execute(record);
record->Modify(msiViewModifyUpdate, record); //throws a _com_error
As stated upon record->Modify(...) throw a _com_error stating: IDispatch error #1000? What does that mean. Where Can I look up these error codes? These are not HRESULTs...
But more important questions are how do I update the record properly? How can I iterate through all selected records? Doing a new fetch and comparing the record with NULL results in an infinite loop.
Thanks for help,
OvanesUsing C++ for this is a bit overkill. Have a read on DTF:
- Automating MSI using DTF, overview
- A more comprehensive list of links on DTF
Ok, found the problem :(
I opened the database in the read-only mode.
Here is the snipped which works:
InstallerPtr installer(TEXT("WindowsInstaller.Installer"));
VARIANT open_flag;
VariantInit(&open_flag);
open_flag.vt = VT_I4;
open_flag.lVal = msiOpenDatabaseModeTransact;
DatabasePtr db = installer->OpenDatabase(msi_path, open_flag);
{
ViewPtr view = db->OpenView(_bstr_t("SELECT Attributes FROM Component"));
view->Execute(NULL);
RecordPtr record=view->Fetch();
if(!record) ... //error handling
while(record)
{
record->PutIntegerData(1, record->GetIntegerData(1)|2048);
record->Modify(msiViewModifyUpdate, record);
record=view->Fetch();
}
} //view->Close() is called implicitly
db->Commit();
Hope that helps to someone.
Ovanes
精彩评论