Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在读取或更新后关闭MSI文件_C#_Windows Installer - Fatal编程技术网

C# 如何在读取或更新后关闭MSI文件

C# 如何在读取或更新后关闭MSI文件,c#,windows-installer,C#,Windows Installer,我需要关闭MSI文件的帮助 我正在制作一个MSI文件编辑器,在那里我可以打开并更新MSI文件。但问题是,当我试图重新打开同一个文件(只是为了交叉检查更新的msi)时,它会抛出一个错误 OpenDatabase、DatabasePath、OpenMode 在这条线上 database = installer.OpenDatabase(msiFile.FullName, MsiOpenDatabaseMode.msiOpenDatabaseModeTransact); 所以,我相信这是因为msi文

我需要关闭MSI文件的帮助

我正在制作一个MSI文件编辑器,在那里我可以打开并更新MSI文件。但问题是,当我试图重新打开同一个文件(只是为了交叉检查更新的msi)时,它会抛出一个错误

OpenDatabase、DatabasePath、OpenMode

在这条线上

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

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

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


或者,您可能需要强制垃圾收集器运行以放弃句柄

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


或者,您可能需要强制垃圾收集器运行以放弃句柄

我猜您正在使用从WindowsInstaller.Installer.COM对象生成的互操作库。你不想那样做。在这件事上相信我。而是下载Windows Installer XML并查找SDK文件夹中的Microsoft.Deployment.WindodsInstaller程序集。这个库是部署工具基础(DTF)的一部分,它是与Windows安装程序交互的金标准。 在DTF中,数据库类实现IDisposable inteface,因此最优雅的方法是将其放在using语句中

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

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

我猜您使用的是从WindowsInstaller.Installer COM对象生成的互操作库。你不想那样做。在这件事上相信我。而是下载Windows Installer XML并查找SDK文件夹中的Microsoft.Deployment.WindodsInstaller程序集。这个库是部署工具基础(DTF)的一部分,它是与Windows安装程序交互的金标准。 在DTF中,数据库类实现IDisposable inteface,因此最优雅的方法是将其放在using语句中

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

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

嘿,Stephen和Christopher,这就是我使用您宝贵的建议解决问题的方法

我使用数据库作为全局变量,因为我需要它来处理整个应用程序中的许多不同事务,所以在打开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();

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

嘿,斯蒂芬和克里斯托弗,这就是我如何利用你们宝贵的建议解决问题的方法

我使用数据库作为全局变量,因为我需要它来处理整个应用程序中的许多不同事务,所以在打开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();

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

您必须释放每个句柄,例如:

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();

试试看。。。最后,你应该很好。

你必须释放每个手柄,例如:

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();

试试看。。。最后,您应该很好。

您是否寻找了
Close()
方法,或者尝试过将
数据库的
变量封装在
using
语句中?数据库上没有Close()方法&“using”语句不起作用。我的回答将解决您的问题。如果没有,则说明您做错了。您是否查找了
Close()
方法,或者尝试过将
数据库
变量封装在
using
语句中?数据库上没有Close()方法&“using”语句不起作用。我的答案将解决您的问题。如果没有,那你就做错了。你为什么不直接处理这个班?你为什么不直接处理这个班?谢谢克里斯,我明白你想解释的。但现在,我已经使用互操作库实现了它。一旦我计划更新这个应用程序,我想我将使用你的方法。再次感谢你的帮助。我在这方面有丰富的经验。相信我,重构不会那么困难,而且你的状态会更好。等待的时间越长,返工的次数就越多。DTF使用P/Invoke,它比COM互操作更干净,还支持WPF数据绑定和LINQ到MSI查询。谢谢Chris,我明白了您要解释的内容。但现在,我已经使用互操作库实现了它。一旦我计划更新这个应用程序,我想我将使用你的方法。再次感谢你的帮助。我在这方面有丰富的经验。相信我,重构不会那么困难,而且你的状态会更好。等待的时间越长,返工的次数就越多。DTF使用P/Invoke,它比COM互操作更干净,还支持WPF数据绑定和LINQ到MSI查询。谢谢!GC.Collect不是为我做的,这是。谢谢!GC.Collect不是为我做的,而是这个。