Чтение нескольких значений из Msi-файла / SELECT * из таблицы MSI / InvokeMember с 5 аргументами «OpenView, Sql» в Powershell - PullRequest
0 голосов
/ 17 апреля 2020

Я застрял в проблеме, прочитав несколько нестатических c значений из Msi-файла с powershell. Есть ли какие-нибудь идеи?

Я хочу прочитать не stati c значения из таблиц Msi.

Я могу фактически прочитать stati c значения из свойств таблицы, но по одному. как эта функция readMsiProperties ($ msifile, $ Property) {

# Read property from MSI database
$WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer
$MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $WindowsInstaller, @($msiFile, 0))
$Query = "SELECT Value FROM Property WHERE Property = '$Property'"

try {

    $View = $MSIDatabase.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $MSIDatabase, ($Query))
    $View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null)
    $Record = $View.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $View, $null)
    $Value = $Record.GetType().InvokeMember("StringData", "GetProperty", $null, $Record, 1)
    # Commit database and close view
    $MSIDatabase.GetType().InvokeMember("Commit", "InvokeMethod", $null, $MSIDatabase, $null)
    $View.GetType().InvokeMember("Close", "InvokeMethod", $null, $View, $null)           
    $MSIDatabase = $null
    $View = $null

    return $Value
    #Catch NullValues if a Query is not correct or not in the MSI File
}
Catch {

}

}

Это прекрасно работает для таблицы свойств. Но если я хочу что-то прочитать из таблицы Serviceinstall, я не могу использовать значения stati c, которые я могу использовать как якорь.

, если я попробую это таким образом, я получу «InvokeMember с исключением 5 аргументов» для Переменная $ view.

функция readMsiServiceTable ($ msifile) {

#try{
# Read property from MSI database
$WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer
$MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $WindowsInstaller, @($msiFile, 0))
$Query = "SELECT '*' FROM 'ServiceInstall' "

try {

    $View = $MSIDatabase.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $MSIDatabase, ($Query))

Итак, что я могу сделать вместо этого. Идея состоит в том, чтобы читать эти нестати c значения в массив или список для работы с ним.

Спасибо !!

1 Ответ

0 голосов
/ 21 апреля 2020

См. Здесь (и пример ниже), как использовать PowerShell для запроса базы данных MSI: https://www.alkanesolutions.co.uk/2016/12/13/query-windows-installer-msi-using-powershell/

$msiOpenDatabaseModeReadOnly = 0
$msiOpenDatabaseModeTransact = 1

$windowsInstaller = New-Object -ComObject windowsInstaller.Installer

$pathToMSI = "C:\temp\test.msi"

$database = $windowsInstaller.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $windowsInstaller, @($pathToMSI, $msiOpenDatabaseModeReadOnly))

$query = "SELECT * FROM ServiceInstall"
$propView = $database.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $database, ($query))
$propView.GetType().InvokeMember("Execute", "InvokeMethod", $null, $propView, $null) | Out-Null
$propRecord = $propView.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $propView, $null)

while  ($propRecord -ne $null)
{
    $serviceInstall = $propRecord.GetType().InvokeMember("StringData", "GetProperty", $null, $propRecord, 1)
    $serviceName = $propRecord.GetType().InvokeMember("StringData", "GetProperty", $null, $propRecord, 2)
    $serviceType = $propRecord.GetType().InvokeMember("IntegerData", "GetProperty", $null, $propRecord, 4)

    write-host $serviceInstall $serviceName $serviceType

    #fetch the next record
    $propRecord = $propView.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $propView, $null)    
}

$propView.GetType().InvokeMember("Close", "InvokeMethod", $null, $propView, $null) | Out-Null          
$propView = $null 
$propRecord = $null
$database = $null
...