macOS Mojave in VirtualBox

macOS in einer VM zu installieren ist eine Geschichte voller Missverständnisse. Zumindest auf meiner Seite.

So wäre ich bspw. davon ausgegangen, dass die Hardware – also die “Machine” in “Virtual Machine” – nun ja, “virtuell” sei. Jein, zum Beispiel muss die verwendete Hardware Virtualisierung unterstützen. Geht bei Dir nicht? Pech gehabt. Und der Prozessor muss (!) von Intel sein. Klar, Apple hatte nie AMD-Prozessoren, warum sollte OS X die unterstützen. Mein Missverständnis an der Stelle: Der reale Prozessor wird nicht zu 100% weg-emuliert. Man kann für VirtualBox-VMs zwar ein wenig die CPU spezifizieren, aber trotzdem keine Chance (Stichwort “Stuck at End RandomSeed”).

Also kein VirtualBox. Es gibt eine Anleitung bei heise+ für macOS unter Windows mittels Qemu – die Idee: Windows 10 kann Linux, Linux kann KVM, und dafür gibt’s Skripte um macOS laufen zu lassen (siehe auch). It’s VMs all the way down, und das ist das nächste Problem: Windows 10 kann keine “Nested Virtualization” – für AMD. Also nächstes Missverständnis: Nur, weil Deine Hardware und Deine Software grundsätzlich Virtualisierung können, heißt das noch lange nichts, auch Dein OS muss das können.

Deshalb war ich zwischenzeitlich auf ein MacBook umgestiegen, um dort macOS Mojave (aka 10.14) als VM in Catalina (aka 10.15) zu hosten. Einschub: Warum eigentlich Mojave? Weil das das letzte macOS ist, das 32-Bit-Anwendungen erlaubt, und mein Photoshop CS6 ist eine solche. Einschub Ende. Und auf explizit Apple-Hardware sollte das ja alles gehen, richtig? Nein, und das ist das nächste Missverständnis. Dieselben Probleme, “End RandomSeed”. Ausprobiert mit einem aktuellen VirtualBox 7.

Dieser Artikel hier nun nennt explizit Mojave und VirtualBox 6.1.26, ok, probieren wir das auch noch mal aus. Und siehe da: Es geht!

Nächstes Missverständnis also offenbar: Was mit VirtualBox 6.1.26 geht/ging, geht auch mit VirtualBox 7.x. Bzw. wo für Windows zu viel Hardware an die VM durchgereicht wurde, war es hier zu wenig, denn die Hardware ist halt von Apple 🙂

Aber nun wollte ich es wissen; Gegenprobe: VirtualBox 6.1.26 auf Windows 11. Startet erst gar nicht:

Das soll mit 6.1.28 wohl behoben sein, aber da kommt dieselbe Meldung. Offenbar kann sich das mit anderer installierter Software ins Gehege kommen, bspw. besagtem Subsystem für Linux, was vom Versuch weiter oben noch installiert ist 🙂 Aber auch ohne das geht es nicht, keine Ahnung. Windows halt. Die “Weiteren Informationen” sagen, man solle die Speicherintegritätsprüfung deaktivieren, aber das klingt mir zu kritisch.

Naja, als nächstes probiere ich Big Sur (aka 11, aka 10.16) als Host, denn das ist das letzte macOS, das auf dem Host-MacBook noch läuft.

Update: Apropos “Emulieren”, es gibt hier einen Artikel, wie man x86 auf den aktuellen ARM-Prozessoren von Apple emuliert – habe ich noch nicht ausprobiert.

WiX 4 in Vagrant Maschine installieren

WiX 4 benötigt .NET SDK 6 oder höher. Das .NET SDK per Shell Provisioner zu installieren ist aber nicht ganz offensichtlich, was primär an zweierlei liegt:

MS möchte .NET gerne per winget installieren, was eine AppStore-App ist (heißt das so?), die per Provisioner selbst nach der abenteuerlichen Installation der Dependencies nicht verfügbar ist:

Program ‘winget.exe’ failed to run: The file cannot be accessed by the systemAt C:\tmp\vagrant-shell.ps1:1 char:1

– vermutlich liegt der Grund irgendwo hier, hier oder hier. Keine Ahnung, Windows halt.

Wenn man .NET dann anders installiert, werden die Umgebungsvariablen nicht mit gesetzt m( Na ja, long story short:

Mit dotnet-install.ps1 von hier; zum Einsatz kommt StefanScherer/windows_10. Der Reboot am Ende sollte imho nicht notwendig sein, aber ohne findet er weder wix.exe, noch dotnet.exe. Windows halt.

Windows: “Autoconfiguration IPv4 Address”

Wenn ich (hier in Windows Server 2016) manuell eine statische IP konfiguriere, würde ich davon ausgehen, dass die dann auch verwendet wird. Spoiler: Wird sie nicht. Sie erscheint zwar in ipconfig /all, aber eine weitere “Autoconfiguration IPv4 Address” wird als “(Preferred)” markiert. Das “W” in WTF steht für Windows 🙄

Nun habe ich keine Ahnung, was der Grund (oder der Sinn) davon ist, und es ist mir auch egal. So deaktiviert man es:

mit <id> gleich der Nummer des gewünschten Adapters, wie sie der erste Befehl ausgibt. Eventuell deaktiviere man danach den DHCP Client Service, es sollte aber auch so gehen – und letzteres brachte bei mir andere Probleme mit sich; auf diesen Service verlassen sich doch einige weitere.

Quelle

WiX: Install features options

Das Feature-Element hat einige UI-relevante Attribute, die nicht selbsterklärend sind:

  • Absent='disallow' schaltet “The feature will not be installed” aus – wie man für mandatorische Features das Dropdown insgesamt deaktiviert, weiß ich nicht. Ja, man kann das ganze Feature verstecken (Display='hidden'), aber nicht nur das Dropdown 🤷🏻‍♂️
  • AllowAdvertise='no' schaltet “The feature will be installed when needed” aus
  • “The feature and all of its subfeatures will be installed locally” (in früheren Versionen auch “Entire feature will be installed on local hard drive”) kann laut Internet nicht entfernt werden… andere Quellen legen nahe, dass man das über die Subfeatures und Komponenten steuert, aber ich hatte damit keinen Erfolg.

PowerShell: Zertifikatsprüfung deaktivieren

via. PS, in einem Vagrantfile so zu escapen – man beachte auch die Einrückungen:

HTH

Windows Server Updates hinter einem Proxy

Wenn Windows Server 2016* immer 0% Fortschritt anzeigt, dann kann man davon ausgehen, dass er nix runterlädt. Auch wenn die Liste der noch verfügbaren Updates sich dabei ständig ändert 🙄

Lösung: Offenbar laufen Windows Updates über “WinHTTP“, und selbstverständlich hat WinHTTP seine eigenen Proxy-Einstellungen. Man kann in einer Admin-Shell aber die IE-Einstellungen importieren:

, danach neu starten, klar. Den Rechner oder nur den Service (per PowerShell):

Ein

sollte dann die importierten Proxyeinstellungen zeigen.

*Update: Bei Windows Server 2012 stellt sich das Problem so dar, dass er gar nicht erst Updates findet. Die Lösung ist aber dieselbe.

Windows: %PATH% überschreiben

Angenommen, ich möchte JAVA_HOME setzen und %PATH% um %JAVA_HOME%/bin ergänzen, habe aber keine Adminrechte. JAVA_HOME kann ich setzen, das überschreibt ggf. gesetzte globale Variablen mit demselben Namen. Aber ein User-PATH wird hinter den globalen PATH gehängt, und überschreibt dadurch nix.

Lösung (nur für die CMD!):

  1. Definiere eine .bat, die mit jeder neuen DOS-Box ausgeführt wird:
  2. Füge die entsprechenden Settings ein (hier: setze den globalen %PATH% hinter meinen):

WiX: Upgrade Pitfalls

Art des Upgrades

tl;dr: MajorUpgrade ab der initialen Version!

Folgendes Szenario: Ich baue mit WiX einen MSI-Installer für meine Software. Die Software hat die Version 1.0. Nun möchte ich meine Software auf v1.1 upgraden. Was tun?

WiX bietet mehrere Möglichkeiten, namentlich “Major Upgrades”, “Minor Upgrades”, sowie “Small Updates”, die sich ungefähr so definieren:

  • Small Updates: Quasi ein Patch vorhandener Files, erfordert nicht (zwingend?) eine Änderung der Versionsnummer
  • Minor Upgrade: Aktualisiert bestehende Files ohne die vorhandene Software zu deinstallieren. Kann aber Features oder Komponenten hinzufügen. Erfordert neue (=höhere) Versionsnummer
  • Major Upgrade: “Deinstalliert das Produkt und installiert es neu”, erfordert neue (=höhere) Versionsummer und eine neue Product.Id (Achtung: Product.UpgradeCode “bleibt immer unverändert”)

Liest sich, als würde man meistens ein Minor Upgrade wollen. Internet sagt allerdings das Gegenteil, die Literatur* sieht Major Upgrades als “easier to implement than any other option” an, und last but not least empfiehlt WiX selbst:

When creating an .msi-based installer, you are strongly encouraged to include logic that supports Windows Installer major upgrades.

Was dabei nie so richtig, richtig klar wird (teilweise wird implizit das Gegenteil angedeutet): Beinhaltet nicht bereits Version 1.0 MajorUpgrade (sondern bspw. erst das erste Upgrade), dann funktioniert quasi nichts:

  • v1.1 wird nicht als Update erkannt, sondern parallel installiert!
  • Conditions funktionieren deshalb ebenfalls nicht wie erwartet, es gilt der Pfad wie bei Erstinstallation
  • Downgrades werden nicht verhindert, weil ja beides parallel installiert wird
  • In anderen Worten: Eine Installation, deren Installer nicht MajorUpgrade enthielt, wird von Upgrade/Downgrade-Logik komplett ignoriert!

Warum das dann nicht mandatorisch ist, wird wohl Microsofts Geheimnis bleiben.

*Nick Ramirez, “WiX 3.6: A Developer’s Guide to Windows Installer XML”, Seite 342

“Scheduling”

Per default deinstalliert ein MajorUpgrade die alte Version und installiert dann die neue. Das kann problematisch sein, denn ein Upgrade (engl. für “Verbesserung”, “Aufrüstung”!) sollte ja bspw. Konfigurationsdaten usw. behalten. Da hilft das Scheduling-Attribut:

sorgt dafür, dass bestehende Dateien (und in diesem Fall auch Services) erhalten bleiben. Es wird quasi definiert, wann das bestehende Produkt entfernt werden soll, und afterInstallExecute sagt “nach der Installation des Upgrades” – natürlich wird dann nur noch entfernt, was in v1.1 nicht mehr benötigt wird.

Achtung: Das setzt offenbar die Erkennung außer Kraft, die eine Neuinstallation derselben Version verhindert 🙄

Conditions

Bestimmte Schritte des Installers sollen nur bei Erstinstallation ausgeführt werden (etwa die Konfiguration durch den User, die Installation eines Services, …). Dafür gibt es Conditions, bzw. verschiedene States, auf die man prüfen kann – und das ist ziemlich unübersichtlich. Ich beschränke mich an dieser Stelle auf einen Stackoverflow-Post, der gute, sprechende Aliase definiert:

Update

Ein Kind von Component sollte immer KeyPath="yes" gesetzt bekommen. Selbst, wenn es nur ein Kind gibt, aber insbesondere bei mehreren. Daran wird entscheiden, welches die maßgebliche Datei ist, die vorhanden (und aktuell) sein muss, um “muss (re-)installiert werden” zu entscheiden.

Windows: Iteriere alle Dateien mit derselben Endung