Ein Windows Installer-Patch (MSP-Datei) ist eine Paketdatei, ein die Updates für eine bestimmte Anwendung enthält und beschreibt, welche Versionen der Anwendung gepatcht werden kann. Der Vorteil eines MSPs ist, dass nur die Dateien enthalten sind, die sich zu einem MSI ändern. MSP werden für Minor Releases eingesetzt (i.d.R. kleine Updates). Ich selber habe ein Tool in der Hinterhand, dass binäre Differenzen für extrem kleine Patches verteilen kann (wird denn demnächst veröffentlicht).
In dem Patch enthalten ist u.a. ein Productcode und ein Patchcode für die zu ändernde Anwendung. Passt der Productcode zu einer installierten Anwendung, kann gepatched werden. Es ist also praktisch, diesen Code schon vor einer Installation zu ermitteln, um eine Softwareverteilung zu optimieren. Im Folgenden werden zwei Lösungen mit Powershell gezeigt.
Wie bekommt man den Productcode heraus? Eine Variante ist die Installation auf Codeplex: MSI Powershell Module. Der Nachteil dieses Modules ist, dass dafür auch wieder ein MSI installiert werden muss. Dies beinhaltet wiederum Komponenten des Windows Installer XML. Also nichts, was einfach in ein Paket eingebunden werden kann.Das MSI Powershell Module ist im übrigen sehr gut und ich kann das sehr empfehlen für komplexere Dinge. Nach der Installation bekommt man beispielsweise so die Daten einer MSI Datei:
get-msicomponentinfo `
| where { $_.Path -like 'C:\Program Files\*\Common7\IDE\devenv.exe'} `
| get-msiproductinfo
Vor kurzen habe ich nach einer Möglichkeit, gesucht, den Productcode eines eines MSP auszulesen, ohne diesen Overhead. Das COM Object "WindowsInstaller.Installer" bietet diese Möglichkeit. Der Vorteil ist, dass diese Funktionen leicht bei Installationen eingesetzt werden können. Also zum Abgleich, ob ein Patch für ein System geeigent ist. Demnächst baue ich das genau so in unseren Citrix XenApp Patcher ein.
Auslesen des "Display Name" des Patches mit Powershell. Achtung, dieser ist nicht immer im MSP enthalten:
function Get-MSPDisplayName {
<#
.SYNOPSIS
Get the Display Name from an Microsoft Installer Patch MSP
.DESCRIPTION
Get Display Name from an Microsoft Installer Patch MSP (Andreas Nick 2015)
.NOTES
$NULL for an error
.LINK
.RETURNVALUE
[String] Display Name
.PARAMETER
[IO.FileInfo] Path to the msp file
#>
function Get-MSPDisplayName {
param (
[IO.FileInfo] $patchnamepath
)
try {
$wi = New-Object -com WindowsInstaller.Installer
$mspdb = $wi.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $Null, $wi, $($patchnamepath.FullName, 32))
$su = $mspdb.GetType().InvokeMember("SummaryInformation", "GetProperty", $Null, $mspdb, $Null)
[String] $displayName = $su.GetType().InvokeMember("Property", "GetProperty", $Null, $su, 6)
return $displayName
}
catch {
Write-Output $_.Exception.Message
return $NULL
}
}
Auslesen des Productcodes eines Microsoft Patches (MSP) mit Powershell:
<#
.SYNOPSIS
Get the Product Code from an Microsoft Installer Patch MSP
.DESCRIPTION
Get a Product Code from an Microsoft Installer Patch MSP (Andreas Nick 2015)
.NOTES
$NULL for an error
.LINK
.RETURNVALUE
[String] Product Code
.PARAMETER
[IO.FileInfo] Path to the msp file
#>
function Get-MSPProductcode {
param (
[IO.FileInfo] $patchnamepath
)
try {
$wi = New-Object -com WindowsInstaller.Installer
$mspdb = $wi.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $Null, $wi, $($patchnamepath.FullName, 32))
$su = $mspdb.GetType().InvokeMember("SummaryInformation", "GetProperty", $Null, $mspdb, $Null)
#$pc = $su.GetType().InvokeMember("PropertyCount", "GetProperty", $Null, $su, $Null)
[String] $productcode = $su.GetType().InvokeMember("Property", "GetProperty", $Null, $su, 7)
return $productcode
}
catch {
Write-Output $_.Exception.Message
return $NULL
}
}
Auslesen des Patchcodes eines MSP Patches mit Powershell:
<#
.SYNOPSIS
Get the Patch Code from an Microsoft Installer Patch MSP
.DESCRIPTION
Get a Patch Code from an Microsoft Installer Patch MSP (Andreas Nick 2015)
.NOTES
$NULL for an error
.LINK
.RETURNVALUE
[String] Product Code
.PARAMETER
[IO.FileInfo] Path to the msp file
#>
function Get-MSPPatchcode {
param (
[IO.FileInfo] $patchnamepath
)
try {
$wi = New-Object -com WindowsInstaller.Installer
$mspdb = $wi.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $Null, $wi, $($patchnamepath.FullName, 32))
$su = $mspdb.GetType().InvokeMember("SummaryInformation", "GetProperty", $Null, $mspdb, $Null)
$pc = $su.GetType().InvokeMember("PropertyCount", "GetProperty", $Null, $su, $Null)
#Write-Host $pc
[String] $patchcode = $su.GetType().InvokeMember("Property", "GetProperty", $Null, $su, 9)
return $patchcode
}
catch {
Write-Output $_.Exception.Message
return $NULL
}
}






















Eine der wichtigsten Aufgaben bei der Installation einer neuen XenApp/XenDesktop 7 Umgebung ist es, den Zugriff auf den Hypervisor zu konfigurieren. Die von uns betreuten Umgebungen nutzen als Basis meist vmware ESXi in Verbindung mit vSphere. Weiterhin ist auch immer wieder die vSphere Appliance ein Thema.
NIT-GPOSearch is a free tool to search in the Group Policy (admx, adml) definitions for a specific setting. New in Version 1.2 - search in the domain template definitions.
The V-Injector is a tool for direct editing of App-V 5 .appv (package) files. V-Injector is a small single C ++ / CLI exe ( “< 400 kb !”) . Very fast and efficient for this purpose. The V-Injector will not extracting an appv file to your file system (like the sequencer)!