2013-05-27 80 views
1

mst + .msi表信息。如何讀取.mst(變換)表.msi

我創建了下面的函數讀取MSI表

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

但是我卻無法使用該功能來讀取的.mst。我讀過你需要使用msi轉換,但我不想更改msi或mst的內容,我只需要讀取所有表格。請指向正確的方向。在此先感謝:)

+1

順便說一句,你是不是處置您的某些類。結帳:http://stackoverflow.com/questions/14020285/how-to-convert-windowsinstaller-record-to-system-data-dataset-or-data-table-whi –

+0

感謝您指出:)將處置他們明確。 (我知道它很好的做法來處理你使用的所有東西,但是不會被.net GC自動處理?只是好奇,但再次感謝) – Apocalyp5e

+0

最終。但是這些類具有非託管(p/invoke)句柄,需要以更及時的方式處理。 –

回答

3

MST根據定義是一種變換。它只包含基本MSI的增量。

數據庫類有一個名爲ViewTransform的方法。如果MST與MSI兼容,它將成功,並且更改顯示在_TransformView表中。

或者,如果您不想查看發生了什麼變化,但希望看到最終狀態,則可以將MSI複製到臨時MSI,然後使用ApplyTransform方法應用轉換並提交它。現在你可以使用你已有的代碼來查詢它。

+0

非常感謝@christopher,那麼是不是沒有辦法查看mst + msi表而不創建temp? – Apocalyp5e

+1

您可能可以在內存中執行此操作。我不能肯定地說,因爲我從來沒有嘗試過。 MsiDatabaseApplyTransform(MSDN)doco建議可能有限制。請參閱http://msdn.microsoft.com/en-us/library/aa370074.aspx –

+0

創建一個臨時Msi,與mst合併它並閱讀:)感謝很多 – Apocalyp5e

0

工作對我來說:

msiDatabase = new Database(@"Foo.msi", DatabaseOpenMode.ReadOnly); 
msiDatabase.ApplyTransform(@"Foo.mst");