PackDesigner-Skripte erstellen

<< 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.

 

Zugriff auf die temporäre Datenbank

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

 

Aktualisieren der temporären Datenbank

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()

}