我有一个从 C# Visual Studio 2010 构建的 MSI 文件。版本是通过
Version
属性设置的。我想知道是否有一种方法无需安装文件即可确定版本。目前,当右键单击并查看属性时,它不会显示。
以下代码可能会有所帮助。但请记住,您应该首先添加对 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” );
是的 - 我认为您需要检查 MSI 数据库,但这需要一些 API 调用或包装实用程序。
Microsoft 的 ORCA 应用程序应该可以让您执行此操作(尽管我自己从未尝试过)。
您可以使用 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
。
根据 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 引用或额外的命名空间,因为我们在这里使用后期绑定(参见动态)。
如果您想快速提取版本,有一个由 Microsoft 员工编写的 PowerShell 模块可以为您执行此操作,称为 PSMSI
这是一个两步过程:
install-package msi -provider PowerShellGet
get-msiproperty ProductVersion -Path '.\Installer.msi'