Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
164 views
in Technique[技术] by (71.8m points)

c# - Checking ProductVersion of an MSI programmatically

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here's what I've come up with.

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:

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

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...