Open sergey-s-betke opened 10 years ago
Использовать idapinst.dll
я не буду - там есть функции для регистрации псевдонимов, но нет - для удаления. Поэтому использовать будем idapi32.dll
.
Код для создания псевдонима нам необходим следующий:
DbiInit(nil);
DbiDeleteAlias(nil, PChar(GAlias));
DbiAddAlias(nil, PChar(StrToOem(GAlias)), PChar(StrToOem(FDrvName)), PChar(FParams), True);
DbiCfgSave(nil, nil, True);
DbiExit();
Создадим скриплет на базе wsc, DynamicWrapperX и idapi32.dll для "обёртывания" необходимых нам методов в ActiveX. Во-первых - инкапсуляция, во-вторых, в дальнейшем можно будет обеспечить управление и через powershell, и не только.
Опять-таки, при создании скриплета следует помнить про платформу: не сможет x64 скриплет (а он по умолчанию будет именно таким на x64 платформе) использовать x86 DynWrapX. Поэтому для 32битных приложений необходимо регистрировать x86 скриплет. Т.е. регистрировать его (скриплет) необходимо следующим образом:
c:\windows\syswow64\regsvr32.exe mywsc.wsc
Хоть какой-то список ошибок BDE: http://base.vingrad.ru/view/1599-Spisok-oshibok-BDE.
Пока не могу решить проблему следующую: при попытке записи конфигурации (SaveConfigFile
, dbiCfgSave
) получаю ошибку 8453
- "Cannot write to Engine configuration file".
При этом файл на месте, права на запись есть даже у пользователей.
Необходимо помнить о том, что в роли пустого указателя использовать в jscript null не следует, следует использовать 0
.
Сейчас имею редакцию скриплета, которая уже позволяет программно регистрировать псевдоним BDE, например - на PowerShell:
$t = New-Object -ComObject ITG.BDEAdministrator;
$t.Init( $null );
$t.AddAlias( 'NevaTest3303P', 'Microsoft dBase Driver (*.dbf)', 'DSN:NevaTest3303P;DESCRIPTION:База данных результатов поверок НеваТест 3303П', $null );
$t.SaveConfigFile( $null );
$t.Done( $null );
[System.Runtime.InteropServices.Marshal]::ReleaseComObject( $t );
Работает скриплет пока неустойчиво, и периодически "роняет" PoSh ISE. Проблемы с выделением памяти, но пока неясно - где.
Есть ещё одна замечательная функция:
extern PACKAGE Word __stdcall DbiImportODBC(hDBICfg hCfg, BOOL bPersist);
Стоит её опробовать. Как я понимаю, она позволяет импортировать в BDE все ODBC DSN. Если это так - тогда всё упрощается существенно. Во всех дистрибутивах буду использовать только ODBC DSN, регистрировать их можно и в MSI, и через GPO "штатными" средствами, а при установке BDE будут принудительно импортировать все ODBC DSN.
В любом случае, нужно добавить ещё метод для удаления псевдонима BDE, и опробовать действия с импортом ODBC DSN.
Как это не смешно, ошибку следует искать в функциях, возвращающих версию BDE. Без их использования скрипт прекрасно многократно выполняется без всяких последствий.
Исправил ошибку в getVersion
в скриплете, теперь он вполне устойчив.
Теперь пришло время создать custom action скрипт, который уже и будет регистрировать необходимый алиас или удалять его с использованием нашего скриплета, предварительно зарегистрированного.
Скриплет интегрировал в дистрибутив, протестировал процедуру его установки и удаления. Всё в порядке. После установки прекрасно работает из PowerShell.
Есть некоторые сложности с откатом создания и удаления псевдонимов BDE. С одной стороны - всё уже готово: сохраняем изменения в конфигурацию только в commit. Но скрипт и объекты в нём не будут жить между действиями. В этом и проблема.
Пока вижу следующее решение: перед изменениями сохраняем конфигурацию во временный файл, потом выполняем все необходимые действия, и в commit ничего делать не надо, а в rollback - восстанавливаем конфигурацию. Аналогично и с удалением.
В итоге - в скриплет необходимо добавить действия по резервированию конфигурации и по откату её изменений.
Есть ещё одна проблема. Начиная с версии 5.8 JScript в WSH поддерживает объект JSON
и всё, что с ним связано. На интересующих нас ОС версия именно 5.8. Но для получения его возможностей необходимо специальным образом его запускать, что msi не обеспечивает. В результате, JSON в custom action мы не имеем. А выдумывать иной формат для упаковки CustomActionData
глупо в случае использования JScript.
Нашёл проект, который может оказаться очень полезным для использования JSON на JScript 5.7 - https://github.com/douglascrockford/JSON-js/blob/master/json2.js. Попробуем его и использовать.
Итак, резервирование конфигурации BDE успешно выполняется. Следует ещё протестировать её восстановление при откате.
Код регистрации алиасов и их удаления так же написан.
Теперь осталось самое сложное (потому как - незнакомое). Теперь необходимо сделать запрос к таблицам пакет .msi, получить сведения о регистрируемых алиасах, связать их с компонентами, и только для тех компонентов, для которых изменяется состояние на "установлен" (не важно - локально, или source
) - их алиасы необходимо планировать на установку.
При удалении обратные действия - только те алиасы, которые связаны с удаляемыми компонентами, следует запланировать к удалению.
Так же отдельно следует обработать и процедуру восстановления - в этом случае состояние компонентов не меняется, а переустановить алиасы необходимо.
Всё-таки при ошибке удаления пакета стоит дать возможность игнорировать эти ошибки. Речь о наших custom action.
В исходниках WiX нашёл пример кода, обрабатывающего custom table: http://wix.codeplex.com/SourceControl/latest#src/ext/ca/wixca/dll/netshortcuts.cpp.
Есть одна тонкость, которую следует проверить. В указанном выше коде для создания ВСЕХ ярлыков планируется одна custom action для создания, и одна - для удаления. И в них уже перебирается некий поток custom action data, содержащий параметры для всех ярлыков. Я же планировал "вызывать" для каждого алиаса custom action data, передавая custom action data только на один алиас. Так и откатывать куда проще, по логике.
Для начала проверю свой вариант, если он не будет работать (сомнения только в передаче custom action data), тогда буду использовать алгоритм, реализованный в указанном коде.
WcaProgressMessage
(последний параметр true
при планировании, и false
при исполнении)WcaOpenExecuteView
== Session.Database.OpenView
, View.Execute
(http://msdn.microsoft.com/en-us/library/aa368255.aspx)WcaFetchRecord
== View.Fetch
WcaGetRecordString
WcaGetComponentToDo
== Session.ComponentRequestState
+ Session.ComponentCurrentState
WcaTableExists
== Database.PrimaryKeys
Код этих функций - http://wix.codeplex.com/SourceControl/latest#src/libs/wcautil/.
А здесь http://wix.codeplex.com/SourceControl/latest#src/ext/ca/serverca/scasched/scasched.cpp исходник IIS custom action.
Для отображения в интерфейсе выполняемых custom action следует так же использовать Session.Message
, но с типом msiMessageTypeActionStart
. Следует разобраться с данным вопросом и включить в наши custom action эти действия.
Следует так же протестировать наши custom action с их сообщениями на случай отключенного интерфейса.
Наткнулся на проект с дополнительными расширениями к WiX - https://github.com/dblock/msiext.
Здесь приведён пример http://bonemanblog.blogspot.ru/2004/09/making-progress-bars-behave-nicely.html по подготовке progress bar и его изменению при каждом сообщении ActionData.
Пора приступать собственно к созданию псевдонимов. Таблицу для их определений создам в конечном пакете через CustomTable
на этом этапе.
Создал таблицу BDEAlias
. Приступаю к её обработке в custom action.
hyyb.ini
содержит в том числе параметры подключения к базе данных:Ясны только первых три параметра. Их и будем рассматривать в данном контексте.