我想在桌面应用程序中读取C#中的MSI属性。我使用以下代码:
public static string GetMSIProperty( string msiFile, string msiProperty)
{
string retVal= string.Empty ;
Type classType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Object installerObj = Activator.CreateInstance(classType);
WindowsInstaller.Installer installer = installerObj as WindowsInstaller.Installer;
Database database = installer.OpenDatabase("C:\\DataP\\sqlncli.msi",0 );
string sql = String.Format("SELECT Value FROM Property WHERE Property=’{0}’", msiProperty);
View view = database.OpenView(sql);
Record record = view.Fetch();
if (record != null)
{
retVal = record.get_StringData(1);
}
else
retVal = "Property Not Found";
return retVal;
}
但是由于System.Runtime.InteropServices.COMException未处理,我收到错误。
sqlncli.msi文件实际放置在c:\ DataP位置。在调试时我发现数据库不包含installer.OpenDatabase()语句之后的数据。
请建议我如何解决此问题并在c#中获取MSI属性。
提前致谢。
答案 0 :(得分:18)
Windows Installer XML的部署工具基础(WiX DTF)是Microsoft的一个开源项目,其中包括Microsoft.Deployment.WindowsInstaller MSI互操作库。使用它来执行这些类型的查询更容易,更可靠。它甚至还有一个LINQ to MSI提供程序,允许您将MSI表视为实体并针对它们编写查询。
using System;
using System.Linq;
using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Deployment.WindowsInstaller.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
using(var database = new QDatabase(@"C:\tfs\iswix.msi", DatabaseOpenMode.ReadOnly))
{
var properties = from p in database.Properties
select p;
foreach (var property in properties)
{
Console.WriteLine("{0} = {1}", property.Property, property.Value);
}
}
using (var database = new Database(@"C:\tfs\iswix.msi", DatabaseOpenMode.ReadOnly))
{
using(var view = database.OpenView(database.Tables["Property"].SqlSelectString))
{
view.Execute();
foreach (var rec in view) using (rec)
{
Console.WriteLine("{0} = {1}", rec.GetString("Property"), rec.GetString("Value"));
}
}
}
Console.Read();
}
}
}
答案 1 :(得分:1)
SQL字符串不正确。它应该是:
SELECT `Value` FROM `Property` WHERE `Property`.`Property` = ’{0}’
答案 2 :(得分:1)
我是按照以下方式做到的:
String inputFile = @"C:\\Rohan\\sqlncli.msi";
// Get the type of the Windows Installer object
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
// Create the Windows Installer object
WindowsInstaller.Installer installer = (WindowsInstaller.Installer)Activator.CreateInstance(installerType);
// Open the MSI database in the input file
Database database = installer.OpenDatabase(inputFile, 0);
// Open a view on the Property table for the version property
View view = database.OpenView("SELECT * FROM _Tables");
// Execute the view query
view.Execute(null);
// Get the record from the view
Record record = view.Fetch();
while (record != null)
{
Console.WriteLine(record.get_StringData(0) + '=' + record.get_StringData(1) + '=' + record.get_StringData(2) + '=' + record.get_StringData(3));
record = view.Fetch();
}
它为我工作。
答案 3 :(得分:1)
我试图重新使用这段代码,而我必须做的唯一更改才能让Devashri发布的代码才能正常运行:
string sql = String.Format("SELECT `Value` FROM `Property` WHERE `Property`='{0}'", msiProperty);
留意单引号!
答案 4 :(得分:-1)
从04/2020开始将是
Type installerType { get; set; }
WindowsInstaller.Installer installerObj { get; set; }
...
installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
installerObj = (WindowsInstaller.Installer)Activator.CreateInstance(installerType);
var installer = installerObj as WindowsInstaller.Installer;
...
private void lnkSelectMsi_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
WindowsInstaller.Database msiDatabase = installerObj.OpenDatabase(txtMsiPath.Text, 0);
readMsiTableColumn(msiDatabase, cmbTable.Text, cmbColumn.Text);
}
private void readMsiTableColumn(WindowsInstaller.Database msiDatabase, string table)
{
WindowsInstaller.View msiView = null;
Record record = null;
string s = string.Empty;
try
{
msiView = msiDatabase.OpenView($"Select * from _Columns");
msiView.Execute();
record = msiView.Fetch();
int k = 0;
while (record != null)
{
if (record.StringData[1].Equals(table, StringComparison.OrdinalIgnoreCase))
{
k++;
s += $"{record.StringData[3],-50} ";
}
record = msiView.Fetch();
}
s += nl;
s += "".PadRight(50 * k, '-') + nl;
msiView.Close();
msiView = msiDatabase.OpenView($"Select * from {table}");
msiView.Execute();
record = msiView.Fetch();
while (record != null)
{
string recordValue = string.Empty;
for (int i = 1; i < record.FieldCount + 1; i++)
{
try { recordValue += $"{record.StringData[i],-50} "; }
catch (Exception ex) { recordValue += $"{i}. err {ex.Message}; "; }
}
s += recordValue + nl;
record = msiView.Fetch();
}
msiView.Close();
txtRes.Text = s;
}
catch (Exception ex) { txtRes.Text = ex.Message; }
}