public static uint MsiGetProductProperty(MsiHandle hProduct, string szProperty, out string value)
    {
        StringBuilder sb     = new StringBuilder(1024);
        int           length = sb.Capacity;
        uint          err;

        value = null;
        if (0 == (err = MsiGetProductPropertyW(hProduct, szProperty, sb, ref length)))
        {
            sb.Length = length;
            value     = sb.ToString();
            return(0);
        }
        return(err);
    }
            private static string GetRecordString(MsiHandle record, int field)
            {
                int           length = 255;
                uint          rv     = 0;
                StringBuilder text   = new StringBuilder(length);

                if ((rv = MsiRecordGetString(record.Handle, field, text, ref length)) == 0xea)
                {
                    text.EnsureCapacity(++length);
                    rv = MsiRecordGetString(record.Handle, field, text, ref length);
                }
                if (rv != 0)
                {
                    throw new Win32Exception();
                }
                return(text.ToString());
            }
            private static List <MsiFileInfo> GetFiles(string msiPath)
            {
                List <MsiFileInfo> msiFiles = new List <MsiFileInfo>();

                // Open database
                int dbHandleVal;

                if (MsiOpenDatabase(msiPath, IntPtr.Zero, out dbHandleVal) != 0)
                {
                    throw new Win32Exception();
                }
                using (MsiHandle dbHandle = new MsiHandle(dbHandleVal))
                {
                    // Make sure file table exists
                    string tableName = "File";
                    if (MsiDatabaseIsTablePersistent(dbHandle.Handle, tableName) == 1)
                    {
                        // Opoen the view of the list of files
                        string query = "SELECT * FROM `" + tableName + "`";
                        int    viewHandleVal;
                        if (MsiDatabaseOpenView(dbHandle.Handle, query, out viewHandleVal) != 0)
                        {
                            throw new Win32Exception();
                        }
                        using (MsiHandle viewHandle = new MsiHandle(viewHandleVal))
                        {
                            if (MsiViewExecute(viewHandle.Handle, 0) != 0)
                            {
                                throw new Win32Exception();
                            }

                            // Get a list of the columns in order to find the name field
                            Dictionary <string, int> fieldToIndexMapping = new Dictionary <string, int>();
                            int columnNamesRecordVal;
                            if (MsiViewGetColumnInfo(viewHandle.Handle, 0, out columnNamesRecordVal) != 0)
                            {
                                throw new Win32Exception();
                            }
                            using (MsiHandle columnNamesRecord = new MsiHandle(columnNamesRecordVal))
                            {
                                int fieldCount = MsiRecordGetFieldCount(columnNamesRecord.Handle);
                                for (int i = 0; i < fieldCount; i++)
                                {
                                    fieldToIndexMapping[GetRecordString(columnNamesRecord, i)] = i;
                                }
                            }
                            if (fieldToIndexMapping.ContainsKey("FileName"))
                            {
                                // Get the files list
                                uint rv;
                                int  recordVal;
                                while ((rv = MsiViewFetch(viewHandle.Handle, out recordVal)) == 0)
                                {
                                    using (MsiHandle record = new MsiHandle(recordVal))
                                    {
                                        string[] fileNameParts = GetRecordString(record, fieldToIndexMapping["FileName"]).Split(
                                            new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                                        string fileName = fileNameParts.Length > 1 ? fileNameParts[1] : fileNameParts[0];
                                        string size     = GetRecordString(record, fieldToIndexMapping["FileSize"]);
                                        string version  = GetRecordString(record, fieldToIndexMapping["Version"]);
                                        msiFiles.Add(new MsiFileInfo(fileName, version, size));
                                    }
                                }
                                if (rv != 0x103)
                                {
                                    throw new Win32Exception();
                                }
                            }
                        }
                    }
                }
                return(msiFiles);
            }
 static extern uint MsiGetProductPropertyW(MsiHandle hProduct, string szProperty, StringBuilder value, ref int length);
 public extern static uint MsiOpenPackageW(string szPackagePath, out MsiHandle product);