Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read MSI properties in c#

I want to read properties of MSI in C# in desktop application.I am using following code:

    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;            
    }

But I am getting error as System.Runtime.InteropServices.COMException was unhandled.

the sqlncli.msi file is physically placed at c:\DataP location. While debugging I found that database does not contain the data after installer.OpenDatabase() statement.

Please suggest me how to resolve this issue and get MSI properties in c#.

Thanks in advance.

like image 978
Devashri B. Avatar asked Dec 19 '12 10:12

Devashri B.


People also ask

How do I view MSI properties?

msi. Interactively, open the . msi then go to Table view and select or type "Property".

How do I read an MSI file?

View MSI files by launching the app, or by right-clicking an MSI file in File Explorer and choosing "Open in MSI Viewer".


4 Answers

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();
        }
    }
}
like image 107
Christopher Painter Avatar answered Nov 08 '22 16:11

Christopher Painter


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.

like image 22
Devashri B. Avatar answered Nov 08 '22 16:11

Devashri B.


The SQL string is incorrect. It should be:

SELECT `Value` FROM `Property` WHERE `Property`.`Property` = ’{0}’
like image 22
Ciprian Avatar answered Nov 08 '22 17:11

Ciprian


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!

like image 1
Rahul Ramesh Avatar answered Nov 08 '22 15:11

Rahul Ramesh