2012-12-19 11 views
5

chcę czytać właściwości MSI w języku C# w application.I stacjonarnych używam następujący kod:Jak odczytać właściwości MSI w C#

public static string GetMSIProperty(string msiFile, string msiProperty) 
    { 
     string retVal= string.Empty ; 

     Type classType = Type.GetTypeFromProgID("WindowsInstaller.Installer"); 
     Object installerObj = Activator.CreateInstance(classType); 
     WindowsInstaller.Installer installer = installerObj as WindowsInstaller.Installer; 

     Database database = installer.OpenDatabase("C:\\DataP\\sqlncli.msi",0); 

     string sql = String.Format("SELECT Value FROM Property WHERE Property=’{0}’", msiProperty); 

     View view = database.OpenView(sql); 

     Record record = view.Fetch(); 

     if (record != null) 
     { 
      retVal = record.get_StringData(1); 
     } 
     else 
      retVal = "Property Not Found"; 

     return retVal;    
    } 

ale otrzymuję błąd jak System.Runtime.InteropServices.COMException było nieobsługiwane.

plik sqlncli.msi jest fizycznie umieszczany w lokalizacji c: \ DataP. Podczas debugowania znalazłem, że baza danych nie zawiera danych po instrukcji install.OpenDatabase().

Proszę zasugerować mi, jak rozwiązać ten problem i uzyskać właściwości MSI w języku C#.

Z góry dziękuję.

+0

W którym wierszu jest wyświetlany wyjątek? –

+0

Twoje zapytanie zawiera dziwne cudzysłowy wokół nazwy właściwości: 'WHERE Właściwość = '{0}'' powinno być 'WHERE Właściwość = '{0}''. –

+0

wyjątek jest generowany w widoku widoku = database.OpenView (sql); –

Odpowiedz

1

Łańcuch SQL jest niepoprawny. Powinno być:

SELECT `Value` FROM `Property` WHERE `Property`.`Property` = ’{0}’ 
1

zrobiłem to w następujący sposób:

String inputFile = @"C:\\Rohan\\sqlncli.msi"; 

// Get the type of the Windows Installer object 
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer"); 

// Create the Windows Installer object 
WindowsInstaller.Installer installer = (WindowsInstaller.Installer)Activator.CreateInstance(installerType); 

// Open the MSI database in the input file 
Database database = installer.OpenDatabase(inputFile, 0); 

// Open a view on the Property table for the version property 
View view = database.OpenView("SELECT * FROM _Tables"); 

// Execute the view query 
view.Execute(null); 

// Get the record from the view 
Record record = view.Fetch(); 

while (record != null) 
{ 
    Console.WriteLine(record.get_StringData(0) + '=' + record.get_StringData(1) + '=' + record.get_StringData(2) + '=' + record.get_StringData(3)); 
    record = view.Fetch(); 
} 

I jego pracy dla mnie.

+1

Rewizja: 1) Używanie @ i ucieczkowych odwrotnych ukośników (redundantnych) 2) Używanie COM Interop, gdy istnieje znacznie czystsza biblioteka interopów, która bazuje na P/Invoke 3). Nie można zamknąć żadnego z niezarządzanych uchwytów. –

+1

@ChristopherPainter, możesz edytować odpowiedź zamiast głosować w dół, ponieważ myślę, że to dodaje więcej wartości społeczności. –

+0

To było 3 lata temu. Przepisanie odpowiedzi na wykorzystanie biblioteki interopowej zamiast COM Interop to więcej niż mała "edycja". –

12

Fundacja narzędzi instalacyjnych systemu Windows Instalatora XML (WiX DTF) to projekt Open Source firmy Microsoft, który zawiera bibliotekę interopii MSI Microsoft.Deployment.WindowsInstaller. O wiele łatwiejsze i bardziej niezawodne jest używanie tego do wykonywania tego rodzaju zapytań. Ma nawet dostawcę LINQ do MSI, który pozwala traktować tabele MSI jako jednostki i pisać przeciwko nim zapytania.

using System; 
using System.Linq; 
using Microsoft.Deployment.WindowsInstaller; 
using Microsoft.Deployment.WindowsInstaller.Linq; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      using(var database = new QDatabase(@"C:\tfs\iswix.msi", DatabaseOpenMode.ReadOnly)) 
      { 
       var properties = from p in database.Properties 
           select p; 

       foreach (var property in properties) 
       { 
        Console.WriteLine("{0} = {1}", property.Property, property.Value); 
       } 
      } 

      using (var database = new Database(@"C:\tfs\iswix.msi", DatabaseOpenMode.ReadOnly)) 
      { 
       using(var view = database.OpenView(database.Tables["Property"].SqlSelectString)) 
       { 
        view.Execute(); 
        foreach (var rec in view) using (rec) 
        { 
         Console.WriteLine("{0} = {1}", rec.GetString("Property"), rec.GetString("Value")); 
        } 
       } 
      } 

      Console.Read(); 
     } 
    } 
} 
1

starałem się ponownie użyć tego kodu, a jedyną zmianą musiałem podjąć w celu uzyskania kodu zamieszczonych przez Devashri do pracy jest to linia:

string sql = String.Format("SELECT `Value` FROM `Property` WHERE `Property`='{0}'", msiProperty); 

Uważaj na pojedynczy cytaty!

+0

Z tego powodu właściwość SqlSelectString i jednostki MSI Linq 2 są tak pomocne. Ukryj SQL i skoncentruj się na kodowaniu. –

Powiązane problemy