Javascript MSI自动化 - 关闭数据库

时间:2009-04-27 14:40:21

标签: windows-installer

我正在维护一些构建脚本,这些脚本可以从Javascript文件(.js)中获取MSI数据库。代码基本上是:

{
    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),我认为这是因为第一个没有关闭。但是,Database对象没有close方法。我试过oTargetDB = null - 没有改变任何东西。

我可以做什么来关闭数据库,所以我可以再次打开它?

编辑:

  • 我看到使用sysinternals中的handle.exe打开句柄,所以肯定是问题
  • 延迟没有帮助(我试着等了很长时间,但没有帮助)
  • 由于现有的脚本结构
  • ,短期脚本不是一个选项
  • Uber-hacking超出了此修复的范围
  • 我将不得不解开我的代码并使用(伪单例)解决方案。 Blergh。

2 个答案:

答案 0 :(得分:0)

将句柄设置为null适用于VB脚本,所以我不确定为什么它不适用于JS。我最好的猜测可能是你发现了JS中的一个错误 - 特别是如果你是第一次以只读方式打开它,就没有必要调用Commit方法来刷新任何改变。

documentation似乎表明只需关闭句柄即可关闭数据库。所以即使在设置oTargetDB = null之后我也猜测Javascript在您再次打开它时没有释放句柄。您可以尝试在释放句柄后插入延迟以查看是否是这种情况。

答案 1 :(得分:0)

在这种情况下,MS忘记实现close方法。真。嗯嗯?通常,设置obj = null不会执行清理,例如关闭操作。

当我遇到特定的问题时,它正在从C#调用MSIDatabase对象。需要关闭数据库(请参阅MsiOpenDatabaseMsiCloseHandle)。不幸的是,正如您所观察到的,MS忘记在您看到的COM对象中实现Database.Close。从C#开始,我可以调用Marshal.FinalReleaseComObject来解锁文件。

我们甚至放弃了COM对象不可靠并切换到p / invoke。

如果jscript是你唯一的选择,你可以让脚本保持短暂状态 - 当它们死亡时它们会释放它们的句柄。或者,您创建一个单例来表示对象。潜在地,一些uberhacker将知道如何从jScript调用MsiCloseHandle,并识别该COM对象使用的句柄。