Skip to content

Instantly share code, notes, and snippets.

@milo2012
Last active July 25, 2024 08:26
Show Gist options
  • Save milo2012/a62a024a11fe4cc9b7f3ea0e24b8fcd2 to your computer and use it in GitHub Desktop.
Save milo2012/a62a024a11fe4cc9b7f3ea0e24b8fcd2 to your computer and use it in GitHub Desktop.
searchMSIGetCustomActions.ps1
function Get-CustomActionsFromMSI {
param (
[string]$msiPath
)
try {
# Load the Windows Installer COM object
$installer = New-Object -ComObject WindowsInstaller.Installer
# Open the MSI database in read-only mode
$database = $installer.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $installer, @($msiPath, 0))
# Define the SQL query to get custom actions
$query = "SELECT * FROM CustomAction"
# Open a view on the CustomAction table
$view = $database.OpenView($query)
# Execute the view query
$view.Execute()
# Fetch the results
$record = $view.Fetch()
# Loop through each record and display the custom actions
while ($record -ne $null) {
$actionName = $record.StringData(1)
#$actionType = $record.IntegerData(2)
$actionType = $record.StringData(2)
$source = $record.StringData(3)
$target = $record.StringData(4)
# Debugging output
#Write-Host "Raw Action Type Value: $actionType"
# Determine the custom action type
switch ($actionType) {
1 { $typeName = "InstallScript" }
2 { $typeName = "DLL" }
3 { $typeName = "EXE" }
4 { $typeName = "Property" }
5 { $typeName = "InstallExecuteSequence" }
6 { $typeName = "InstallUISequence" }
17 { $typeName = "Directory" }
18 { $typeName = "CreateFolder" }
19 { $typeName = "StartService" }
21 { $typeName = "File" }
22 { $typeName = "RemoveFile" }
34 { $typeName = "RegisterServer" }
35 { $typeName = "RegisterTypeLib" }
36 { $typeName = "UnregisterServer" }
38 { $typeName = "UnregisterTypeLib" }
50 { $typeName = "SetProperty" }
51 { $typeName = "SetDirectory" }
53 { $typeName = "InstallConfig" }
54 { $typeName = "Commit" }
#default { $typeName = "Unknown Type" }
}
# Output custom action details
#Write-Host "Custom Action Name: $actionName"
Write-Host "Custom Action Type: $typeName"
Write-Host "Source: $source"
Write-Host "Target: $target`n"
# Check for specific paths
if ($target -match 'USERPROFILE') {
Write-Host "The target contains USERPROFILE"
}
if ($target -match 'TEMP|TMP') {
Write-Host "The target contains TEMP or TMP"
}
#Write-Host "`n"
# Fetch the next record
$record = $view.Fetch()
}
# Close the view
$view.Close()
}
catch {
Write-Output "Error: $($_.Exception.Message)"
}
}
function Get-MSIProperties {
param (
[string]$filePath
)
try {
# Initialize variables
$manufacturer = $null
$productName = $null
$productVersion = $null
# Load the Windows Installer COM object
$installer = New-Object -ComObject WindowsInstaller.Installer
# Open the MSI database in read-only mode
$database = $installer.OpenDatabase($filePath, 0)
# Query and get Manufacturer
$view = $database.OpenView("SELECT `Value` FROM `Property` WHERE `Property`='Manufacturer'")
$view.Execute()
$record = $view.Fetch()
if ($record -ne $null) {
$manufacturer = $record.StringData(1)
}
$view.Close()
# Query and get ProductName
$view = $database.OpenView("SELECT `Value` FROM `Property` WHERE `Property`='ProductName'")
$view.Execute()
$record = $view.Fetch()
if ($record -ne $null) {
$productName = $record.StringData(1)
}
$view.Close()
# Query and get ProductVersion
$view = $database.OpenView("SELECT `Value` FROM `Property` WHERE `Property`='ProductVersion'")
$view.Execute()
$record = $view.Fetch()
if ($record -ne $null) {
$productVersion = $record.StringData(1)
}
$view.Close()
# Create an object to return the properties
$result = [PSCustomObject]@{
Manufacturer = $manufacturer
ProductName = $productName
ProductVersion = $productVersion
}
return $result
}
catch {
Write-Output "Error: $($_.Exception.Message)"
}
}
$folderPath = "C:\Windows\Installer"
$msiFiles = Get-ChildItem -Path $folderPath -Filter "*.msi" -File
foreach ($file in $msiFiles) {
#if ($file.FullName -like "*poc*") {
$result = Get-MSIProperties($file.FullName)
#,Manufacturer:$($result.Manufacturer,ProductName, $($result.Manufacturer,ProductName: $($result.Manufacturer) $($result.ProductName) $($result.ProductVersion)"
#if ($result.Manufacturer -ne "Microsoft Corporation") {
Write-Output "File: $($file.FullName)"
#Write-Output "Manufacturer: $($result.Manufacturer)"
Write-Output "ProductName/Version: $($result.ProductName) $($result.ProductVersion)"
#Write-Output "ProductName: $($result.ProductName)"
#Write-Output "ProductVersion: $($result.ProductVersion)"
#Write-Output "-----------------------------"
Get-CustomActionsFromMSI($file.FullName)
Write-Output "-----------------------------"
#}
#}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment