本文介绍了以编程方式检查MSI的ProductVersion的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用msi.dll通过pinvoke快速获取msi数据库的ProductVersion?我发现的大多数情况都涉及利用WindowsInstaller COM包装器,虽然这项工作已完成,但我想通过使用msi.dll的pinvoke获得相同的结果.

How do I quickly obtain the ProductVersion of an msi database through pinvoke using the msi.dll? Mostly what I found involved utilizing the WindowsInstaller COM wrapper, while this got the job done, I want to achieve the same results through pinvoke using the msi.dll.

推荐答案

这就是我要提出的.

C#Windows Installer COM库:

C# Windows Installer COM library:

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

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

            // Open the MSI database in the input file
            Database database = installer.OpenDatabase(od.FileName, MsiOpenDatabaseMode.msiOpenDatabaseModeReadOnly);

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

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

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

            // Get the version from the data
            string version = record.get_StringData(2);

C#Pinvoke:

C# Pinvoke:

    [DllImport("msi.dll", SetLastError = true)]
    static extern uint MsiOpenDatabase(string szDatabasePath, IntPtr phPersist, out IntPtr phDatabase);

    [DllImport("msi.dll", CharSet = CharSet.Unicode)]
    static extern int MsiDatabaseOpenViewW(IntPtr hDatabase, [MarshalAs(UnmanagedType.LPWStr)] string szQuery, out IntPtr phView);

    [DllImport("msi.dll", CharSet = CharSet.Unicode)]
    static extern int MsiViewExecute(IntPtr hView, IntPtr hRecord);

    [DllImport("msi.dll", CharSet = CharSet.Unicode)]
    static extern uint MsiViewFetch(IntPtr hView, out IntPtr hRecord);

    [DllImport("msi.dll", CharSet = CharSet.Unicode)]
    static extern int MsiRecordGetString(IntPtr hRecord, int iField,
       [Out] StringBuilder szValueBuf, ref int pcchValueBuf);

    [DllImport("msi.dll", ExactSpelling = true)]
    static extern IntPtr MsiCreateRecord(uint cParams);

    [DllImport("msi.dll", ExactSpelling = true)]
    static extern uint MsiCloseHandle(IntPtr hAny);

    public string GetVersionInfo(string fileName)
    {
        string sqlStatement = "SELECT * FROM Property WHERE Property = 'ProductVersion'";
        IntPtr phDatabase = IntPtr.Zero;
        IntPtr phView = IntPtr.Zero;
        IntPtr hRecord = IntPtr.Zero;

        StringBuilder szValueBuf = new StringBuilder();
        int pcchValueBuf = 255;

        // Open the MSI database in the input file
        uint val = MsiOpenDatabase(fileName, IntPtr.Zero, out phDatabase);

        hRecord = MsiCreateRecord(1);

        // Open a view on the Property table for the version property
        int viewVal = MsiDatabaseOpenViewW(phDatabase, sqlStatement, out phView);

        // Execute the view query
        int exeVal = MsiViewExecute(phView, hRecord);

        // Get the record from the view
        uint fetchVal = MsiViewFetch(phView, out hRecord);

        // Get the version from the data
        int retVal = MsiRecordGetString(hRecord, 2, szValueBuf, ref pcchValueBuf);

        uRetCode = MsiCloseHandle(phDatabase);
        uRetCode = MsiCloseHandle(phView);
        uRetCode = MsiCloseHandle(hRecord);

        return szValueBuf.ToString();
    }

通过更改SQL语句,可以很容易地将其推断为从msi数据库获取任何属性或字段.我希望这可以帮助某人.

This could easily be extrapolated into obtaining any property or field from the msi database by changing the SQL statement. I hope this helps someone out.

这篇关于以编程方式检查MSI的ProductVersion的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 14:27