如何将WindowsInstaller.Record转换为System.Data.Dataset或数据表(在阅读MSI文件时)在C# [英] How to convert WindowsInstaller.Record to System.Data.Dataset or Data Table (While reading MSI file) in C#

查看:173
本文介绍了如何将WindowsInstaller.Record转换为System.Data.Dataset或数据表(在阅读MSI文件时)在C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要阅读MSI文件(Windows Installer Package)。我已经写了下面的函数,它有两个输入参数:msifileName和Table Name,并返回一个数据表,它是MSI表之一。

I want to read MSI file(Windows Installer Package). I have written a function as below which takes two input parameters : msifileName and Table Name and returns a data table which is one of the MSI table.

public DataTable ReadMsiPropertyTable(string msiFile, string tableName)
    {            
        Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");

        WindowsInstaller.Installer installer = (WindowsInstaller.Installer)Activator.CreateInstance(installerType);

        Database database = installer.OpenDatabase(msiFile, 0);

        string sqlQuery = String.Format("SELECT * FROM {0}",tableName);

        View view = database.OpenView(sqlQuery);

        view.Execute(null);

        Record record = view.Fetch();

        DataTable msiPropertyTable = new DataTable();

        msiPropertyTable.Columns.Add("Column1", typeof(string));
        msiPropertyTable.Columns.Add("Column2", typeof(string));
        msiPropertyTable.Columns.Add("Column3", typeof(string));
        msiPropertyTable.Columns.Add("Column4", typeof(string));

        while (record != null)
        {
            int fieldCount;
            fieldCount = record.FieldCount;

            msiPropertyTable.Rows.Add(record.get_StringData(0), record.get_StringData(1), record.get_StringData(2), record.get_StringData(3));                
            record = view.Fetch();
        }
        return msiPropertyTable;
    }

使用上面的代码片段,记录的行数和列数不知道。所以我只是静静地返回四列。我想返回正在记录的MSI表的所有行和列。

Using above code snippet, the number of rows and columns of Record are not known. SO I am statically returning only four columns. I want to return all the rows and columns of MSI Table which are in record.

所以请让我知道如何将视图或记录的输出转换为数据集,然后绑定到Datatable。或者还有其他方式可以返回所有行和列。提前致谢。

So Please let me know how can I convert output of view or record to Dataset and then bind to Datatable. Or is there any other way to return all the rows and columns. Thanks in advance.

推荐答案

这是类似的逻辑,使用互操作类型,而不是DTF类型。正如你所看到的,这是一个更多的工作。这也是因为COM涉及而不是P / Invoke而变得更加脆弱。另外,如果可以消除创建ADO.NET DataTable的要求,DTF支持LINQ查询和数据绑定。换句话说,我只写这个乐趣。我将永远不会在实际代码中使用此方法。

Here's similar logic using the interop types rather then the DTF types. As you can see it's a lot more work. It's also a lot more fragile since COM is involved instead of P/Invoke. Also, if you can eliminate the requirement to create an ADO.NET DataTable, DTF supports LINQ queries and databinding. In other words, I wrote this for fun only. I would NEVER use this method in real code.

 public static DataTable ReadMsiPropertyTable(string msiFile, string tableName)
        {
            DataTable dataTable = new DataTable(tableName);
            Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
            Installer installer = (WindowsInstaller.Installer)Activator.CreateInstance(installerType);
            Database database = installer.OpenDatabase(msiFile, MsiOpenDatabaseMode.msiOpenDatabaseModeReadOnly);

            string sqlQuery = String.Format("SELECT * FROM {0}", tableName);
            View view = database.OpenView(sqlQuery);
            view.Execute(null);

            Record names = view.ColumnInfo[MsiColumnInfo.msiColumnInfoNames];
            Record types = view.ColumnInfo[MsiColumnInfo.msiColumnInfoTypes];
            Record row = view.Fetch();

            for (int index = 1; index < names.FieldCount+1; index++)
            {
                string columnName = names.get_StringData(index);
                string columnSpec = types.get_StringData(index);

                switch (columnSpec.Substring(0, 1).ToLower())
                {
                    case "s":
                        dataTable.Columns.Add(columnName, typeof(String));
                        break;

                    case "l":
                        dataTable.Columns.Add(columnName, typeof(String));
                        break;

                    case "i":
                        dataTable.Columns.Add(columnName, typeof(Int32));
                        break;

                    case "v":
                        dataTable.Columns.Add(columnName, typeof (Stream));
                        break;
                }
            }

            while (row != null)
            {
                DataRow dataRow = dataTable.NewRow();
                for (int index = 0; index < dataTable.Columns.Count; index++)
                {

                    if(dataTable.Columns[index].DataType == typeof(String))
                    {
                        dataRow[index] = row.StringData[index + 1];
                    }
                    else if(dataTable.Columns[index].DataType == typeof(Int32))
                    {
                        dataRow[index] = row.IntegerData[index + 1];
                    }
                    else if(dataTable.Columns[index].DataType == typeof(Stream))
                    {
                       // Insanity has it's limits. Not implemented.
                    }
                }
                dataTable.Rows.Add(dataRow);
                row = view.Fetch();
            }
            return dataTable;
        }

这篇关于如何将WindowsInstaller.Record转换为System.Data.Dataset或数据表(在阅读MSI文件时)在C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆