Доброго времени суток, увожаемый All!
Возникла проблема, об которую набиваю себе большую шишку на голове.
Проблема такая :
Есть msi инсталляция, которая вызывает метод из DLL-ки (кустом акшэном).
Этот метод из DLL-ки делает следующие вещи :
MsiDatabaseOpenView(hopenbase,
__T("INSERT into `Property` (`Property`.`Property`, `Property`.`Value`) VALUES('propDummy', 'valDummy')")
,&hview));
//3)Пытается его запустить...
MsiViewExecute(hview,0)
Ну.. в этом случае возвращается код ошибки ERROR_FUNCTION_FAILED
..В общем, полный облом.
Проблема в правах доступа к базе :
//MSDN :
For read-only access to the current database obtain the database handle by calling MsiGetActiveDatabase
Как это можно обойти? Как из кустом акшн процедуры получить доступ для записи в базу???
Если у кого-то есть решения — плиз помогите.
Функция MsiOpenDatabase может получить хендл с доступом на запись... Но не могу представить, как её можно
использовать из кустом-акшн DLL-процедуры?
Извините за такой экспрессивный мессадж... Буду благодарен за любую помощь!
Проблема в том, что MsiGetActiveDatabase дает только read-only handle, а MsiOpenDatabase для custom action dll не подходит. Смысл этого в том, что неразумно менять базу данных в момент инсталляции, и это, согласись, правильно.
Единственное что, следуя той же логике, можно менять — user-defined Properties.
Для этого есть функция MsiSetProperty.
По-моему должно сработать.
P.S.
Из зачем этот SQL городить? К тому же как-то он подозрительно выглядит... (Property 3 раза повторяется, я бы написал один раз, к тому же я вставляю записи не так: MsiCreateRecord, MsiRecordSet*, MsiViewModify(MSIMODIFY_INSERT), а при создании вью только SELECT нужные мне колонки).
Здравствуйте, Ignoramus, Вы писали:
I>Здравствуйте, tantrum, Вы писали:
I>Проблема в том, что MsiGetActiveDatabase дает только read-only handle, а MsiOpenDatabase для custom action dll не подходит. Смысл этого в том, что неразумно менять базу данных в момент инсталляции, и это, согласись, правильно.
I>Единственное что, следуя той же логике, можно менять — user-defined Properties.
I>Для этого есть функция MsiSetProperty. I>По-моему должно сработать.
I>P.S. I>Из зачем этот SQL городить? К тому же как-то он подозрительно выглядит... (Property 3 раза повторяется, я бы написал один раз, к тому же я вставляю записи не так: MsiCreateRecord, MsiRecordSet*, MsiViewModify(MSIMODIFY_INSERT), а при создании вью только SELECT нужные мне колонки).
Согласен, все правильно. Но у меня такая вот задача — нужно в комбобокс MSI-ный добавить какое-то количество строк
"на лету"- т.е. из вызова кустом-акшн функции Первое, что пришло в голову — это сделать соответсвующий INSERT в msi базу. Не получается Что же мне делать теперь?
Уверен, есть способ сделать это легально. Подскажите, как?
Здравствуйте, tantrum, Вы писали:
T>Согласен, все правильно. Но у меня такая вот задача — нужно в комбобокс MSI-ный добавить какое-то количество строк T>"на лету"- т.е. из вызова кустом-акшн функции Первое, что пришло в голову — это сделать соответсвующий INSERT в msi базу. Не получается Что же мне делать теперь? T>Уверен, есть способ сделать это легально. Подскажите, как?
Может поставить заполнение комбо-бокса из properties, а уже их задавать в runtime через SetProperty?
Здравствуйте, tantrum, Вы писали:
T>Доброго времени суток, увожаемый All! T>Возникла проблема, об которую набиваю себе большую шишку на голове. T>Проблема такая : T>Есть msi инсталляция, которая вызывает метод из DLL-ки (кустом акшэном). T>Этот метод из DLL-ки делает следующие вещи :
T>//1)Получает хендл открытой базы. T>hopenbase=MsiGetActiveDatabase(hInstall);
T>//2)Получает хендл view..
T>MsiDatabaseOpenView(hopenbase, T> __T("INSERT into `Property` (`Property`.`Property`, `Property`.`Value`) VALUES('propDummy', 'valDummy')")
T> ,&hview));
T>//3)Пытается его запустить... T>MsiViewExecute(hview,0)
T>Ну.. в этом случае возвращается код ошибки ERROR_FUNCTION_FAILED
T>..В общем, полный облом. T>Проблема в правах доступа к базе : T>//MSDN : T>For read-only access to the current database obtain the database handle by calling MsiGetActiveDatabase
T>Как это можно обойти? Как из кустом акшн процедуры получить доступ для записи в базу??? T>Если у кого-то есть решения — плиз помогите. T>Функция MsiOpenDatabase может получить хендл с доступом на запись... Но не могу представить, как её можно T>использовать из кустом-акшн DLL-процедуры?
T>Извините за такой экспрессивный мессадж... Буду благодарен за любую помощь!
Да, можно обойти. У меня к примеру добавляются custom action на лету. Нужно в конце SQL запроса просто дописать VALUES(.ля..ля..) TEMPORARY. Но изменения будут только в памяти, вроде то что нужно.
Здравствуйте, tantrum, Вы писали:
T>Согласен, все правильно. Но у меня такая вот задача — нужно в комбобокс MSI-ный добавить какое-то количество строк T>"на лету"- т.е. из вызова кустом-акшн функции Первое, что пришло в голову — это сделать соответсвующий INSERT в msi базу. Не получается Что же мне делать теперь? T>Уверен, есть способ сделать это легально. Подскажите, как?
Реально работающи код, добавляет список сетевых адаптеров.
hDB = MsiGetActiveDatabase(hmsi);
if (hDB == NULL)
throw "MsiGetActiveDatabase failed."
result = MsiDatabaseOpenView(hDB, "SELECT * FROM ComboBox", &hView);
if (result != ERROR_SUCCESS)
throw "NetworkAdapterList: MsiDatabaseOpenView failed.";
xs_string defname;
xs_string desc;
int index =0;
for (int i = 0; i < (int)adapter.count(); ++i)
{
PIP_ADDR_STRING cItem = &adapter[i]->IpAddressList;
while (cItem) {
if (!index) defname = cItem->IpAddress.String;
desc = xs_string(cItem->IpAddress.String);
desc += " ("+xs_string(adapter[i]->Description)+")";
rec = MsiCreateRecord(4);
MsiRecordSetString(rec, 1, "IM_ADAPTER_NAME");
MsiRecordSetInteger(rec, 2, index);
MsiRecordSetString(rec, 3, cItem->IpAddress.String);
MsiRecordSetString(rec, 4, desc.c_str());
MsiViewModify(hView, MSIMODIFY_INSERT_TEMPORARY, rec);
MsiCloseHandle(rec);
cItem = cItem->Next;
index++;
}
}
if (hView != 0) MsiViewClose(hView);
if (hDB != 0) MsiCloseHandle(hDB);
MU::setProperty(hmsi, "IM_ADAPTER_NAME", defname.c_str());