Moin zusammen,
Ich brauche mal eure Schwarmintelligenz.
Vorab: diese Applikation wird unter macOS (13.0.0 mit VSMac 17.5.0) und Linux entwickelt; um Windows kümmere ich mich später.
In meiner Applikation lade ich diverse Module dynamisch; alle Komponenten der Applikationen können immer ausgetauscht werden.
D.h.: zur Laufzeit können mit Befehl (oder direkt beim Programmstart) diverse Module geladen werden.
Alle Module (Plugins) werden als .dll gebaut.
Nun habe ich mit einem Modul das Problem, dass eines meiner Plugins ein NuGet-Paket als Dependency hat; speziell
Visual Studio kopiert aus - mir unerklärlichen - Gründen dieses Paket nicht zum Build-Ordner. Also habe ich die DLL in meinem
Ich bin mir ziemlich sicher dass ich die richtige Datei erwischt habe, denn in der
Der Ordner sieht folgendermaßen aus:
Spoiler anzeigen
Wenn ich Plugins lade, kann es nun natürlich immer passieren, dass nicht immer alle Dateipfade korrekt angegeben werden und die Anwendung nur in ihrem eigenen Ordner und der
dafür habe ich folgendes Event abboniert:
Spoiler anzeigen
Hier nochmal der Code, der tatsächlich die Module in die Applikation lädt:
Spoiler anzeigen
Alles erstmal alles kein Hexenwerk.
Nun aber zu dem Fehler:
Die Fehlermeldung sagt, dass eine "strongly-named assembly" benötigt wird. Wenn ich mich nicht täusche, bedeutet das, dass der PublicKeyToken belegt sein muss.
Hatte jemand schon mal diesen Fehler und kann mich in die richtige Richtung lenken? Stackoverflow war bisher noch keine großartige Hilfe.
Ich brauche mal eure Schwarmintelligenz.
Vorab: diese Applikation wird unter macOS (13.0.0 mit VSMac 17.5.0) und Linux entwickelt; um Windows kümmere ich mich später.
In meiner Applikation lade ich diverse Module dynamisch; alle Komponenten der Applikationen können immer ausgetauscht werden.
D.h.: zur Laufzeit können mit Befehl (oder direkt beim Programmstart) diverse Module geladen werden.
Alle Module (Plugins) werden als .dll gebaut.
Nun habe ich mit einem Modul das Problem, dass eines meiner Plugins ein NuGet-Paket als Dependency hat; speziell
System.Data.SqlClient
.Visual Studio kopiert aus - mir unerklärlichen - Gründen dieses Paket nicht zum Build-Ordner. Also habe ich die DLL in meinem
.nuget
-Ordner gesucht und händisch an die richtige Stelle kopiert.Ich bin mir ziemlich sicher dass ich die richtige Datei erwischt habe, denn in der
*.deps.json
steht eindeutig:Quellcode
- "System.Data.SqlClient/4.8.5": {
- "dependencies": {
- "Microsoft.Win32.Registry": "4.7.0",
- "System.Security.Principal.Windows": "4.7.0",
- "runtime.native.System.Data.SqlClient.sni": "4.7.0"
- },
- "runtime": {
- "lib/netcoreapp2.1/System.Data.SqlClient.dll": {
- "assemblyVersion": "4.6.1.5",
- "fileVersion": "4.700.22.51706"
- }
- },
- "runtimeTargets": {
- "runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": { # [b]diese Datei[/b] habe ich kopiert
- "rid": "unix",
- "assetType": "runtime",
- "assemblyVersion": "4.6.1.5",
- "fileVersion": "4.700.22.51706"
- },
- "runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": {
- "rid": "win",
- "assetType": "runtime",
- "assemblyVersion": "4.6.1.5",
- "fileVersion": "4.700.22.51706"
- }
- }
- },
Der Ordner sieht folgendermaßen aus:
Quellcode
- total 560
- drwxr-xr-x 6 simon staff 192B Feb 25 20:29 .
- drwxr-xr-x 19 simon staff 608B Feb 24 00:39 ..
- -rw-r--r-- 1 simon staff 19K Feb 24 14:55 Hermod.EmailImport.deps.json
- -rw-r--r-- 1 simon staff 24K Feb 24 14:55 Hermod.EmailImport.dll
- -rw-r--r-- 1 simon staff 14K Feb 24 14:55 Hermod.EmailImport.pdb
- -rwxr--r-- 1 simon staff 218K Feb 25 18:35 System.Data.SqlClient.dll
Wenn ich Plugins lade, kann es nun natürlich immer passieren, dass nicht immer alle Dateipfade korrekt angegeben werden und die Anwendung nur in ihrem eigenen Ordner und der
$PATH
Variable schaut;dafür habe ich folgendes Event abboniert:
C#-Quellcode
-
- private Assembly? CurrentDomain_AssemblyResolve(object? sender, ResolveEventArgs args) {
- AppLogger?.Warning("Failed to resolve assembly {argname}", args.Name);
- var loadedAssembly = AppDomain.CurrentDomain.GetAssemblies()?.Where(x => x.FullName == args.Name)?.FirstOrDefault();
- if (loadedAssembly is not null) {
- return loadedAssembly;
- }
- var folderPath = Path.GetDirectoryName(args.RequestingAssembly?.Location);
- var asmName = new AssemblyName(args.Name);
- if (folderPath is null || asmName.Name is null) {
- AppLogger?.Error("Could not find assembly in {location}", folderPath);
- return default;
- }
- var rawPath = Path.Combine(folderPath, asmName.Name);
- var asmPath = rawPath + ".dll";
- if (!File.Exists(asmPath)) {
- AppLogger?.Warning("Could not find {asmPath}! Is it an executable?", asmPath);
- asmPath = rawPath + ".exe";
- if (!File.Exists(asmPath)) {
- AppLogger?.Warning("Could not find {asmPath}!", asmPath);
- return default;
- }
- }
- return Assembly.LoadFrom(asmPath);
- }
Hier nochmal der Code, der tatsächlich die Module in die Applikation lädt:
C#-Quellcode
-
- internal void RegisterPlugin(ref Assembly assembly, Type type) {
- if (!LoadedAssemblies.ContainsKey(assembly)) {
- AppLogger?.Debug($"Plugin assembly seems to be new; registering { assembly.GetName().FullName } for the first time!");
- LoadedAssemblies.Add(assembly, new Dictionary<Type, IPlugin>());
- } else if (LoadedAssemblies[assembly].ContainsKey(type)) {
- AppLogger?.Error($"The plugin { type.Name } has already been loaded as a plugin! Silently ignoring...");
- return;
- }
- try {
- var plugin = Activator.CreateInstance(type) as IPlugin;
- if (plugin is null) {
- throw new PluginLoadException(type.Name);
- }
- LoadedAssemblies[assembly].Add(type, plugin);
- var pluginDelegator = new PluginDelegator(plugin);
- PluginDelegators.Add(pluginDelegator);
- plugin = LoadedAssemblies[assembly][type];
- plugin.OnLoad(pluginDelegator);
- LastRegisteredPlugin = plugin;
- AppLogger?.Information($"Loaded plugin { plugin.PluginName } { plugin.PluginVersion.ToString() }");
- } catch (Exception ex) {
- AppLogger?.Error("Failed to load plugin from assembly!");
- AppLogger?.Error($"Error: { ex.Message }");
- throw;
- }
- }
- internal bool ContainsPlugins(Assembly assembly, out List<Type> pluginTypes) {
- pluginTypes = new List<Type>();
- foreach (var type in assembly.GetTypes()) {
- var isSubclass = type.IsSubclassOf(typeof(IPlugin)) || type.IsSubclassOf(typeof(Plugin));
- var attribute = type.GetCustomAttribute<PluginAttribute>();
- if (isSubclass && attribute is not null) {
- pluginTypes.Add(type);
- }
- }
- return pluginTypes.Count > 0;
- }
Alles erstmal alles kein Hexenwerk.
Nun aber zu dem Fehler:
Quellcode
-
- [21:50:06 INF] Attempting to load /Users/simon/Projects/Hermod/Plugins/Hermod.EmailImport.dll...
- [21:50:06 INF] Loading assembly...
- [21:50:06 WRN] Failed to resolve assembly System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
- [21:50:06 WRN] Failed to resolve assembly System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
- [21:50:06 WRN] Failed to resolve assembly System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
- Failed to load one or more plugins!
- [21:50:06 ERR] Command execution failed! Command: load-plugin ../Plugins/Hermod.EmailImport.dll
- System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types.
- Could not load file or assembly 'System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. A strongly-named assembly is required. (0x80131044)
- Could not load file or assembly 'System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. A strongly-named assembly is required. (0x80131044)
- Could not load file or assembly 'System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. A strongly-named assembly is required. (0x80131044)
- at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
- at System.Reflection.Assembly.GetTypes()
- at Hermod.PluginFramework.PluginRegistry.ContainsPlugins(Assembly assembly, List`1& pluginTypes) in /Users/simon/Projects/Hermod/Hermod/PluginFramework/PluginRegistry.cs:line 119
- at Hermod.PluginFramework.PluginRegistry.LoadPlugin(FileInfo pluginFile) in /Users/simon/Projects/Hermod/Hermod/PluginFramework/PluginRegistry.cs:line 83
- at Hermod.Hermod.HandleLoadPlugin(String[] args) in /Users/simon/Projects/Hermod/Hermod/Hermod.Commands.cs:line 111
- System.IO.FileLoadException: Could not load file or assembly 'System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. A strongly-named assembly is required. (0x80131044)
- File name: 'System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
- ---> System.IO.FileLoadException: A strongly-named assembly is required. (0x80131044)
- System.IO.FileLoadException: Could not load file or assembly 'System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. A strongly-named assembly is required. (0x80131044)
- File name: 'System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
- ---> System.IO.FileLoadException: A strongly-named assembly is required. (0x80131044)
- System.IO.FileLoadException: Could not load file or assembly 'System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. A strongly-named assembly is required. (0x80131044)
- File name: 'System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
- ---> System.IO.FileLoadException: A strongly-named assembly is required. (0x80131044)
Die Fehlermeldung sagt, dass eine "strongly-named assembly" benötigt wird. Wenn ich mich nicht täusche, bedeutet das, dass der PublicKeyToken belegt sein muss.
Hatte jemand schon mal diesen Fehler und kann mich in die richtige Richtung lenken? Stackoverflow war bisher noch keine großartige Hilfe.
Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)
Meine Firma: Procyon Systems
Meine Privatwebseite: SimonC.eu
Bitte nicht wundern, wenn meine Aktivitäten im Forum etwas langsamer sind, ich baue gerade mein Nebengewerbe zum Vollgewerbe aus.
Ich versuche auf euch zurückzukommen
Meine Firma: Procyon Systems
Meine Privatwebseite: SimonC.eu
Bitte nicht wundern, wenn meine Aktivitäten im Forum etwas langsamer sind, ich baue gerade mein Nebengewerbe zum Vollgewerbe aus.
Ich versuche auf euch zurückzukommen