首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在.NET中发布COM句柄

如何在.NET中发布COM句柄
EN

Stack Overflow用户
提问于 2012-03-26 07:19:08
回答 3查看 2.1K关注 0票数 3

我使用ASP.NET 4.0框架下的以下代码从web应用程序中获得MSI文件的版本:

代码语言:javascript
运行
复制
string strVersion = "";

try
{
    Type InstallerType;
    WindowsInstaller.Installer installer;

    InstallerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
    installer = (WindowsInstaller.Installer)Activator.CreateInstance(InstallerType);

    WindowsInstaller.Database db = installer.OpenDatabase(strMSIFilePath, 0);

    WindowsInstaller.View dv = db.OpenView("SELECT `Value` FROM `Property` WHERE `Property`='ProductVersion'");

    WindowsInstaller.Record record = null;

    dv.Execute(record);

    record = dv.Fetch();

    strVersion = record.get_StringData(1).ToString();

    dv.Close();
    //db.Commit();
    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(dv);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(db);
}
catch
{
    //Failed
    strVersion = "";
}

它工作得很好,只是当代码运行完毕时,它保存了一个内部MSI文件句柄,所以当我试图移动或重命名MSI文件时,我会得到该文件仍在使用的错误。这种情况一直持续到我实际从调用上述方法的ASPX页面导航。

我的问题是,我显然没有关闭上面代码中的某些句柄或对象。但那会是什么呢?

PS。我正在VS2010的开发环境中测试它。

编辑:按照阿德里亚诺的建议编辑代码。谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-03-26 07:28:29

COM对象还没有被释放(当它超出作用域时应该是自动释放的,但是在.NET中这并不是很好的工作)。因为它没有实现IDisposable接口,所以不能调用它的Dispose()方法,也不能在using语句中使用它。您必须显式地调用Marshal.FinalReleaseComObject。例如:

代码语言:javascript
运行
复制
try
{
    // Your stuffs
}
finally
{
    dv.Close();
    Marshal.FinalReleaseComObject(dv);
    Marshal.FinalReleaseComObject(db);
}

此外,请注意,您实际上不需要调用Commit()方法,因为您没有做任何更改,只是进行了一个查询。

票数 9
EN

Stack Overflow用户

发布于 2012-03-26 11:01:04

FWIW,您应该使用(WiX)部署工具基础(DTF)。这是一个来自微软的自由和开放源码软件项目,可以在CodePlex上找到。它具有与COM类非常相似但实现IDisosable的类的MSI互操作库,并在幕后使用P/Invoke而不是COM。如果您愿意,甚至支持Linq到MSI。完整的源代码是可用的。

DTF是.NET世界中MSI互操作的黄金标准。以下是两个例子:

代码语言:javascript
运行
复制
using System;
using System.Linq;
using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Deployment.WindowsInstaller.Linq;

namespace ConsoleApplication3
{
    class Program
    {
        const string DATABASE_PATH = @"C:\FOO..MSI";
        const string SQL_SELECT_PRODUCTVERSION = "SELECT `Value` FROM `Property` WHERE `Property`='ProductVersion'";

        static void Main(string[] args)
        {
            using (Database database = new Database(DATABASE_PATH, DatabaseOpenMode.ReadOnly))
            {
                Console.WriteLine(database.ExecuteScalar(SQL_SELECT_PRODUCTVERSION).ToString());
            }
            using (QDatabase database = new QDatabase(DATABASE_PATH, DatabaseOpenMode.ReadOnly))
            {
                var results = from property in database.Properties where property.Property == "ProductVersion" select property.Value;
                Console.WriteLine(results.AsEnumerable<string>().First());                    
            }
        }
    }
}
票数 3
EN

Stack Overflow用户

发布于 2012-03-26 07:26:53

尝试Dispose对象。

代码语言:javascript
运行
复制
dv.Dispose();
db.Dispose();
票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9868091

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档