I want to read properties of MSI in C# in desktop application.I am using following code:
public static string GetMSIProperty( string msiFile, string msiP
I was trying to re-use this code, and the only change I had to make to get the code posted by Devashri to work is this line:
string sql = String.Format("SELECT `Value` FROM `Property` WHERE `Property`='{0}'", msiProperty);
Watch out for the single quotes!
The SQL string is incorrect. It should be:
SELECT `Value` FROM `Property` WHERE `Property`.`Property` = ’{0}’
I did it in following way:
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();
}
And its working for me.
as of 04/2020 it would be
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; }
}
Windows Installer XML's Deployment Tools Foundation (WiX DTF) is an Open Source project from Microsoft which includes the Microsoft.Deployment.WindowsInstaller MSI interop library. It's far easier and more reliable to use this to do these sorts of queries. It even has a LINQ to MSI provider that allows you to treat MSI tables as entities and write queries against them.
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();
}
}
}