Reputation:
My script gathering msi information such as ProductCode, ProductName, Upgrade Code etc.. I am trying to get all information what in CLI read export a csv file.
Here is a piece of code, the rest is also similar
$Dir = Get-ChildItem -Path W:\MSIs\*.msi -Recurse
foreach ($item in $Dir) {
try {
$windowsInstaller = New-Object -com WindowsInstaller.Installer
$database = $windowsInstaller.GetType().InvokeMember('OpenDatabase', 'InvokeMethod', $null, $windowsInstaller, @((Get-Item -Path $item).FullName, 0))
$view = $database.GetType().InvokeMember('OpenView', 'InvokeMethod', $null, $database, ("SELECT Value FROM Property WHERE Property = 'ProductName'"))
$view.GetType().InvokeMember('Execute', 'InvokeMethod', $null, $view, $null)
$record = $view.GetType().InvokeMember('Fetch', 'InvokeMethod', $null, $view, $null)
echo "Product Name"
Write-Output -InputObject $($record.GetType().InvokeMember('StringData', 'GetProperty', $null, $record, 1))
} catch {
Write-Error -Message "Product Name" $_.ToString()s
break
}
Upvotes: 0
Views: 112
Reputation: 1039
Graham's Answer is good. I had already started writing a function to export all the properties to PowerShell so decided to post it anyway.
I wrote a thing! It grabs all properties from an MSI and simply translates it into a PSCustomObject. This allows you to do a Select-Object on the object to grab the properties you're interested in.
$Dir = Get-ChildItem -Path C:\MSIs\*.msi -Recurse
function Get-MsiPropertyList {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string]
$Path
)
process {
$Path | Foreach-Object {
$item = $_
$windowsInstaller = New-Object -ComObject WindowsInstaller.Installer
$database = $windowsInstaller.GetType().InvokeMember('OpenDatabase', 'InvokeMethod', $null, $windowsInstaller, @((Get-Item -Path $item).FullName, 0))
$view = $Database.GetType().InvokeMember('OpenView', 'InvokeMethod', $null, $Database, ("SELECT Property,Value FROM Property"))
$view.GetType().InvokeMember('Execute', 'InvokeMethod', $null, $view, $null) | Out-Null
$record = $view.GetType().InvokeMember('Fetch', 'InvokeMethod', $null, $view, $null)
$ret = [pscustomobject]@{
Path = $item
}
while ($record -ne $null) {
$property = $record.GetType().InvokeMember('StringData', 'GetProperty', $null, $record, 1)
$value = $record.GetType().InvokeMember('StringData', 'GetProperty', $null, $record, 2)
$ret | Add-Member -MemberType NoteProperty -Name $property -Value $value
$record = $view.GetType().InvokeMember('Fetch', 'InvokeMethod', $null, $view, $null)
}
Write-Output $ret
}
}
}
# Export all properties to a csv
$Dir | Get-MsiPropertyList | Export-Csv -Path C:\MSIs\test.csv -NoTypeInformation
# Export selected properties to a csv
$Dir | Get-MsiPropertyList | Select-Object -Property Path, ProductName, ProductVersion | Export-Csv -Path C:\MSIs\test2.csv -NoTypeInformation
Hope it helps. Fish
Upvotes: 1
Reputation: 497
I had to do something fairly similiar myself, though only with a few select properties.
I used this microsoft site first of all to get a huge amount of data from the msi files.
https://gallery.technet.microsoft.com/scriptcenter/Get-all-native-properties-e4e19180
Unfortunately the one property I needed wasn't listed, when my search continued I found this much simpler version of getting file info.
Armed with the second link I built a function to suit my needs perfectly - depending on the properties you're after this function can easily be amended, and once in an array it's easy to export.
Function Get-FileInfo {
<#
.SYNOPSIS
Retrieves information from files
.DESCRIPTION
This function uses the WindowInstaller COM object to pull the subject line from an MSI file.
.EXAMPLE
Get-FileInfo E:\DownloadDir\MicrosoftIdentityExtensions-64.msi
Name RevNo Size
---- ----- ----
ACS S2S OAuth JWT Extension {6520558F-956F-4388-8C50-58E5557D7519} 252
.NOTES
Inspired by this:
https://devblogs.microsoft.com/scripting/hey-scripting-guy-how-can-i-retrieve-the-subject-property-for-a-msi-file/
#>
Param (
[parameter( Mandatory = $true ) ][ValidateNotNullOrEmpty()][System.IO.FileInfo]$FilePath
)
Begin {
If ( $FilePath.Extension -match ".msi" ){
$com_object = New-Object -com WindowsInstaller.Installer
$comproperties = $com_object.SummaryInformation( $FilePath.Fullname )
}
$msiproperties = @()
}
Process {
If ( $FilePath.Extension -match ".msi" ){
$msiproperties += [PSCustomObject] @{
Name = ( $comproperties.Property( 3 ) ).TrimEnd() ;
RevNo = $comproperties.Property( 9 );
Creation = $comproperties.Property( 12 );
}
}
}
End {
Return $msiproperties
}
}
Hope it helps
Upvotes: 2