Question

mst + .msi table information.

I created following function to read msi Tables

// This method returns all rows and columns of a Table specified by Name
    public DataTable ReadMsiTableByName(string msiFile, string tableName)
    {
        DataTable msiTable = new DataTable(tableName);
        Database database = null;
        View view = null;

        try
        {
            using (database = new Database(msiFile, DatabaseOpenMode.ReadOnly))
            {
                string sqlQuery = String.Format("SELECT * FROM {0}", tableName);

                view = database.OpenView(sqlQuery);
                view.Execute(null);
                Record record = view.Fetch();

                ColumnCollection columnCollection = view.Columns;

                for (int i = 0; i < columnCollection.Count; i++)
                {
                    string columnName = columnCollection[i].Name.ToString();
                    System.Type columnType = columnCollection[i].Type;

                    msiTable.Columns.Add(columnName, columnType.UnderlyingSystemType);
                }

                while (record != null)
                {
                    DataRow row = msiTable.NewRow();
                    for (int i = 0; i < columnCollection.Count; i++)
                    {
                        string type = columnCollection[i].Type.ToString();

                        if (type == "System.String")
                        {
                            row[columnCollection[i].Name.ToString()] = record.GetString(columnCollection[i].Name.ToString());
                        }
                        else if (type == "System.Int16")
                        {
                            row[columnCollection[i].Name.ToString()] = record.GetInteger(columnCollection[i].Name.ToString());
                        }
                        else if (type == "System.Int32")
                        {
                            row[columnCollection[i].Name.ToString()] = record.GetInteger(columnCollection[i].Name.ToString());
                        }
                        else if (type == "System.IO.Stream")
                        {
                            System.IO.Stream stream;
                            stream = record.GetStream(columnCollection[i].Name.ToString());
                            row[columnCollection[i].Name.ToString()] = stream;
                        }
                    }
                    msiTable.Rows.Add(row);
                    record = view.Fetch();
                }
            }
        }

        catch (Exception ex)
        {
            CommonFn.CreateLog(ex.ToString());
        }

        finally
        {
            if (database != null)
                database.Close();

            if (view != null)
                view.Close();
        }
        return msiTable;
    }

However I am unable to read .mst with this function. I read that you need to use msi transform for it, But I don't want to change the content of msi or mst, I just need to read all the tables. Please point me in right direction. Thanks in Advance :)

Was it helpful?

Solution

An MST is by definition a transform. It only contains the deltas of a base MSI.

The database class has a method called ViewTransform. If the MST is compatible with the MSI it'll succeed and the changes appear in the _TransformView table.

Alternatively if you don't want to see whats changed but you want to see the final state, you could copy the MSI to a temporary MSI and use the ApplyTransform method to apply the transform and then commit it. Now you could query it using the code you already have.

OTHER TIPS

Works for me:

msiDatabase = new Database(@"Foo.msi", DatabaseOpenMode.ReadOnly);
msiDatabase.ApplyTransform(@"Foo.mst");
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top