Laden von 64Bit DLLs in 32Bit Anwendung mit Reflection


Da könnte man sich fragen wozu man sowas braucht. Aber es gibt immer einen guten Grund und in meinem Fall ging es darum, das ich in einem T4 Template 64Bit DLLs laden musste und diese nach Benutzerdefinierten Attributen zu durchsuchen um dann eine passende Ausgabe zu erstellen. Leider gibt es die Konsolenanwendung mit der VisualStudio die T4 Templates ausführt nur als 32 Bit Anwendung, daher musste eine andere Lösung her und die hieß, laden von 64Bit DLLs in einer 32 Bit Anwendung.

Wenn man also 64Bit DLLs in einer 32Bit Anwendung laden möchte, kann man nicht mehr einfach Assembly.LoadFrom(“FilePathDll”) verwenden, was einem die passende DLL inklusive aller Abhängigkeiten lädt, sondern man muss Assembly.ReflectionOnlyLoadFrom(“FilePathDll”) verwenden. Diese Funktion lädt leider nicht mehr automatisch alle Abhängigkeiten, sondern diese muss man “manuell” nachladen. Dafür stellt .NET einen Eventhandler bereit AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve, an dem man einfach eine passende Funktion registrieren muss, die immer dann aufgerufen wird, wenn eine abhängige Assembly benötigt wird (aufgelöst werden muss) und die Funktion gibt die passende Assembly zurück.

Das Laden von Assemblies und der passende Eventhandler könnten dann z.B. im einfachsten Fall folgendermaßen implementiert werden

 

Ein weiterer “Vorteil” dieser Lösung (zumindest in meinem Fall),  das für alle Dateien die im übergebenen Verzeichnis aufgelöst werden können (NUR NACH NAME keine Versionsnummer), die Assembly Redirects ignoriert werden. Das gilt für alle DLLs die wir im Snippet mit Assembly.ReflectionOnlyLoadFrom(pathWithDll) aufrufen, da wir hier vorher kein ApplyPolicy anwenden. Das Problem bei T4 Templates ist nämlich, das es im Ausführungskontext von Visual Studio ausgeführt wird und damit nicht die Assembly Redirects z.B. aus der web.config oder der app.config im Projekt verwendet, sondern nur die Redirects die in der app.config des Visual Studios angegeben sind.

Ein weiterer und leider auch entscheidender Nachteil an dieser Lösung ist das man eigene Attribute nicht mehr so einfach suchen kann. Denn die Funktion GetCustomAttributes(…) kann nicht verwendet werden, wenn man Assembly.ReflectionOnlyLoadFrom verwendet. Hier steht einem nur die Methode GetCustomAttributesData() zur Verfügung, mit der das Filtern nach eigenen Attributen nicht mehr ganz so komfortabel ist.

Hinweis: Probleme hatte ich außerdem, beim Vergleichen von Typen

assembly.GetCustomAttributesData().Where(p => p.AttributeType == typeof(MeinAttribut))

hier haben die Hashcodes nicht übereingestimmt, obwohl es sich um das gleiche Attribut/Typen handelte, daher habe ich dann nach FullName verglichen und das hat dann funktioniert, hier weiß ich leider nicht woran das liegt.

assembly.GetCustomAttributesData().Where(p => p.AttributeType.FullName == typeof(MeinAttribut).FullName)

Quelle: http://blog.slaks.net/2013-12-25/redirecting-assembly-loads-at-runtime/

Advertisements

Webpack 2 Parameterübergabe and den Buildprozess auf der Konsole


Die meisten Beispiele für Webpack enthalten fertige Konfigurationen die als npm scripte hinterlegt sind. Wenn man aber einen automatisierten Build Prozess verwendet z.B. über den TFS, dann möchte man evtl. einige Variablen von außen an den Buildprozess übergeben. Dazu könnte z.B. die “baseUrl” gehören, wenn die Anwendung nicht im Root des Webserver gehostet wird.

Wenn man z.B. angular-starter installiert und man an den Befehle für “build:prod” noch den Namen der Anwendung übergeben möchte, damit dieser als “baseUrl” gesetzt wird, dann sind dafür die folgenden Schritte notwendig.

Anpassen der package.json, hier müssen zwei “- -“ (doppeldashes) entfernt werden, da sonst die Übergabeparameter nicht gesetzt/erkannt werden.

Vorher:

„build:prod“: „npm run clean:dist && npm run webpack — –config config/webpack.prod.js –progress –profile –bail“,

Nachher:

„build:prod“: „npm run clean:dist && npm run webpack –config config/webpack.prod.js –progress –profile –bail“,

Dann passen wir die “webpack.prod.js” an und prüfen ob der “appname” übergeben wurde und erweitern bei Bedarf die “environment” Variable um den Appnamen

Dann wird noch die “webpack.common.js” angepasst und wenn der “appname” gesetzt ist, ersetzen wir die “baseUrl”

jetzt können wir die passende Kommandozeile aufrufen und den passenden “appnamen” übergeben

npm run build:prod — –env.appname „meineAnwendung“

hier können wir jetzt beliebig viele Parameter übergeben z.B.

npm run build:prod — –env.appname „meineAnwendung“ –env.test “../testFolder”

Wenn wir den Befehl ausführen, dann kann man in der Konsole auch unser “console.log” sehen und man sieht das webpack hier ein JSON Objekt erstellt auf das wir entsprechend in der “webpack.prod.js” über die “env” Variable zugreifen können.  Damit lassen sich beliebige Informationen von außen über eine Buildumgebung noch an webpack übergeben.

CSS IntelliSense in Visual Studio mit Angular und Resharper


Manchmal könnte man sagen “früher” war alles besser. Zumindest war es mit Angular 1 und dem “alten” System in dem man noch direkt JavaScript und Styles eingebunden hat, einfacher im HTML die passende IntelliSense für die CSS Klassen mit der Hilfe von Resharper zu erhalten. Dabei handelte es sich z.B. um Bootstrap und font awesome Klassen.

Wenn man jetzt aber das ganze für Angular 2 möchte, wo alle Styles und Scripts nur noch aus dem node_modules Ordner referenziert werden und das Projekt mit Hilfe von Webpack gebaut wird. Gibt es nicht mehr “einfach” so die IntelliSense für die CSS Klassen.

Auch auf Addons wie Glyphfriend kann man leider nicht zurückgreifen, denn hier muss man die IntelliSense für HTML und CSS im Resharper ausstellen, damit die IntelliSense von Visual Studio greift. Dann hat man aber keine Autovervollständigung von Angular 2 Variablen im HTML Template mehr – was meiner Meinung nach noch wesentlich wichtiger ist.

Hier bleibt meines Wissens aktuell leider nur eine Möglichkeit, man kopiert sich die passenden css Dateien aus dem node_modules Ordner und fügt die Dateien bei sich im Projekt ein und macht noch einen Vermerk das die Dateien nur für die IntelliSense im Projekt enthalten sind aber nicht direkt referenziert werden.

image

wie man sieht hat man dann auch IntelliSense für Bootstrap 4 und die Klassen sind nicht alle unterstrichen (was normalerweise bedeutet das er die Klasse nicht kennt).

image

Auch font awesome geht wieder.

image

Out of Memory Exception beim EF Debuggen im IIS Express


Bisher noch nie vorgekommen, aber es gibt immer ein erstes mal. Heute hatte ich beim Abrufen großer Datenmengen um einen Cache zu befüllen auf einmal eine “Out of Memory” Exception, obwohl mein Visual Studio vom RAM her sehr gut aussah und auch noch genug RAM zur Verfügung stand.

Leider gibt die Fehlermeldung auch nicht mehr her, weder Stacktrace, noch eine Innerexception. Daher erst einmal Google befragt und hier findest sich auch nicht wirklich etwas brauchbares, außer das man wahrscheinlich in einer x86 Anwendung arbeitet oder seinen Code in x86 kompiliert hat. Das war bei mir aber nicht der Fall, ich habe alles mit “AnyCpu” kompiliert.

Leider weiß ich nicht mehr wie ich auf die Idee kam, das es ja auch am IIS Express liegen könnte, denn auf dem Server wo die Anwendung bereits ausgerollt war funktionierte es ja bestens. Und siehe da standardmäßig nimmt VS den IIS Express mit 32Bit und wieder habe ich ein Optionsmenü in VS gesehen was ich bisher noch nicht kannte, in dem man einstellen konnte das VS den IIS Express standardmäßig mit 64Bit startet.

Extras => Optionen => Projekte und Projektmappen => Webprojekte

image

und “schon” war meine “Out of Memory” Exception beim Abrufen von EF Daten in meiner Webanwendung gelöst.

ngModel like two-way-databinding für Komponenten in Angular


Da es sich bei Angular nur noch im Komponenten handelt, ist es hier natürlich auch wichtig wie man Daten an Komponenten weitergibt und auch wieder zurückgeben kann. Dafür gibt es zwei wichtige Dekoratoren “@Input” um Daten an eine Komponenten zu übergeben und “@Output“ um Daten wieder “zurückzugeben”.

Um ein two-way-databinding zu erstellen gibt es mindestens zwei Möglichkeiten.

V1 eine ngModel Like Datenbinding mit “banana in the box” Syntax  [(name)] hier muss in der Childkomponente bei der Namensgebung des Output Dekorators darauf geachtet werden, das dieser am Ende des Namens “Change” stehen hat und der Name selbst dem vom Input Dekorator entspricht.

V2 hier handelt es sich um die “normale” Bindung mit zwei Attributen eine für die Eingabe der Werte mit eckigen Klammern  “[age]” und dann noch um eine Eventbindung mit  runden Klammern “(ageChanged)” um die Daten die aus der Child Komponente zurückgegeben werden auszuwerten. Auch hier werden wieder zwei Dekoratoren benötigt der Input um die Daten an die Komponente zu senden und der Output Dekorator um das Changed Event aufzurufen.

Parent Komponente

Child Komponente

Wie man in beiden Fällen sieht wird in der Child Komponente für den Output Dekorator ein EventEmitter erstellt mit einem bestimmten Typen (bei uns string), der als Rückgabewert im emit für den EventEmitter übergeben werden muss. Bei dem Wert den man an emit übergibt, handelt es sich um den Rückgabewert und dieser muss immer entsprechend “manuell” angestoßen werden, bei uns z.B. über das “keyup” Event unseres Inputs.

Dazu gibt es noch ein funktionierendes Plunkr Beispiel.

Visual Studio 2013/2015 bereitgestellte nodejs Version veraltet


Wenn man Visual Studio installiert wird bereits eine nodejs Version mit installiert, aber nicht im Standardpfad von nodejs. Wenn man also eine aktuelle nodejs Version auf seinem System installiert hat, verwendet diese Visual Studio NICHT automatisch. Meist merkt man dies erst, wenn man versucht npm pakete über Visual Studio zu installieren und in der Ausgabe Fehler erscheinen

npm WARN package.json @ No description
npm WARN package.json @ No repository field.
npm WARN package.json @ No README data

npm ERR! node -v v0.10.31
npm ERR! npm -v 1.4.9
npm ERR! code E404

===npm command completed with exit code 1====

und es werden keine npm Pakete installiert.

Daher ist es notwendig das man nodejs auf dem Rechner selbst installiert und dann in Visual Studio als externes Webtool Einträgt. Sobald man nodejs installiert hat, geht man in Visual Studio auf

“Extras => Optionen => Projekte und Projektmappen => Externe Webtools”

und fügt dort den aktuellen Installationspfad von nodejs hinzu und verschiebt diesen ganz nach oben. Dann muss Visual Studio noch einmal neu gestartet werden und jetzt klappt es auch mit der Installation der npm Pakete.

nodeJsVisualStudioEinstellen

Wenn ein update von npm notwendig ist, dann einfach über die normale Konsole global aktualisieren und in Visual Studio wird dann ebenfalls diese Version verwendet.

npm cheat sheet


Da ich selbst node und  npm noch nicht so lange verwende, muss ich hin und wieder einige für mich wichtige Befehle nachschauen. Daher nachfolgend einige npm Befehle. Da ich die Befehle nur unter Windows verwende, kann ich leider nicht sagen ob es da signifikante Unterschiede zur Linux Version gibt,

Wenn man dann noch hinter einem Proxy sitzt, dann sind die folgenden npm Befehle ebenfalls sehr hilfreich, denn man kann den Proxy explizit für npm angeben.