2012-12-19 43 views
5

我想读在桌面application.I在C#MSI的性质正在使用下面的代码:在C#中如何阅读MSI属性

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

但我得到错误的System.Runtime.InteropServices.COMException是未处理。

sqlncli.msi文件实际位于c:\ DataP位置。在调试时,我发现数据库不包含installer.OpenDatabase()语句后的数据。

请建议我如何解决这个问题,并在c#中获得MSI属性。

在此先感谢。

+0

在哪条线上抛出异常? –

+0

您的查询在属性名称周围有一些奇怪的引号字符:'WHERE Property ='{0}''应该是WHERE Property ='{0}''。 –

+0

View view = database.OpenView(sql);抛出异常 –

回答

1

SQL字符串不正确。它应该是:

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

我这样做是在下列方式:

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(); 
} 

而且它为我工作。

+1

Downvoted for:1)使用@和转义反斜杠(冗余)2)当基于P/Invoke的更干净的互操作库存在时,使用COM Interop 3)未能关闭任何非托管句柄。 –

+1

@ChristopherPainter,随时编辑答案而不是downvote,因为我认为这为社区增加了更多价值。 –

+0

那是3年前。重写使用互操作库而不是COM Interop的答案稍微有点“编辑”。 –

12

Windows安装程序XML的部署工具基础(WiX DTF)是一个来自Microsoft的开放源代码项目,其中包含Microsoft.Deployment.WindowsInstaller MSI互操作库。使用它来执行这些查询要容易得多并且更加可靠。它甚至还有一个LINQ to MSI提供程序,它允许您将MSI表视为实体并针对它们编写查询。

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

我想重新使用此代码,我不得不做出度日Devashri发布工作的代码唯一的变化是这一行:

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

当心单报价!

+0

这就是为什么SqlSelectString属性和Linq 2 MSI实体如此有用。隐藏SQL并专注于编码。 –