PowerShell: Zertifikatsprüfung deaktivieren

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

HTH

Windows Server 2016 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 aber die IE-Einstellungen importieren:

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

Ein

sollte dann die importierten Proxyeinstellungen zeigen.

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.

Missing vcruntime140.dll / vcruntime140d.dll

Deine Visual Studio Anwendung beschwert sich über eine fehlende vcruntime140d.dll? Das “d” steht für debug, bitte als “Release”-Version kompilieren.

Deine Visual Studio Anwendung beschwert sich (nun) über eine fehlende vcruntime140.dll? Dann bitte das aktuelle Microsoft Visual C++ Redistributable Package installieren. Achtung: Ob x64 oder x86 entscheidet sich nicht an der Systemarchitektur, sondern an der Programm-Version! Also: Win32-Anwendung läuft nicht -> x86-Package installieren.

hth

Java: C/C++ über JNI einbinden

Neulich musste ich eine DLL aus Java heraus ansprechen. Zur Wahl stehen JNI und JNA, wobei JNA “nur” ein Wrapper für JNI ist – und bei mir nicht funktioniert hat. In der Theorie ist JNI aber auch nicht schwer, allerdings legt Visual Studio einem mir Steine in den Weg. Ein Grund mehr, bei Java zu bleiben.

Der Java-Teil ist dann auch denkbar einfach:

Diese DllBridge wird dann in eine Headerdatei übersetzt:

Und diese Header-Datei dann in “das” C/C++-Projekt kopiert. An “das” Projekt kommt man wie folgt:

  • Visual Studio installieren; ich habe Visual Studio Community 2017 mit den Standardkomponenten genommen
  • Neues C++/Win32-Projekt anlegen, im Dialog unter “Anwendungseinstellungen” den Anwendungstyp “DLL” wählen
  • Ich habe das Projekt testweise MyDll genannt, die entstehende .dll heißt später genauso

Nachdem man die DllBridge.h in das Projekt kopiert und über Rechtsklick > Include In Project eingebunden hat, kann man ihre Methoden implementieren. O.g. Code erzeugt genau eine Methode Java_DllBridge_hello, siehe DllBridge.h. Deren Implementierung in der .c-Datei:

Alleine die Importe und die korrekte Version von MessageBox herauszufinden, hat sicher eine Stunde gedauert 😡 Oh, Stichwort “Importe”: jni.h wird vom  JDK mitgebracht, die entsprechenden Ordner muss man in VS bekannt machen. Das funktioniert nicht über einen Symlink, sondern über die Projekteinstellungen, indem man unter Configuration Properties > C/C++ > General > Additional Include Directories diese drei Verzeichnisse hinzufügt (Rekursion wäre ja auch zu einfach.):

  • C:\Program Files (x86)\Java\jdk1.8.0_121\include
  • C:\Program Files (x86)\Java\jdk1.8.0_121\include\win32
  • C:\Program Files (x86)\Java\jdk1.8.0_121\include\win32\bridge
    PS Ja: Das ist ein 32-Bit-Java, weil ich letztlich eine 32Bit dll ansprechen will.

Das Ganze sollte jetzt bauen (Build > Build solution, oder STRG+Shift+B) und eine <Projektname>.dll erzeugen, siehe Konsolenausgabe. Der Name der .dll muss dem im initialen Java-Code entsprechen.

Ein Aufruf von

öffnet dann die MessageBox:

Sowie die erwartete Ausgabe auf der Konsole. Für reine C-Anbindung könnte man hier aufhören.

Interessant wird es nun, wenn man langlebigere C++-Objekte von Java aus referenzieren möchte. Idee:

  • Eine Klasse auf Java-Seite, die die dll lädt, sowie die nativen Methoden bereitstellt, und eine Klasse auf C++-Seite, die diese implementiert
  • Die C++-Klasse wird initialisiert, ihren Pointer gibt man in Form einer long an Java zurück (bzw. jlong, vgl. hier), vermutlich ist das die Speicheradresse
  • Über diese long kann Java dann das Objekt referenzieren
  • Braucht man das C++-Objekt nicht mehr, wird es deleted.

(via, längeres Beispiel, Danke Nils!)

Hier sieht das so aus:

Bzw. in C++:

Aufruf in Java dann:

Last but not least die andere Richtung, also C++ nach Java. Die Methode

lässt sich von C++ aus aufrufen über

Weiterführendes dazu hier.

hth

Windows: Welcher Prozess blockiert eine Datei?

Wer mit Bordmitteln herausfinden will, welcher der bsplw. drölf “java.exe”-Prozesse auf eine Datei zugreift, der kann den “Resource Monitor” verwenden – “resmon.exe” im Startmenü:

  • Tab “CPU”
  • Reiter “Processes”: Alle zu untersuchenden Prozesse anwählen
  • Reiter “Associated Handles”: In das Suchfeld den Dateinamen eingeben
  • Prozess finden und direkt von hier aus beenden

via