Windows Installer
От: tantrum США  
Дата: 10.06.05 17:26
Оценка:
Доброго времени суток, увожаемый All!
Возникла проблема, об которую набиваю себе большую шишку на голове.
Проблема такая :
Есть msi инсталляция, которая вызывает метод из DLL-ки (кустом акшэном).
Этот метод из DLL-ки делает следующие вещи :

//1)Получает хендл открытой базы.
hopenbase=MsiGetActiveDatabase(hInstall);

//2)Получает хендл view..

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-процедуры?

Извините за такой экспрессивный мессадж... Буду благодарен за любую помощь!
Re: Windows Installer
От: Ignoramus  
Дата: 10.06.05 21:16
Оценка:
Здравствуйте, tantrum, Вы писали:

Проблема в том, что MsiGetActiveDatabase дает только read-only handle, а MsiOpenDatabase для custom action dll не подходит. Смысл этого в том, что неразумно менять базу данных в момент инсталляции, и это, согласись, правильно.

Единственное что, следуя той же логике, можно менять — user-defined Properties.

Для этого есть функция MsiSetProperty.
По-моему должно сработать.

P.S.
Из зачем этот SQL городить? К тому же как-то он подозрительно выглядит... (Property 3 раза повторяется, я бы написал один раз, к тому же я вставляю записи не так: MsiCreateRecord, MsiRecordSet*, MsiViewModify(MSIMODIFY_INSERT), а при создании вью только SELECT нужные мне колонки).
Re[2]: Windows Installer
От: tantrum США  
Дата: 13.06.05 08:34
Оценка:
Здравствуйте, 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 базу. Не получается Что же мне делать теперь?
Уверен, есть способ сделать это легально. Подскажите, как?
Re[3]: Windows Installer
От: Ignoramus  
Дата: 13.06.05 09:19
Оценка:
Здравствуйте, tantrum, Вы писали:

T>Согласен, все правильно. Но у меня такая вот задача — нужно в комбобокс MSI-ный добавить какое-то количество строк

T>"на лету"- т.е. из вызова кустом-акшн функции Первое, что пришло в голову — это сделать соответсвующий INSERT в msi базу. Не получается Что же мне делать теперь?
T>Уверен, есть способ сделать это легально. Подскажите, как?

Может поставить заполнение комбо-бокса из properties, а уже их задавать в runtime через SetProperty?
Re: Windows Installer
От: sharpcell  
Дата: 19.09.06 07:35
Оценка:
Здравствуйте, 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. Но изменения будут только в памяти, вроде то что нужно.
Re[3]: Windows Installer
От: ffk  
Дата: 19.09.06 07:47
Оценка: 1 (1)
Здравствуйте, 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());
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.