2009-04-27 2 views
1

Я поддерживаю некоторые скрипты сборки, которые обрабатывают базы данных MSI из файлов Javascript (.js). Код в основном:Javascript MSI automation - закрытие базы данных

{ 
    var oTargetDB = g_oInstaller.openDatabase("mymsi.msi", msiOpenDatabaseModeReadOnly); 
    var oView = oTargetDB.openView(...); 
    oView.execute(); 
    oView.close(); 
} 
// Later... 
{ 
    var oTargetDB = g_oInstaller.openDatabase("mymsi.msi", msiOpenDatabaseModeTransact); 
} 

второй OpenDatabase терпит неудачу с постоянно полезными 0x80004005 (E_FAIL), который я предполагаю, потому что первый не закрыт. Однако объект базы данных не имеет близкого метода. Я пробовал oTargetDB = null - ничего не менял.

Что можно сделать, чтобы закрыть базу данных, чтобы я мог открыть ее снова?

Edit:

  • Я вижу ручку с открытым использованием Handle.exe от Sysinternals, так что это определенно проблема
  • Задержка не помогло (я пытался ждет очень долго, и это Бесполезный «т помощь)
  • Короткоживущие сценарий не вариант из-за существующую структуру сценария
  • Uber-хакинг выходит за рамки этого исправить
  • мне придется уродовать свой код и идти с (псевдо-синглтон) s olution. Blergh.

ответ

0

Установка дескриптора в null работает с VB Script, поэтому я не уверен, почему это не с JS. Мое лучшее предположение, возможно, заключалось в том, что вы обнаружили ошибку в JS implimentation - особенно если вы открываете его как только для чтения в первый раз, нет необходимости вызывать метод Commit для сброса любых изменений.

documentation, похоже, указывает, что просто закрыть дескриптор - это все, что необходимо для закрытия базы данных. Поэтому я угадываю даже после установки oTargetDB = null Javascript не освобождает дескриптор к тому моменту, когда вы открываете его снова. Вы можете попробовать вставить задержку после отпускания дескриптора, чтобы убедиться, что это так.

0

В этом случае MS забыл реализовать метод close. В самом деле. Хм, да? В общем случае установка obj = null не выполняет очистку, например, операции закрытия.

Когда я столкнулся с конкретной проблемой, он вызывал объекты MSIDatabase из C#. База данных должна быть закрыта (см. MsiOpenDatabase и MsiCloseHandle). К сожалению, как вы заметили, MS забыла реализовать Database.Close в COM-объекте, который вы видите. С C# я смог вызвать Marshal.FinalReleaseComObject, чтобы разблокировать файл.

Мы случайно отказались от COM-объекта как ненадежные и переключились на p/invoke.

Если jscript - это ваш единственный вариант, вы можете сохранить сценарии недолговечными - когда они умрут, они освободят свои ручки. Или вы создаете синглтон для представления объекта. Потенциально, некоторый uberhacker будет знать, как вызывать MsiCloseHandle из jScript и идентифицировать дескриптор, используемый этим объектом COM.