1

我在关闭 MSI 文件时需要帮助。

我正在制作一个 MSI 文件编辑器,我可以在其中打开和更新 msi 文件。但问题是当我尝试重新打开同一个文件(只是为了交叉检查更新的 msi)时,它会引发错误

开放数据库、数据库路径、开放模式

在这条线上

database = installer.OpenDatabase(msiFile.FullName, MsiOpenDatabaseMode.msiOpenDatabaseModeTransact);

所以,我相信它是因为 msi 文件已经打开了。谁能帮我关闭一个已经打开的msi。

4

4 回答 4

3

我猜您正在使用从 WindowsInstaller.Installer COM 对象生成的互操作库。你不想那样做。相信我这个。而是下载 Windows Installer XML 并在 SDK 文件夹中查找 Microsoft.Deployment.WindodsInstaller 程序集。该库是部署工具基础 (DTF) 的一部分,它是与 Windows Installer 互操作的黄金标准。

在 DTF 中,Database 类实现了 IDisposable 接口,因此最优雅的方法是将其放在 using 语句中。

using(Database database = new Database(...))
{
 // Do Stuff Here
}

一旦块完成,.NET 将自动调用 Dispose() 方法,这反过来会关闭数据库并释放非托管句柄。然后将通知垃圾收集器在以后的非重要时间清理托管类。如果您未能调用 Dispose(隐式或显式),那么在垃圾收集器开始清理之前不会释放未管理的资源,这不会是您所看到的一件好事。

于 2013-02-11T13:47:07.637 回答
2

嘿斯蒂芬和克里斯托弗,这就是我使用您宝贵的建议解决我的问题的方法。

我使用数据库作为全局变量,因为整个应用程序中的许多不同事务都需要它,所以在打开 msi 文件之前添加了这些行。

if (view != null)
   {
      System.Runtime.InteropServices.Marshal.FinalReleaseComObject(view);
      view = null;
   }
if (database != null)
   {
      System.Runtime.InteropServices.Marshal.FinalReleaseComObject(database);
      database = null;
   }
GC.Collect();

希望我的回答也能帮助陷入同样情况的人们。

于 2013-02-12T07:35:28.950 回答
1

将数据库变量设置为 null 或强制变量超出范围。这应该释放打开的句柄。

或者,您可能需要强制垃圾收集器运行以放弃句柄。在 C# 中强制垃圾回收的最佳实践

于 2013-02-11T13:08:27.680 回答
0

您将不得不释放每个手柄,例如:

Database database = _installer.OpenDatabase(...);
View view = database.OpenView(query);
view.Execute();
Record record = view.Fetch();

Marshal.FinalReleaseComObject(record);
view.Close();
Marshal.FinalReleaseComObject(record);
Marshal.FinalReleaseComObject(database);
record = null;
view = null;
database = null;
GC.Collect();

尝试一下……最后,你应该会很好。

于 2013-06-25T16:30:18.100 回答