Einleitung Also hab ich mich im Netz auf die Suche gemacht und einige Zeit mit Recherchen verbracht um diese Fragen beantworten zu können und ich bin fündig geworden. Wer in VB 6 ActiveX Dll´s entwickelt, behandelt die unterschiedlichen Versionen über die Binärkompatibilität. Nur, auf die Gefahr hin das ich mich wiederhole, die Binärkompatibilität gibt es so, wie es in VB 6 war, in .Net nicht mehr. Assemblies bilden die grundlegenden Bausteine des .Net Frameworks. Diese können aus ausführbaren Dateien(exe) oder Dynamik Link Lybraries(DLL) bestehen. Ein in VB .Net erstelltes Assembly lässt sich über die Interoperabilität problemlos in anderen .Net Programmiersprachen verwenden, umgekehrt geht's genauso. Assemblies liefern der Common Language Runtime(CLR) Informationen die zum Erkennen der Typimplementierungen notwendig sind. Man kann sich ein Assembly als eine Auflistung von Ressourcen und Typen vorstellen, die eine Einheit bilden und für ein Zusammenwirken konzipiert sind. Ein in VB .NET erstelltes Assembly unterscheidet sich kaum von den Typbibliotheken in älteren VB Versionen. Der einzige unterschied gegenüber Exe und Dll Dateien aus früheren Windows Versionen besteht darin, dass Assemlys in .Net zusätzlich zu den Informationen einer Typbibliothek noch alle anderen wichtigen Informationen zum Ausführen einer Anwendung oder Komponente enthällt und: Ein in .NET erstelltes Assembly wird nicht registriert, so wie es bei den COM Objekten in älteren VB Versionen der Fall war. Dies ist auch nicht nötig, da das ganze über den Global Assembly Cache (GAC) geregelt wird. Dazu gleich mehr. Assemblymanifest
Global Assembly Cache(GAC) Also: globale Assemblies gehören in den GAC installiert und private ins Anwendungsverzeichnis. Nun zum GAC: Die CLR beginnt zur Laufzeit nach dem angeforderten Assembly zuerst im GAC zu suchen ob sich dort ein passendes Assembly befindet, und wenn ja, wird dieses benutzt. Falls dort nicht vorhanden, wird in der Verzeichnissebene der installierten Anwendung gesucht. Es bleibt letztendlich euch überlassen, wie ihr das handhabt, ob ihr euer Assembly global zur Verfügung stellt oder private im Anwendungsverzeichnis. Nur!!! Ein kleines Beispiel: Anwendung A benötigt die Datei, ich nenne diese jetzt mal myDll.dll, der Version 1.0.0.0 Unter VB 6 oder älteren Versionen habt ihr das über die Binärkompatibilät geregelt und die Dll ins System32 kopiert, die ältere Version ersetzt und am COM Server mit regsvr32.exe angemeldet. Bei .Net könnt Ihr das gänzlich vergessen. Es besteht natürlich auch die Gefahr, sich den GAC zu zu müllen. Mal angenommen, eure Anwendung A wird im Funktionsumfang erweitert und die myDll.dll der Version 1.0.0.0 reicht nicht mehr aus. Ihr müsst jetzt eine neue Version dieser Dll erstellen und kompiliert eure Anwendung A gegen die myDll.dll Version 1.1.0.0. Somit habt ihr jetzt eine dritte Version der Dll. Ihr Installiert diese auf dem Zielsystem, wo auch Anwendung B noch läuft. Anwendung A wird jetzt gegen die neue ausgetauscht. Die neue Version der myDll.dll wird in den GAC installiert. Schaut ihn euch an. Anwendung B arbeitet wie gewohnt mit der Version 1.0.0.1. Anwedung A aber jetzt mit der Version 1.1.0.0 der myDll.dll. Was ist jetzt mit der Version 1.0.0.0 ???? Gar nichts! Die bleibt dort einfach liegen und wird nicht genutzt. Man kann sich vorstellen, wie der GAC dann aussieht, wenn man das oft genug macht. Eine Möglichkeit ist, das Ganze ohne den GAC zu erledigen. Das heißt also, eure Dll im Anwendungsverzeichnis zu lassen (Private Object). Die Nachteile habe ich ja ein par zeilen oberhalb schon beschrieben. Aber der Vorteil ist auch, dass ihr gar nichts mehr installieren müsst. Es reicht dann aus, einfach die Dateien im Anwendungsverzeichnis auszutauschen, Exe, Dll usw. Nutzt Ihr den GAC kommt ihr um eine Installationsroutine nicht herum. Ihr müsst nämlich eure Dll´s in den GAC installieren. Ein einfaches Kopieren reicht da nicht aus. Installation in den Global Assembly Cache(GAC) Zunächst benötigt ihr zwei kleine Tools: GACutil.exe und SN.exe C:\Programme\Microsoft SDKs\Windows\v6.0A\bin Der Ordner v6.0A ist natürlich abhängig von eurer Installation des Frameworks. Alternativ zum GACutil.exe gibt es ein frei zur Verfügung stehendes Programm (WinGac), das das GACutil mit einer GUI zur verfügung stellt. Für Sn.exe, also StrongName.exe, hab ich noch nichts gefunden. Kurz, ich hab mir dann selbst eines erstellt: SN.exe braucht man aber nicht unbedingt. Man kann sich über die Projekteigenschaften\Signierung eine neue Schlüsseldatei von VB erstellen lassen. Um das Ganze mal zu testen, erstellen wir ein neues Projekt vom Typ Klassenbibliothek. Wir nutzen einfach mal die Klasse CSystem um eine Guid zu erstellen. Quelltext der Klasse Imports System Public Class CSystem Implements IDisposable ' So ermitteln Sie überflüssige Aufrufe Private disposedValue As Boolean = False ''' <summary> ''' Erzeugt eine System Guid ''' </summary> ''' <returns>String mit der erzeugten Guid</returns> Public Overloads Shared Function CreateSystemGuid() As String Return Guid.NewGuid.ToString End Function ''' <summary> ''' Erzeugt eine System Guid. Hier kann nocht gewählt werden, ''' ob die Sonderzeichen entfernt werden sollen ''' </summary> ''' <param name="StripSlashes"></param> ''' <returns>String mit der erzeugten Guid ''' mit/ohne Sonderzeichen</returns> Public Overloads Shared Function CreateSystemGuid( _ ByVal StripSlashes As Boolean) As String Dim sGuid As String = Guid.NewGuid.ToString Dim sTempGuid As String = "" If (StripSlashes) Then For i As Int32 = 1 To sGuid.Length If Not Mid(sGuid, i, 1) = "{" And _ Not Mid(sGuid, i, 1) = "}" And _ Not Mid(sGuid, i, 1) = "-" Then sTempGuid = sTempGuid & Mid(sGuid, i, 1) End If Next i Return sTempGuid.ToString Else Return sGuid.ToString End If End Function ' IDisposable Protected Overridable Sub Dispose(ByVal disposing As Boolean) If Not Me.disposedValue Then If disposing Then Dispose() ' TODO: Anderen Zustand freigeben (verwaltete Objekte). End If ' TODO: Eigenen Zustand freigeben (nicht verwaltete Objekte). ' TODO: Große Felder auf NULL festlegen. End If Me.disposedValue = True End Sub #Region " IDisposable Support " ' Dieser Code wird von Visual Basic hinzugefügt, um das ' Dispose-Muster richtig zu implementieren. Public Sub Dispose() Implements IDisposable.Dispose ' Ändern Sie diesen Code nicht. Fügen Sie oben in Dispose ' (ByVal disposing As Boolean) Bereinigungscode ein. Dispose(True) GC.SuppressFinalize(Me) End Sub #End Region Public Sub New() MyBase.New() End Sub Protected Overrides Sub Finalize() Dispose(True) MyBase.Finalize() End Sub End Class Assembly Informationen der Dll Die Versionen müsst ihr hier von Hand erhöhen. Für den GAC ist die Assemblyversion wichtig, die Dateiversion nicht. <Assembly: AssemblyVersion("1.0.0.0")> ändert. Der dann so aussieht: <Assembly: AssemblyVersion("1.0.*")> Jedes mal, wenn ihr die Dll erstellen lasst, wird die Assemblyversion automatisch erhöht. Wechselt jetzt in den Projekteigenschaften auf „Signierung“. Setzt ein Häckchen bei „Assembly Signieren“. Wählt in der ComboBox „Neu“ und gebt den Dateinamen an. Alternativ kann man die snk datei mit Kennwort schützen. Bestätigt mit „OK“ Die erstellte Dll befindet sich jetzt im Projektverzeichnis\bin\release. Klickt auf „Install“ und öffnet die Dll. WinGac installiert jetzt die myDll.dll in den GAC und quitiert das Ganze mit: Bestätigt diesen Dialog mit „OK“. Wir wollen sehen, wo unsere Dll abgeblieben ist. Gebt einfach ein “my“ im Textfeld ein, um alle Assemblies, die mit „my“ beginnen, zu filtern. Da ist sie, unsere myDll.dll, die wir gerade in den Cache installiert haben. Mit allen Informationen: Name der Datei, Assemblyversion, Prozessorarchitektur, Kompatibilitätsmodus und der volle Name mit dem PublicKeyToken, den wir mit der Vergabe des starken Namens über die Datei myDll.snk vergeben haben. Zum Vergleich schauen wir nochmal im Cache nach: Ihr findet sie auch dort. Nachdem wir die Dll erstellt haben und in den Cache Installiert haben, wollen wir diese auch nutzen. Startet eure VB IDE, erstellt ein neues Projekt des Typs „Windows Forms Anwendung“ und vergebt den Namen myTestAppA. Speichert das Projekt. Kopiert die Dll aus dem Releaseverzeichnis ins Bin\Debug Verzeichnis unserer Test Anwendung. Ich kopiere die dll deshalb dahin, weil es ja die zwei Möglichkeiten wie vorher beschrieben gibt, die dlls aus dem Cache zu holen oder aus der Anwendungsebene. Ich möchte gleich noch nachweisen können, dass die Exe auch läuft, wenn die Dll nicht mehr im Anwendungsverzeichnis liegt, sondern in den Cache Installiert wurde. Öffnet die Projekteigenschaften der Testanwendung und geht auf „Verweise“. Klickt auf „Hinzufügen“ und wählt „Verweis“ aus. Es öffnet sich folgender Dialog: Sucht im .Net Register nach unserer Dll myDll. Nein!!! Sie befindet sich zwar im Global Cache, wird aber in der Assembly-Liste nicht aufgeführt. Ihr müsst die Dll zur Entwurfszeit vom lokalen Speicherort aus einbinden. Der Global Cache ist nur für die Laufzeit wichtig, nicht für die Entwurfszeit. Sobald euer Programm läuft, sucht die CLR nach dem angeforderten Assembly im Cache. Ihr müsst die Dll immer noch referenzieren, auch wenn sie im GAC ist. Sonst müsste eure Anwendung zur Entwurfszeit immer automatisch alle Assemblies, die im GAC sind, laden, damit sie sofort zur Verfügung stehen. Und wenn ihr euch mal den GAC anschaut, wieviel da drinn ist! Es werden nur die aufgelistet, die vom Vorlagendesigner vorgesehen sind. Natürlich die, die mit der Installation des Frameworks ausgeliefert werden. Auf meinem System sind knapp 500 Assemblies. Mein RAM wird sich freuen, wenn diese alle automatisch geladen werden müssten, damit sie sofort zur Verfügung stehen. Das ist einiges an Speicher, die der Entwicklungsrechner zur Verfügung stellen müsste. Zur Laufzeit sieht das ganze dann anders aus. In der Manifest der Testanwendung steht drin, welche Assembly er laden soll und die CLR lädt diese dann anhand des starken Namen aus dem Cache. Geht auf Register „Durchsuchen“ und wählt die Dll von ihrem Speicherort aus. Mit „OK“ wird der Verweis gesetzt. Wie ihr hier sehen könnt, steht unter TYP „.net“. Weil es ein Assembly ist und kein COM. Wenn ihr Com einbindet steht unter TYP „COM“. Durch das gesetzte Häckchen bei den importierten Namespaces braucht es keine Importsanweisung oder dass der Namespace vorangesetzt wird. Erstellt einen Button auf der Form und gebt folgendes im Klick Event ein: Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click MsgBox(CSystem.CreateSystemGuid()) ' myDll braucht hier nicht vorangesetzt werden ' da der NameSpace beim Verweisvorgang gesetzt werden kann End Sub Startet das Programm und Testet! Das Ergebnis aus der Funktion CSystem.CreateSystemGuid(), welche die Dll beinhaltet und zurück gibt. Erstellt nun eure Anwendung. Jetzt befinden sich folgende Dateien im Debug Verzeichnis inklusive unserer Dll, die wir vorher dort hinein kopiert haben. Startet die myTestAppA.exe. Es folgt das gleicher Ergebnis. Die Anwendung läuft immer noch ohne Fehler. Ja natürlich, das Assembly wurde jetzt auch zur Laufzeit aus dem GAC geladen und nicht aus dem Anwendungsverzeichnis. Eure VB IDE meckert jetzt natürlich, da die Dll, auf die verwiesen wird, fehlt. Kopiert sie wieder zurück. Nun zur neuen Version von myDll.dll ''' <summary> ''' Funktion zeig Hallo Welt die erste ''' </summary> ''' <returns>String</returns> Public Shared Function HelloWorld1() As String Return "Hallo Welt die Erste" End Function Ändert die Assembly Version: Erstellt die Dll und installiert diese mit WinGac in den Global Cache: Jetzt haben wir zwei Dll´s mit gleichem Namen - aber mit unterschiedlichen Versionen.ü> Startet ein neues Projekt mit dem Namen „myTestAppB“. Kopiert die neu erstellte Dll mit der Version 1.0.0.1 ins Debug verzeichnis der Anwendung B. Setzt den Verweis. Erstellt auf der Form1 zwei Buttons. Im Klick Event des Buttons 1 lassen wir uns wieder eine Guid erzeugen. Im Klick Event von Button 2 lassen wir uns dann das "Hallo Welt die Erste" ausgeben. Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click MsgBox(CSystem.CreateSystemGuid) End Sub Private Sub Button2_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button2.Click MsgBox(CSystem.HelloWorld1) End Sub End Class Erstellt nun die Anwendung „myTestAppB“ und testet das ganze mal. Jetzt geht hin und löscht die Dll aus dem Debugverzeichnis der myTestAppA und aus dem Debugverzeichnis myTestAppB. Startet beide Exe. Beide Anwendungen laufen jetzt parallel, wobei beide Anwendung auf die myDll verweisen, jedoch unterschiedlicher Assemblyversionen. Fazit Das Gegenteil könnt ihr testen, indem ihr die beiden Dll´s aus dem GAC deinstalliert, die Version 1.0.0.0 ins Debugverzeichnis von Anwendung A legt und die 1.0.0.1 ins Debugverzeichnis von Anwendung B. Setzt dementsprechend die Verweise. Ihr werdet feststellen, dass im Verweisfenster dann bei Lokaler Kopie „True“ steht. Sie ist ja nicht mehr im GAC installiert und wird nur noch lokal vom Speicherort aufgerufen. Startet beide Exe. Auch diese laufen beide parallel. Wie schon gesagt, es bleibt euch überlassen, wie ihr mit den unterschiedlichen Versionen umgeht oder diese verwaltet, da ja jetzt mehrere Versionen ein- und derselben Datei verwendet werden können und nicht nur eine, wie es bei älteren Versionen und dem System32 der Fall war. Dieser Workshop wurde bereits 22.060 mal aufgerufen.
Anzeige
Diesen und auch alle anderen Workshops finden Sie auch auf unserer aktuellen vb@rchiv Vol.6 Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! - nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten - Symbol-Galerie mit mehr als 3.200 Icons im modernen Look Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m. |
sevISDN 1.0 Überwachung aller eingehender Anrufe! Die DLL erkennt alle über die CAPI-Schnittstelle eingehenden Anrufe und teilt Ihnen sogar mit, aus welchem Ortsbereich der Anruf stammt. Weitere Highlights: Online-Rufident, Erkennung der Anrufbehandlung u.v.m. Tipp des Monats Dezemeber 2024 Roland Wutzke MultiSort im ListView-Control Dieses Beispiel zeigt, wie sich verschiedene Sortierfunktionen für ein ListView Control realisieren lassen. TOP! Unser Nr. 1 Neu! sevDataGrid 3.0 Mehrspaltige Listen, mit oder ohne DB-Anbindung. Autom. Sortierung, Editieren von Spalteninhalten oder das interaktive Hinzufügen von Datenzeilen sind ebenso möglich wie das Erstellen eines Web-Reports. |
|||||||||||||
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein. |