.msi

2013-05-27 4 views
1

mst + .msi 테이블 정보와 함께 .mst (변환) 테이블을 읽는 방법. .msi

나는 MSI 테이블 나는이 기능을 .MST 읽을 수 없습니다입니다 그러나
// 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; 
    } 

를 읽을 다음 함수를 만들었습니다. 나는 당신이 그것을 위해 msi transform을 사용할 필요가 있다고 읽었지 만, 나는 msi 또는 mst의 내용을 바꾸고 싶지 않습니다. 단지 모든 테이블을 읽을 필요가 있습니다. 저를 올바른 방향으로 가르쳐주십시오. 미리 감사드립니다 :)

+1

은 BTW, 당신은 당신의 클래스의 일부를 폐기하지 않습니다. Checkout : 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, 그럼 temp를 만들지 않고 단 몇 mst + msi 테이블을 볼 방법이 없습니까? – Apocalyp5e

+1

메모리에서 수행 할 수 있습니다. 나는 결코 그것을 시도하지 않았기 때문에 나는 확실히 말할 수 없다. MSDN (MsiDatabaseApplyTransform) 문서는 제한 사항이있을 수 있음을 나타냅니다. 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");