Search code examples
windows-installer

How to get all properties in msi file


How to know the property list contained an MSI file?

If we know the property name, we can get property value for a specific property. we can use the following codes:

WCHAR wzBuf[MAX_PATH+1]=L"";
DWORD dw=_countof(wzBuf);
    fGoodPath = ( ERROR_SUCCESS == ::MsiGetPropertyW(hInstall, L"INSTALLLOCATION", wzBuf, &dw) );

Just wondering how can we know all the property names defined in MSI/MSP files?


Solution

  • Github.com: VBScript sample from github.com: PullMSPOfficeUpdates.vbs which is recommended to check. Iterates patches. A "canned" github search.

    Basic Sample: Here is a trimmed down sample which gets the Patch Code from an MSP. Sorry for no C++, but I am too rusty and not enough time (maybe add your own answer and set that accepted as C++ - hint: just edit your current one, it is more of a comment as it stands - prefer to edit your original answer or comment it - just the approach generally used here):

    Const MSIOPENDATABASEMODE_PATCHFILE = 32
    Const MSIPID_REVNUMBER = 7
    
    Set installer = CreateObject("WindowsInstaller.Installer")
    Set msp = installer.OpenDatabase("C:\MyPath.msp", MSIOPENDATABASEMODE_PATCHFILE)
    Set summaryinfo = msp.SummaryInformation
    
    MsgBox summaryinfo.Property(MSIPID_REVNUMBER)
    

    UPDATE: I am not a C++ developer, but with some help from Installshield's Michael Urman, I think this C++ sample should work with Visual Studio 2017 at least. Please don't be too picky about the actual C++ constructs, use github.com to find more samples (canned search sample - just for others and myself in the future, I know you don't need it):

    #include "pch.h"
    
    #define WIN32_LEAN_AND_MEAN
    
    #include <atlstr.h> // CString support from ATL
    #include <Msiquery.h>
    
    #pragma comment(lib, "msi.lib") // to allow linking
    
    int main()
    {
        CString lpszFilename = L"C:\\YourPatchFile.msp";
    
        PMSIHANDLE hSum;
        DWORD dwErr = MsiGetSummaryInformation(0, lpszFilename, 0, &hSum);
        if (ERROR_SUCCESS == dwErr)
        {
            UINT uiProperty = 7;
            UINT uiDataType = 0;
            INT iValue = 0;
            FILETIME ftValue = { 0 };
            CString sValue;
            DWORD cchValue = MAX_PATH;
    
            dwErr = MsiSummaryInfoGetProperty(hSum, uiProperty, &uiDataType, &iValue, &ftValue, (LPWSTR)sValue.GetString(), &cchValue);
    
            MessageBox(NULL, sValue, L"Patch Code:", MB_OK);
        }
    
       MsiCloseHandle(hSum);
       return 0;
    }
    

    Testing: 1) Create new C++ console project in Visual Studio, 2) Paste the above code to the new project's main "ConsoleApplicationX.cpp" file (where X is a number) - replacing whatever is there, 3) Adjust the path to your MSP file (CString lpszFilename = L"C:\\YourPatchFile.msp";), 4) Say out loud: "fire in the hole" and hope for the best :-).

    MSI API Documentation: Here are some links: