Checking ProductVersion of an MSI programmatically

后端 未结 2 1326
逝去的感伤
逝去的感伤 2020-12-10 09:00

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, whi

相关标签:
2条回答
  • 2020-12-10 09:32

    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.

    0 讨论(0)
  • 2020-12-10 09:38

    Anyone needing to do .NET interop with MSI should be using Microsoft.Deployment.WindowsInstaller found in WiX's DTF SDK. It's a very clean library and way better then trying to write your own.

    0 讨论(0)
提交回复
热议问题