How to Use GetMSIVersion to Check Installer Packages

Written by

in

To implement a GetMSIVersion routine, developers typically extract the ProductVersion property embedded inside a closed Microsoft Installer (.msi) file database without triggering an active installation. This is achieved programmatically by querying the Property table inside the MSI database utilizing the native Windows Installer COM Object (WindowsInstaller.Installer).

The following examples demonstrate how to implement this logic using both C# and PowerShell. 🛠️ Method 1: C# Implementation

In C#, you dynamically look up the WindowsInstaller.Installer COM type via its Program ID (ProgID). This approach avoids forcing a rigid dependency or requiring an external Interop DLL assembly inside your project deployment.

using System; // … (implementation uses Type.GetTypeFromProgID and OpenDatabase) Use code with caution.

The core logic involves initializing the WindowsInstaller.Installer object, opening the MSI in read-only mode, executing a SQL query (SELECT ValueFROMPropertyWHEREProperty = ‘ProductVersion’), and reading the result. 📜 Method 2: PowerShell Implementation

PowerShell interacts natively with COM APIs, allowing a clean scripting implementation. Option A: Native COM Object (Standard & Robust)

This approach mimics the C# architecture directly inside a reusable PowerShell function using New-Object -ComObject WindowsInstaller.Installer. It utilizes InvokeMember for database operations (OpenDatabase, OpenView, Execute, Fetch) and requires proper cleanup of the object to release the file lock. Option B: AppLocker Quick Method (One-Liner)

If AppLocker is available, you can quickly retrieve version metadata without direct COM manipulation:(Get-AppLockerFileInformation -Path “C:\path.msi” | Select-Object -ExpandProperty Publisher).BinaryVersion 📋 Comparison Overview Metric / Feature C# Implementation PowerShell COM Implementation Execution Context Compiled binaries / application backends Automation scripting / DevOps pipelines Performance Fast, optimized memory footprint Slightly slower, interpreter overhead Error Resiliency Compile-time checks available Fully runtime-dependent dynamic parsing File Locking Explicit try/finally structure recommended Prone to locks if GC is not handled

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *