我需要帮助才能关闭MSI文件。
我正在创建一个MSI文件编辑器,我可以在其中打开并更新msi文件。但问题是当我尝试重新打开同一个文件时(只是为了交叉检查更新的msi),它会抛出错误
的openDatabase,DatabasePath,用于openmode
在这一行
database = installer.OpenDatabase(msiFile.FullName, MsiOpenDatabaseMode.msiOpenDatabaseModeTransact);
所以,我相信它,因为msi文件已经打开。任何人都可以帮我关闭已经开放的msi。
答案 0 :(得分:2)
我猜你正在使用从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(隐式或显式),那么在垃圾收集器开始清理之前,不会释放未管理的资源,这对您来说不是一件好事。
答案 1 :(得分:1)
将数据库设置为null或仅强制变量超出范围。这应该释放打开的手柄。
或者,您可能需要强制垃圾收集器运行以放弃句柄。 Best Practice for Forcing Garbage Collection in C#
答案 2 :(得分:1)
我使用数据库作为全局变量,因为我需要在整个应用程序中进行许多不同的事务,所以在打开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();
希望我的回答也能帮助人们陷入同样的境地。
答案 3 :(得分: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();
尝试一下......最后,你应该做得很好。