├── .gitattributes ├── README.md ├── LICENSE └── GetMSIInfo.ps1 /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GetMSIInfo 2 | GetMSIInfo is a simple PowerShell script that adds a right click context menu to grab information for MSI files. 3 | 4 | # Installation 5 | 1. Run GetMSIInfo.ps1 with the "-Install" flag to install the appliction to your %LOCALAPPDATA% folder and set the appropriate registry keys, this is a User Based installation. 6 | 7 | # Usage 8 | * Right click an MSI file and click "Get MSI Information" to retrieve the "Property" table from within the MSI. 9 | * Select one or multiple properties and click OK, the Values for the Properties are copied to your clipboard 10 | 11 | # Uninstallation 12 | 1. Run the GetMSIInfo.ps1 script with the "-Uninstall" flag to remove the script and associated registry keys. 13 | 14 | # Special Thanks 15 | Adam Bertram for Get-MsiDatabaseProperties from https://github.com/adbertram/Random-PowerShell-Work/blob/master/Software/Get-MSIDatabaseProperties.ps1 which made pulling the MSI data easy! 16 | 17 | Roger Zander for https://reg2ps.azurewebsites.net/ which made the registry edits (and numerous other things in my life) easy! -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Andrew Jimenez 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /GetMSIInfo.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Script that adds a right click menu to grab info from MSI Files. 4 | .DESCRIPTION 5 | GetMSIInfo is a simple PowerShell script that adds a right click context menu to grab information for MSI files. 6 | .EXAMPLE 7 | Install the Script 8 | GetMSIInfo.ps1 -Install 9 | .EXAMPLE 10 | Uninstall the Script 11 | GetMSIInfo.ps1 -Uninstall 12 | .NOTES 13 | This script is installed in the User Context 14 | Created by Andrew Jimenez (@asjimene) 2020-04-12 15 | #> 16 | 17 | Param ( 18 | # Specifies a path to one or more locations. Unlike the Path parameter, the value of the LiteralPath parameter is 19 | # used exactly as it is typed. No characters are interpreted as wildcards. If the path includes escape characters, 20 | # enclose it in single quotation marks. Single quotation marks tell Windows PowerShell not to interpret any 21 | # characters as escape sequences. 22 | [Parameter(Mandatory = $false, 23 | Position = 0, 24 | ParameterSetName = "LiteralPath", 25 | ValueFromPipelineByPropertyName = $true, 26 | HelpMessage = "Literal path to one or more locations.")] 27 | [Alias("PSPath")] 28 | [ValidateNotNullOrEmpty()] 29 | [string[]] 30 | $LiteralPath, 31 | # Install Switch Run this Script with the Install Switch to Install the Script and add the Registry changes to your account 32 | [Parameter(Mandatory = $false)] 33 | [switch] 34 | $Install = $false, 35 | # Uninstall Switch Run this Script with the uninstall Switch to uninstall the Script and remove the Registry changes to your account 36 | [Parameter(Mandatory = $false)] 37 | [switch] 38 | $Uninstall = $false 39 | ) 40 | 41 | function Get-MsiDatabaseProperties { 42 | <# 43 | .SYNOPSIS 44 | This function retrieves properties from a Windows Installer MSI database. 45 | .DESCRIPTION 46 | This function uses the WindowInstaller COM object to pull all values from the Property table from a MSI. 47 | .EXAMPLE 48 | Get-MsiDatabaseProperties 'MSI_PATH' 49 | .PARAMETER FilePath 50 | The path to the MSI you'd like to query 51 | #> 52 | [CmdletBinding()] 53 | param ( 54 | [Parameter(Mandatory = $True, 55 | ValueFromPipeline = $True, 56 | ValueFromPipelineByPropertyName = $True, 57 | HelpMessage = 'What is the path of the MSI you would like to query?')] 58 | [IO.FileInfo[]]$FilePath, 59 | [Parameter()] 60 | [String] 61 | $Table = "Property" 62 | ) 63 | 64 | begin { 65 | $com_object = New-Object -com WindowsInstaller.Installer 66 | } 67 | 68 | process { 69 | try { 70 | $database = $com_object.GetType().InvokeMember( 71 | "OpenDatabase", 72 | "InvokeMethod", 73 | $Null, 74 | $com_object, 75 | @($FilePath.FullName, 0) 76 | ) 77 | 78 | $query = "SELECT * FROM $Table" 79 | $View = $database.GetType().InvokeMember( 80 | "OpenView", 81 | "InvokeMethod", 82 | $Null, 83 | $database, 84 | ($query) 85 | ) 86 | 87 | $View.GetType().InvokeMember("Execute", "InvokeMethod", $Null, $View, $Null) 88 | 89 | $record = $View.GetType().InvokeMember( 90 | "Fetch", 91 | "InvokeMethod", 92 | $Null, 93 | $View, 94 | $Null 95 | ) 96 | 97 | $msi_props = @{ } 98 | while ($record -ne $null) { 99 | $msi_props[$record.GetType().InvokeMember("StringData", "GetProperty", $Null, $record, 1)] = $record.GetType().InvokeMember("StringData", "GetProperty", $Null, $record, 2) 100 | $record = $View.GetType().InvokeMember( 101 | "Fetch", 102 | "InvokeMethod", 103 | $Null, 104 | $View, 105 | $Null 106 | ) 107 | } 108 | 109 | $msi_props 110 | 111 | } 112 | catch { 113 | throw "Failed to get MSI file properties the error was: {0}." -f $_ 114 | } 115 | } 116 | } 117 | 118 | 119 | if ($Install) { 120 | Write-Output "Creating GetMSIInfo folder in LOCALAPPDATA folder" 121 | New-Item -ItemType Directory -Path $env:LOCALAPPDATA -Name "GetMSIInfo" -ErrorAction SilentlyContinue 122 | 123 | Write-Output "Copying Script to GetMSIInfo Folder" 124 | Copy-Item $PSScriptRoot\GetMSIInfo.ps1 -Destination "$env:LOCALAPPDATA\GetMSIInfo\GetMSIInfo.ps1" -ErrorAction SilentlyContinue 125 | 126 | # Reg2CI (c) 2020 by Roger Zander 127 | if ((Test-Path -LiteralPath "HKCU:\Software\Classes\SystemFileAssociations\.msi") -ne $true) { New-Item "HKCU:\Software\Classes\SystemFileAssociations\.msi" -force -ea SilentlyContinue }; 128 | if ((Test-Path -LiteralPath "HKCU:\Software\Classes\SystemFileAssociations\.msi\shell") -ne $true) { New-Item "HKCU:\Software\Classes\SystemFileAssociations\.msi\shell" -force -ea SilentlyContinue }; 129 | if ((Test-Path -LiteralPath "HKCU:\Software\Classes\SystemFileAssociations\.msi\shell\Get MSI Information") -ne $true) { New-Item "HKCU:\Software\Classes\SystemFileAssociations\.msi\shell\Get MSI Information" -force -ea SilentlyContinue }; 130 | if ((Test-Path -LiteralPath "HKCU:\Software\Classes\SystemFileAssociations\.msi\shell\Get MSI Information\command") -ne $true) { New-Item "HKCU:\Software\Classes\SystemFileAssociations\.msi\shell\Get MSI Information\command" -force -ea SilentlyContinue }; 131 | New-ItemProperty -LiteralPath 'HKCU:\Software\Classes\SystemFileAssociations\.msi\shell\Get MSI Information' -Name '(default)' -Value "Get MSI Information" -PropertyType String -Force -ea SilentlyContinue; 132 | New-ItemProperty -LiteralPath 'HKCU:\Software\Classes\SystemFileAssociations\.msi\shell\Get MSI Information\command' -Name '(default)' -Value "C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -Command `"$env:LOCALAPPDATA\GetMSIInfo\GetMSIInfo.ps1`" -LiteralPath '%1'" -PropertyType String -Force -ea SilentlyContinue; 133 | 134 | Write-Output "Installation Complete" 135 | Pause 136 | } 137 | 138 | if ($Uninstall) { 139 | Write-Output "Removing Script from LOCALAPPDATA" 140 | Remove-item "$env:LOCALAPPDATA\GetMSIInfo" -Force -Recurse -ErrorAction SilentlyContinue 141 | 142 | Write-Output "Cleaning Up Registry" 143 | if ((Test-Path -LiteralPath "HKCU:\Software\Classes\SystemFileAssociations\.msi\shell\Get MSI Information") -eq $true) { 144 | Remove-Item "HKCU:\Software\Classes\SystemFileAssociations\.msi\shell\Get MSI Information" -force -Recurse -ea SilentlyContinue 145 | } 146 | if ([System.String]::IsNullOrEmpty((Get-ChildItem "HKCU:\Software\Classes\SystemFileAssociations\.msi\shell"))) { 147 | Remove-Item "HKCU:\Software\Classes\SystemFileAssociations\.msi\shell" -force -Recurse -ea SilentlyContinue 148 | } 149 | if ([System.String]::IsNullOrEmpty((Get-ChildItem "HKCU:\Software\Classes\SystemFileAssociations\.msi"))) { 150 | Remove-Item "HKCU:\Software\Classes\SystemFileAssociations\.msi" -force -Recurse -ea SilentlyContinue 151 | } 152 | 153 | Write-Output "Uninstallation Complete!" 154 | Pause 155 | } 156 | 157 | if ((-not $Install) -and (-not $Uninstall)) { 158 | $SelectedInfo = Get-MsiDatabaseProperties -FilePath $LiteralPath | Out-GridView -Title "MSI Database Properties for $LiteralPath" -OutputMode Multiple 159 | $SelectedInfo.Value | Set-Clipboard 160 | } --------------------------------------------------------------------------------