无需安装即可确定 MSI 的版本

问题描述 投票:0回答:5

我有一个从 C# Visual Studio 2010 构建的 MSI 文件。版本是通过

Version
属性设置的。我想知道是否有一种方法无需安装文件即可确定版本。目前,当右键单击并查看属性时,它不会显示。

c# windows-installer
5个回答
6
投票

以下代码可能会有所帮助。但请记住,您应该首先添加对 Microsoft Windows Installer 对象库的 COM 引用,并将 WindowsInstaller 命名空间添加到您的代码中。以下功能可能正是您所需要的。

public static string GetMsiInfo( string msiPath, string Info)
{
   string retVal = string.Empty;

   Type classType = Type.GetTypeFromProgID( “WindowsInstaller.Installer” );
   Object installerObj = Activator.CreateInstance( classType );
   Installer installer = installerObj as Installer;

   // Open msi file
   Database db = installer.OpenDatabase( msiPath, 0 );

   // Fetch the property
   string sql = String.Format(“SELECT Value FROM Property WHERE Property=’{0}’”, Info);
   View view = db.OpenView( sql );
   view.Execute( null );

   // Read in the record
   Record rec = view.Fetch();
   if ( rec != null )
      retVal = rec.get_StringData( 1 );

   return retVal;
}

如果您需要版本,请传入您想要的MSI文件的名称,例如

string version = GetMsiInfo( "d:\product.msi", “ProductVersion” );

3
投票

是的 - 我认为您需要检查 MSI 数据库,但这需要一些 API 调用或包装实用程序。

Microsoft 的 ORCA 应用程序应该可以让您执行此操作(尽管我自己从未尝试过)。


0
投票

您可以使用 wixtoolset SDK 中的

Microsoft.Deployment.WindowsInstaller
库,而不是使用 COM 库。引用后,您可以非常类似地获取版本信息。

private string GetMsiInfo(string msiPath)
{
    using (var database = new Microsoft.Deployment.WindowsInstaller.Database(msiPath))
    {
        var sql = "SELECT Value FROM Property WHERE Property ='ProductVersion'";
        using (var view = database.OpenView(sql))
        {
            view.Execute();

            using (var record = view.Fetch())
            {
                var version = record?.GetString(1);
                return version;
            }
        }
    }
}

我还没有找到通过 nuget 安装程序获取正确程序集的方法。但是,在我安装了 wixtoolset https://wixtoolset.org/releases/ 后,我可以直接在我的项目中添加引用,

assemblies -> extensions -> Microsoft.Deployment.WindowsInstaller


0
投票

根据 Gupta 的回答,我添加了 COM 发布调用。如果您想重新创建或替换在进一步的工作流程中访问的文件,它可能仍在使用中,并且如果 GC 尚未释放对象,您将收到异常,因此让我们手动执行此操作。

public static string GetMsiInfo(string msiPath, string info)
{
  string retVal = string.Empty;

  Type classType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
  dynamic installer = Activator.CreateInstance(classType);
  try
  {

    // Open msi file
    var db = installer.OpenDatabase(msiPath, 0);
    try
    {
      // Fetch the property
      string sql = $"SELECT Value FROM Property WHERE Property ='{info}'";
      var view = db.OpenView(sql);
      try
      {
        view.Execute(null);

        // Read in the record
        var rec = view.Fetch();
        if (rec != null)
          retVal = rec.StringData(1);

        return retVal;
      }
      finally
      {
        view.Close();
        Marshal.ReleaseComObject(view);
      }
    }
    finally
    {
      //db.Commit();
      Marshal.ReleaseComObject(db);
    }
  }
  finally
  {
    Marshal.ReleaseComObject(installer);
  }
}

我认为使用这段代码,不需要像 Gupta 提到的那样添加 COM 引用或额外的命名空间,因为我们在这里使用后期绑定(参见动态)。


0
投票

如果您想快速提取版本,有一个由 Microsoft 员工编写的 PowerShell 模块可以为您执行此操作,称为 PSMSI

这是一个两步过程:

  1. 安装模块:
    install-package msi -provider PowerShellGet
  2. 获取版本:
    get-msiproperty ProductVersion -Path '.\Installer.msi'
© www.soinside.com 2019 - 2024. All rights reserved.