param(
[Parameter(Mandatory=$true)][string]$MsiPath,
[ValidateSet('tables','features','components','files','shortcuts','custom_actions','summary')]
[string]$Action = 'tables'
)
$ErrorActionPreference = 'Stop'
if (-not (Test-Path -LiteralPath $MsiPath)) {
throw "MSI path not found: $MsiPath"
}
$installer = New-Object -ComObject WindowsInstaller.Installer
$db = $installer.OpenDatabase($MsiPath, 0)
switch ($Action) {
'tables' {
$view = $db.OpenView("SELECT Name FROM _Tables")
$view.Execute() | Out-Null
$rows = @()
while ($true) {
$rec = $view.Fetch()
if (-not $rec) { break }
$rows += $rec.StringData(1)
}
$rows | ConvertTo-Json -Compress
break
}
'features' {
$view = $db.OpenView("SELECT Feature, Title, Description, Display, Level, Directory_, Attributes, Feature_Parent FROM Feature")
$view.Execute() | Out-Null
$rows = @()
while ($true) {
$rec = $view.Fetch()
if (-not $rec) { break }
$rows += [pscustomobject]@{
Feature = $rec.StringData(1)
Title = $rec.StringData(2)
Description = $rec.StringData(3)
Display = $rec.StringData(4)
Level = $rec.StringData(5)
Directory = $rec.StringData(6)
Attributes = $rec.StringData(7)
FeatureParent = $rec.StringData(8)
}
}
$rows | ConvertTo-Json -Compress
break
}
'components' {
$view = $db.OpenView("SELECT Component, ComponentId, Directory_, Attributes, Condition, KeyPath FROM Component")
$view.Execute() | Out-Null
$rows = @()
while ($true) {
$rec = $view.Fetch()
if (-not $rec) { break }
$rows += [pscustomobject]@{
Component = $rec.StringData(1)
ComponentId = $rec.StringData(2)
Directory = $rec.StringData(3)
Attributes = $rec.StringData(4)
Condition = $rec.StringData(5)
KeyPath = $rec.StringData(6)
}
}
$rows | ConvertTo-Json -Compress
break
}
'files' {
$view = $db.OpenView("SELECT File, Component_, FileName, FileSize, Version, Language, Attributes, Sequence FROM File")
$view.Execute() | Out-Null
$rows = @()
while ($true) {
$rec = $view.Fetch()
if (-not $rec) { break }
$rows += [pscustomobject]@{
File = $rec.StringData(1)
Component = $rec.StringData(2)
FileName = $rec.StringData(3)
FileSize = $rec.StringData(4)
Version = $rec.StringData(5)
Language = $rec.StringData(6)
Attributes = $rec.StringData(7)
Sequence = $rec.StringData(8)
}
}
$rows | ConvertTo-Json -Compress
break
}
'shortcuts' {
$view = $db.OpenView("SELECT Shortcut, Directory_, Name, Target FROM Shortcut")
$view.Execute() | Out-Null
$rows = @()
while ($true) {
$rec = $view.Fetch()
if (-not $rec) { break }
$rows += [pscustomobject]@{
Shortcut = $rec.StringData(1)
Directory = $rec.StringData(2)
Name = $rec.StringData(3)
Target = $rec.StringData(4)
}
}
$rows | ConvertTo-Json -Compress
break
}
'custom_actions' {
$view = $db.OpenView("SELECT Action, Type, Source, Target FROM CustomAction")
$view.Execute() | Out-Null
$rows = @()
while ($true) {
$rec = $view.Fetch()
if (-not $rec) { break }
$rows += [pscustomobject]@{
Action = $rec.StringData(1)
Type = $rec.StringData(2)
Source = $rec.StringData(3)
Target = $rec.StringData(4)
}
}
$rows | ConvertTo-Json -Compress
break
}
'summary' {
$sum = $null
try {
$sum = $installer.SummaryInformation($MsiPath, 0)
$obj = [pscustomobject]@{
Title = $sum.Property(2)
Subject = $sum.Property(3)
Author = $sum.Property(4)
Keywords = $sum.Property(5)
Comments = $sum.Property(6)
Template = $sum.Property(7)
LastSavedBy = $sum.Property(8)
RevisionNumber = $sum.Property(9)
CreateTimeDate = $sum.Property(12)
LastSaveTimeDate = $sum.Property(13)
PageCount = $sum.Property(14)
WordCount = $sum.Property(15)
CharacterCount = $sum.Property(16)
ApplicationName = $sum.Property(18)
Security = $sum.Property(19)
}
$obj | ConvertTo-Json -Compress
} finally {
if ($sum) { $sum.Persist() | Out-Null }
}
break
}
default {
throw "Unknown action: $Action"
}
}