Zum Inhalt springen

Java msi mit Powershell extrahieren

Eine wesentlicher Aspekt der alltäglichen Netzwerkverwaltung besteht im Patchen von Anwendungen, wofür je nach Anzahl der zu betreuenden Clients und Applikationen unterschiedliche Techniken und Software zum Einsatz kommen.

Ich habe im Laufe der letzten Jahre unterschiedliche Ansätze ausprobiert und verwende mittlerweile eine Kombination aus WSUS für alle Microsoft Patches und dem WSUS Package Publisher, der es ermöglicht Paktete von Drittanbietern per WSUS zu verteilen. Wie der Package Publisher konfiguriert wird bzw. wie man die Patches verteilt, werde ich in einer späteren Anleitung beschreiben.

Eine im Schulbetrieb häufig verwendete Software ist das Java Runtime Environment von Oracle, das z.B. für die Mathematiksoftware GeoGebra benötigt wird. Java stand in den letzten Jahren häufig als unsichere Anwendung in der Kritik und die Fachpresse riet von der Verwendung in Unternehmen ab. Wie es um die Qualität der Software bestellt ist, möchte ich nicht bewerten, aber ich bin überzeugt, dass es wesentlich ist, das JRE zumindest bestmöglich aktuell zu halten.

Egal welche Updatestrategie man wählt, in den meisten Fällen benötigt man die Software im msi-Format. Da Oracle das JRE leider nur als exe-Datei zur Verfügung stellt, sind ein paar einfache Schritte nötig, um daraus die msi-Datei zur Weiterverteilung zu gewinnen.

Die folgende Anleitung beschreibt nicht nur den manuellen Ansatz, wie man von der exe-Datei zur msi-Datei gelangt, sondern stellt auch eine Möglichkeit zur Automatisierung per Powershell vor. Grundlage für beide Methoden ist, dass Sie über eine Installationsdatei verfügen. Dazu navigiert man zur Java Homepage und lädt das zur Architektur passende „Windows Offline“ Paket herunter.

  1.  Manuelles Vorgehen

Verfügt der Benutzer über die entsprechenden Rechte, kann die Installation durch Doppelklick auf die Installationsdatei gestartet werden und der Installationsdialog erscheint. Wichtig ist, hier NICHT auf den Installieren-Button zu klicken!

Der nächste Schritt erfolgt im Windows Explorer, der mithilfe der Shortcuts Windowstaste + E gestartet werden kann. In die Adressleiste des Explorers gibt man den Pfad zum Appdata-Folder ein, oder man nutzt die Systemvariable %appdata% und bestätigt mit der Enter-Taste.

Der Windows Explorer öffnet nun automatisch den Appdata/Roaming Pfad des Benutzers, der in diesem Zusammenhang nicht benötigt wird.  Wechseln Sie jetzt in das übergeordnete Verzeichnis Appdata und dann in den Ordner LocalLow. Wurde die Installation erfolgreich gestartet, findet man hier einen Ordner mit dem Namen Oracle, den der Java Installer nutzt. Hier wechselt man in den Ordner Java und dann einen versionsabhängigen Ordner, in meinem Fall jre1.8.0_181, der die gesuchte msi-Datei enthält.

Die enthaltene msi-Datei kann nun zur Weiterverteilung kopiert und die Installation fortgesetzt oder abgebrochen werden. Bricht man die Installation ab, bleiben die Java Ordner im Appdata-Verzeichnis erhalten und müssen manuell entfernt werden.

  1. Geskriptete Lösung

Als begeisterter Powershell Nutzer versuche ich repetitive Arbeiten möglichst per Skript zu erledigen und hierfür ein einfaches Skript geschrieben, das Sie weiter unten finden. Die einzelnen Zeilen sind kommentiert und können natürlich nach Belieben verändert werden.

<#
.SYNOPSIS 
Das Skript extrahiert die msi-Datei aus einer Java Installation. 
.NOTES
Author: Martin Stolzlechner
Creation Date: 17. August 2018
Purpose/Change: Java Deployment  
.COMPONENT Das Skript benötigt NET, getestet auf Windows Server 2016 &amp; Windows 10 (PS 5.1, August 2018) Das Skript muss mit Administratorenrechten ausgeführt werden.
.LINK schulnetz.borg3.at
#>

### Windows Forms verwenden

Add-Type -AssemblyName System.Windows.Forms 

### Fenstertitel ändern $host.ui.RawUI.WindowTitle = "Java exe to msi" 

### Skript muss als Administrator ausgeführt werden 

#Requires -RunAsAdministrator 

### Errorpreference festlegen 

$ErrorActionPreference = "SilentlyContinue" 

### Nachfrage, ob neue Java Version bereits hernutergeladen wurde 

Write-Host "Abfrage, ob bereits eine Java Installationsdatei zur Bearbeitung Verfügbar ist." 

$AuswahlDialog_exe = [System.Windows.Forms.MessageBox]::Show("Haben Sie bereits eine Java Installationsdatei, die bearbeitet werden soll?","Erstabfrage","YesNoCancel","Question","Button1","DefaultDesktopOnly")

if ($AuswahlDialog_exe -eq "Yes") {

Function Get-File($initialDirectory) {

[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null          $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog     
$OpenFileDialog.initialDirectory = $initialDirectory     
$OpenFileDialog.filter = "exe (*.exe)| *.exe"     
$OpenFileDialog.title = "Java Installationsdatei zum Bearbeiten auswählen."     $OpenFileDialog.ShowDialog() | Out-Null     
$OpenFileDialog.filename  } 

$Java_exe = Get-File}           

elseif ($AuswahlDialog_exe -eq "No") { 

### Wenn nicht, Browser öffnen 

Start https://java.com/de/download/manual.jsp 
Write-Host "Laden Sie eine Windows-Offline Java Installationsdatei von der Java Homepage herunter." $Java_Download = [System.Windows.Forms.MessageBox]::Show("Laden Sie eine Windows-Offline Java Installationsdatei zur weiteren Bearbeitung herunter. Wenn der Download erfolgt ist, klicken Sie Ok.","Java Download","OkCancel","Exclamation","Button1","DefaultDesktopOnly") 

if ($Java_Download -eq "Cancel") {Exit}}           

else {   
                   
Write-Host "Die Ausführung des Skripts wurde vom Benutzer abgebrochen"           
Exit} 

### Überprüfe, ob im Auswahldialog tatsächlich eine Datei ausgewählt wurde. 

if ([string]::IsNullOrWhiteSpace($Java_exe)) { 

Write-Host "Es wurde keine Datei gewählt." 
[System.Windows.Forms.MessageBox]::Show("Es wurde keine Installationsdatei ausgewählt. Das Skript wird beendet.","Leerer Dateipfad","Ok","Warning","Button1","DefaultDesktopOnly") 
Exit} 

### Speicherort für msi-Datei, falls nicht Speicherort der exe 

$AuswahlDialog_msi = [System.Windows.Forms.MessageBox]::Show("Soll die msi-Datei im Speicherpfad der Installationsdatei gespeichert werden?","Speicherort der msi-Datei","YesNoCancel","Question","Button1","DefaultDesktopOnly")           

if ($AuswahlDialog_msi -eq "Yes") {

$Speicherpfad_msi = ($Java_exe | Split-Path)}           

elseif ($AuswahlDialog_msi -eq "No") {

$browser = New-Object System.Windows.Forms.FolderBrowserDialog 
$browser.Description = "Speicherort für msi-Datei auswählen." 
$browser.rootfolder = "MyComputer" $null = $browser.ShowDialog() 
$Speicherpfad_msi = $browser.SelectedPath }           

else {                     

Write-Host "Die Ausführung des Skripts wurde vom Benutzer abgebrochen"  
Exit}         

### Überprüfen, ob Installaton bereits manuell gestartet wurde 

Write-Host "Überprüfe, ob die Java Installation bereits gestartet wurde und beende diese gegebenenfalls." 

if (Get-Process -Name jre*) {Stop-Process -Name jre* -Force} 

### Installation starten 

if (!(Get-Process -Name jre*)) {Start-Process -FilePath $Java_exe} 

### Untersuche, ob Installationsprozess gestartet wurde 

$timer =  [system.diagnostics.stopwatch]::StartNew()

### Eine Minute auf Starten der Installation warten, ansonsten schließen 

Write-Host "Warte auf Beginn der Installation." 

$Java_Prozesse = (Get-Process -Name jre*).Count 

while ($Java_Prozesse -lt 2) { 

if ($timer.Elapsed.TotalSeconds -ge 60) {

$timer.Stop() 
$timer.Reset()
[System.Windows.Forms.MessageBox]::Show("Die Java Installation konnte nicht gestartet werden.","Java Installation","Ok","Warning","Button1","DefaultDesktopOnly")        
Exit}
   
Start-Sleep -Seconds 5
$Java_Prozesse = (Get-Process -Name jre*).Count} 
$timer.Stop() 
$timer.Reset() 
Write-Host "Die Installation wurde erfolgreich gestartet. Java Fenster nicht schließen!"

### Anzahl der msi-Dateien im Appdata Folder feststellen und bei mehr als einer Warnung ausgeben. 

Write-Host "Untersuche LocalAppdata auf Reste älterer Java Installationen." 

$Java_msi_Anzahl = (Get-ChildItem -Path "$env:UserProfile\AppData\LocalLow\Oracle\Java" -Filter *.msi -Recurse).Count 
if ($Java_msi_Anzahl -gt 1) { 
$AuswahlDialog_mehrere_MSIs = [System.Windows.Forms.MessageBox]::Show("Es wurden mehr als eine Java msi-Datei gefunden. Wenn Sie den Prozess fortsetzen, wird die neueste msi-Datei ausgewählt. Wollen Sie fortsetzen?","Mehrere msi-Dateien im Appdata-Folder","YesNo","Question","Button1","DefaultDesktopOnly")
if ($AuswahlDialog_mehrere_MSIs -eq "No") { Write-Host "Die Ausführung des Skripts wurde vom Benutzer abgebrochen" 
if (Get-Process -Name jre*) {Stop-Process -Name jre* -Force} Exit} } 

### msi-Datei kopieren

Write-Host "Kopiere die msi-Datei an den gewählten Speicherort." 
$Java_msi = (Get-ChildItem -Path "$env:UserProfile\AppData\LocalLow\Oracle\Java" -Filter *.msi -Recurse | Sort-Object -Property LastWriteTime -Descending | Select FullName -First 1).Fullname 
$Java_msi_Dateiname = $Java_msi | Split-Path -Leaf 
$Java_msi_Destination = $Speicherpfad_msi + "\" + $Java_msi_Dateiname  
$Java_msi_Version = $Java_msi_Dateiname.Substring(5).TrimEnd(".msi") -replace "_","." Copy-Item -Path $Java_msi -Destination $Java_msi_Destination 

### Abfrage, ob Installationsdatei gelöscht werden soll 

Write-Host "Abfrage, ob Installationsreste gelöscht werden sollen." 

$AuswahlDialog_Prozessende = [System.Windows.Forms.MessageBox]::Show("Die msi-Datei wurde kopiert und die Java-Installation beendet. Sollen die Installationsdateien aus dem Appdata-Ordner entfernt werden? ","Installationsreste entfernen","YesNo") 

### Installationsreste entfernen 

if ($AuswahlDialog_Prozessende -eq "Yes") {

### Java Installation schließen 

Write-Host "Beende Java Installationsprozess." 

Get-Process -Name jre* | Stop-Process -Force Get-ChildItem -Path "$env:UserProfile\AppData\LocalLow\Oracle\Java" | Sort-Object -Property LastWriteTime -Descending | Select -First 1 | Remove-Item -Recurse -Force } 

### Java Installation schließen

Write-Host "Beende Java Installationsprozess." 

Get-Process -Name jre* | Stop-Process -Force 

### Skript beenden 

Write-Host "Java $Java_msi_Version wurde erfolgreich gespeichert." 
Exit

Um das Skript für die Weitergabe besser nutzbar zu machen, habe ich Dateibrowser eingefügt. Verwendet man Hardcoding der Pfade, lässt sich der Vorgang natürlich deutlich beschleunigen. Das Skript wurde auf Windows 10 (1803) und MS Server 2016 getestet, sowohl in Powershell, als auch der Powershell ISE. Da ich gerade keine andere Installation zur Verfügung habe, konnte ich die Abwärtskompatibilität nicht überprüfen.

Anmerkungen sind herzlich willkommen und das Skript darf gerne – auf eigene Verantwortung – verwendet und kopiert werden!

Mit freundlichen Grüßen,

Martin Stolzlechner

Sei der Erste der einen Kommentar abgibt

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

5 × drei =