开发者

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,

Ovanes


Using 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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜