|
<< Click to Display Table of Contents >> RayPack > 8.0 > User Guide > Erweiterte Themen PackDesigner-Skripte erstellen |
PackDesigner bietet eine einfache Möglichkeit, skriptbasierte Logik für alle MSI-/RPP-/MST-Projekte zu implementieren. Die Skripte (Makros) werden in der aggregierten Ansicht Plugins angezeigt. Skripte sind einfache VBS- oder PowerShell-Dateien, die am folgenden Speicherort vorhanden sein müssen.
<PackPoint>\Scripts
Dabei ist <PackPoint> der Speicherort, an dem die PackPoint-Ressourcen installiert sind. Die Standardinstallation von RayPack enthält bereits zwei Beispielskripte für GUID-Manipulationen (beide aus funktionaler Sicht gleichwertig; eines in VBS, das andere in PowerShell geschrieben). Skripte werden im Baum angezeigt, und Dateinamen werden als Knotenbezeichnungen verwendet.
Unabhängig von der gewählten Technologie wird das Skript mit einem einzelnen Argument gestartet – einem vollständigen Pfad zu einer temporären Datenbank, die das Skript aktualisieren soll. Nachfolgend finden Sie ein Beispiel für ein Skript, das lediglich das Orca-Tool startet und das aktuelle Paket in Orca öffnet.
const DontWaitUntilFinished = false, ShowWindow = 1, DontShowWindow = 0, WaitUntilFinished = true
'Standard VBS object, used to operate with windows shell (explorer)
Dim objShell
Set objShell = WScript.CreateObject( "WScript.Shell" )
'Finding correct path to the ProgramFiles directory
programFilesPath = objShell.ExpandEnvironmentStrings("%ProgramFiles(x86)%")
arguments = ""
'Checking, if we have at least one command line argument. It's expected to be MSI file path.
if WScript.Arguments.Count > 0 Then
arguments = """" & WScript.Arguments(0) & """"
end if
'Creating final executable path with arguments
exePath = """" & programFilesPath & "\Orca\Orca.exe"" " & arguments
'Running the application and waiting for it to finish
objShell.Run exePath, ShowWindow, WaitUntilFinished
Set objShell = Nothing
Nachfolgend finden Sie ein Standardskript (ebenfalls VBS), das alle Paket-GUIDs zurücksetzt und die temporäre Datenbank speichert. Nachdem das Skript abgeschlossen ist, erfasst RayPack die Änderungen und wendet sie im aktuellen Projekt an.
Zum Öffnen, Bearbeiten und Speichern einer MSI-Datenbank wird die MSI-COM-Schnittstelle verwendet. Die Dokumentation ihrer Methoden ist auf der MSDN-Website verfügbar: https://msdn.microsoft.com/en-us/library/windows/desktop/aa367810(v=vs.85).aspx.
Option Explicit
Function CreateGUID
Dim TypeLib
Set TypeLib = CreateObject("Scriptlet.TypeLib")
dim guid
guid = TypeLib.Guid
CreateGUID = Left(UCase(guid), 38)
End Function
Dim installer, database, view, record, viewUpdate
Set installer = CreateObject("WindowsInstaller.Installer")
Set database = installer.OpenDatabase (WScript.Arguments(0), 1)
Set view = database.OpenView ("SELECT Component FROM Component")
view.execute
set record = view.Fetch
Do While Not record Is Nothing
dim componentName, componentGuid
componentName = record.StringData(1)
componentGuid = CreateGUID
set viewUpdate = database.OpenView ("UPDATE Component SET ComponentId='" & componentGuid & "' WHERE Component='" & componentName & "'")
viewUpdate.Execute
set record = view.Fetch
loop
set viewUpdate = database.OpenView ("UPDATE Property SET Value='" & CreateGUID & "' WHERE Property='ProductCode'")
viewUpdate.Execute
set viewUpdate = database.OpenView ("UPDATE Property SET Value='" & CreateGUID & "' WHERE Property='UpgradeCode'")
viewUpdate.Execute
database.Commit
Set database = Nothing
Set installer = Nothing
Set view = Nothing
Ein ähnlicher Ansatz kann mit PowerShell ausgeführt werden. Beachten Sie, dass der Parameter $Path definiert ist und sein Wert extern von RayPack gesetzt wird, bevor das PowerShell-Skript-Engine aufgerufen wird. In diesem Beispiel wird die MSI-COM-Schnittstelle zur Aktualisierung des MSI verwendet, und ihre Methoden werden über Reflection aufgerufen.
param(
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[String]$Path
)
Process {
try {
# Read property from MSI database
$OpenReadOnly = 0
$OpenTransact = 1
$WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer
$MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $WindowsInstaller, @($Path, $OpenTransact))
$Query = "SELECT Component FROM Component"
$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)
while ($Record -ne $null)
{
$componentName = $Record.GetType().InvokeMember("StringData", "GetProperty", $null, $Record, 1)
$newGuid = [guid]::NewGuid().ToString("B").ToUpper()
$updateQuery = "UPDATE Component SET ComponentId='" + $newGuid + "' WHERE Component='" + $componentName + "'"
$viewUpdate = $MSIDatabase.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $MSIDatabase, ($updateQuery))
$viewUpdate.GetType().InvokeMember("Execute", "InvokeMethod", $null, $viewUpdate, $null)
$Record = $View.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $View, $null)
$viewUpdate.GetType().InvokeMember("Close", "InvokeMethod", $null, $viewUpdate, $null)
}
$viewUpdate = $MSIDatabase.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $MSIDatabase, ("UPDATE Property SET Value='" + [guid]::NewGuid().ToString("B").ToUpper() + "' WHERE Property='ProductCode'"))
$viewUpdate.GetType().InvokeMember("Execute", "InvokeMethod", $null, $viewUpdate, $null)
$viewUpdate = $MSIDatabase.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $MSIDatabase, ("UPDATE Property SET Value='" + [guid]::NewGuid().ToString("B").ToUpper() + "' WHERE Property='UpgradeCode'"))
$viewUpdate.GetType().InvokeMember("Execute", "InvokeMethod", $null, $viewUpdate, $null)
# Commit database and close view
$MSIDatabase.GetType().InvokeMember("Commit", "InvokeMethod", $null, $MSIDatabase, $null)
$View.GetType().InvokeMember("Close", "InvokeMethod", $null, $View, $null)
$viewUpdate.GetType().InvokeMember("Close", "InvokeMethod", $null, $viewUpdate, $null)
$MSIDatabase = $null
$View = $null
$viewUpdate = $null
}
catch {
Write-Warning -Message $_.Exception.Message ; break
}
}
End {
# Run garbage collection and release ComObject
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($WindowsInstaller)
[System.GC]::Collect()
}