Last active
July 25, 2024 08:26
-
-
Save milo2012/a62a024a11fe4cc9b7f3ea0e24b8fcd2 to your computer and use it in GitHub Desktop.
searchMSIGetCustomActions.ps1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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