NuGet-Paket (DLL) kann nicht dynamisch geladen werden: strongly-named assembly is required

  • C#

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von siycah.

    NuGet-Paket (DLL) kann nicht dynamisch geladen werden: strongly-named assembly is required

    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 ​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

    1. ​"System.Data.SqlClient/4.8.5": {
    2. "dependencies": {
    3. "Microsoft.Win32.Registry": "4.7.0",
    4. "System.Security.Principal.Windows": "4.7.0",
    5. "runtime.native.System.Data.SqlClient.sni": "4.7.0"
    6. },
    7. "runtime": {
    8. "lib/netcoreapp2.1/System.Data.SqlClient.dll": {
    9. "assemblyVersion": "4.6.1.5",
    10. "fileVersion": "4.700.22.51706"
    11. }
    12. },
    13. "runtimeTargets": {
    14. "runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": { # [b]diese Datei[/b] habe ich kopiert
    15. "rid": "unix",
    16. "assetType": "runtime",
    17. "assemblyVersion": "4.6.1.5",
    18. "fileVersion": "4.700.22.51706"
    19. },
    20. "runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": {
    21. "rid": "win",
    22. "assetType": "runtime",
    23. "assemblyVersion": "4.6.1.5",
    24. "fileVersion": "4.700.22.51706"
    25. }
    26. }
    27. },


    Der Ordner sieht folgendermaßen aus:
    Spoiler anzeigen

    Quellcode

    1. ​total 560
    2. drwxr-xr-x 6 simon staff 192B Feb 25 20:29 .
    3. drwxr-xr-x 19 simon staff 608B Feb 24 00:39 ..
    4. -rw-r--r-- 1 simon staff 19K Feb 24 14:55 Hermod.EmailImport.deps.json
    5. -rw-r--r-- 1 simon staff 24K Feb 24 14:55 Hermod.EmailImport.dll
    6. -rw-r--r-- 1 simon staff 14K Feb 24 14:55 Hermod.EmailImport.pdb
    7. -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:

    Spoiler anzeigen

    C#-Quellcode

    1. private Assembly? CurrentDomain_AssemblyResolve(object? sender, ResolveEventArgs args) {
    2. AppLogger?.Warning("Failed to resolve assembly {argname}", args.Name);
    3. var loadedAssembly = AppDomain.CurrentDomain.GetAssemblies()?.Where(x => x.FullName == args.Name)?.FirstOrDefault();
    4. if (loadedAssembly is not null) {
    5. return loadedAssembly;
    6. }
    7. var folderPath = Path.GetDirectoryName(args.RequestingAssembly?.Location);
    8. var asmName = new AssemblyName(args.Name);
    9. if (folderPath is null || asmName.Name is null) {
    10. AppLogger?.Error("Could not find assembly in {location}", folderPath);
    11. return default;
    12. }
    13. var rawPath = Path.Combine(folderPath, asmName.Name);
    14. var asmPath = rawPath + ".dll";
    15. if (!File.Exists(asmPath)) {
    16. AppLogger?.Warning("Could not find {asmPath}! Is it an executable?", asmPath);
    17. asmPath = rawPath + ".exe";
    18. if (!File.Exists(asmPath)) {
    19. AppLogger?.Warning("Could not find {asmPath}!", asmPath);
    20. return default;
    21. }
    22. }
    23. return Assembly.LoadFrom(asmPath);
    24. }


    Hier nochmal der Code, der tatsächlich die Module in die Applikation lädt:
    Spoiler anzeigen

    C#-Quellcode

    1. internal void RegisterPlugin(ref Assembly assembly, Type type) {
    2. if (!LoadedAssemblies.ContainsKey(assembly)) {
    3. AppLogger?.Debug($"Plugin assembly seems to be new; registering { assembly.GetName().FullName } for the first time!");
    4. LoadedAssemblies.Add(assembly, new Dictionary<Type, IPlugin>());
    5. } else if (LoadedAssemblies[assembly].ContainsKey(type)) {
    6. AppLogger?.Error($"The plugin { type.Name } has already been loaded as a plugin! Silently ignoring...");
    7. return;
    8. }
    9. try {
    10. var plugin = Activator.CreateInstance(type) as IPlugin;
    11. if (plugin is null) {
    12. throw new PluginLoadException(type.Name);
    13. }
    14. LoadedAssemblies[assembly].Add(type, plugin);
    15. var pluginDelegator = new PluginDelegator(plugin);
    16. PluginDelegators.Add(pluginDelegator);
    17. plugin = LoadedAssemblies[assembly][type];
    18. plugin.OnLoad(pluginDelegator);
    19. LastRegisteredPlugin = plugin;
    20. AppLogger?.Information($"Loaded plugin { plugin.PluginName } { plugin.PluginVersion.ToString() }");
    21. } catch (Exception ex) {
    22. AppLogger?.Error("Failed to load plugin from assembly!");
    23. AppLogger?.Error($"Error: { ex.Message }");
    24. throw;
    25. }
    26. }
    27. internal bool ContainsPlugins(Assembly assembly, out List<Type> pluginTypes) {
    28. pluginTypes = new List<Type>();
    29. foreach (var type in assembly.GetTypes()) {
    30. var isSubclass = type.IsSubclassOf(typeof(IPlugin)) || type.IsSubclassOf(typeof(Plugin));
    31. var attribute = type.GetCustomAttribute<PluginAttribute>();
    32. if (isSubclass && attribute is not null) {
    33. pluginTypes.Add(type);
    34. }
    35. }
    36. return pluginTypes.Count > 0;
    37. }


    Alles erstmal alles kein Hexenwerk.

    Nun aber zu dem Fehler:

    Quellcode

    1. [21:50:06 INF] Attempting to load /Users/simon/Projects/Hermod/Plugins/Hermod.EmailImport.dll...
    2. [21:50:06 INF] Loading assembly...
    3. [21:50:06 WRN] Failed to resolve assembly System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
    4. [21:50:06 WRN] Failed to resolve assembly System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
    5. [21:50:06 WRN] Failed to resolve assembly System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
    6. Failed to load one or more plugins!
    7. [21:50:06 ERR] Command execution failed! Command: load-plugin ../Plugins/Hermod.EmailImport.dll
    8. System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types.
    9. 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)
    10. 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)
    11. 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)
    12. at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
    13. at System.Reflection.Assembly.GetTypes()
    14. at Hermod.PluginFramework.PluginRegistry.ContainsPlugins(Assembly assembly, List`1& pluginTypes) in /Users/simon/Projects/Hermod/Hermod/PluginFramework/PluginRegistry.cs:line 119
    15. at Hermod.PluginFramework.PluginRegistry.LoadPlugin(FileInfo pluginFile) in /Users/simon/Projects/Hermod/Hermod/PluginFramework/PluginRegistry.cs:line 83
    16. at Hermod.Hermod.HandleLoadPlugin(String[] args) in /Users/simon/Projects/Hermod/Hermod/Hermod.Commands.cs:line 111
    17. 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)
    18. File name: 'System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
    19. ---> System.IO.FileLoadException: A strongly-named assembly is required. (0x80131044)
    20. 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)
    21. File name: 'System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
    22. ---> System.IO.FileLoadException: A strongly-named assembly is required. (0x80131044)
    23. 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)
    24. File name: 'System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
    25. ---> 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 :)
    @siycah Probier mal dies:
    Benenne das NuGet-Paket um in *.ZIP, gehe hinein und kopiere Dir heraus, was Du benötigst, sofern es drinnen ist.
    Möglicherweise fehlt die gewünschte Source.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Bisher habe ich die Dateien direkt aus dem Nuget-Cache kopiert, aber das probiere ich nochmal. Vielleicht ist beim Entpacken des Pakets irgendwas schiefgelaufen.

    Melde mich mit den Ergebnissen zurück!
    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 :)
    @RodFromGermany

    Leider hat das auch nichts gebracht:
    Spoiler anzeigen

    Quellcode

    1. load-plugin ../Plugins/Hermod.EmailImport.dll
    2. [18:39:55 INF] Attempting to load /Users/simon/Projects/Hermod/Plugins/Hermod.EmailImport.dll...
    3. [18:39:55 INF] Loading assembly...
    4. [18:39:55 WRN] Failed to resolve assembly System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
    5. [18:40:02 WRN] Failed to resolve assembly System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
    6. [18:40:02 WRN] Failed to resolve assembly System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
    7. Failed to load one or more plugins!
    8. [18:40:02 ERR] Command execution failed! Command: load-plugin ../Plugins/Hermod.EmailImport.dll
    9. System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types.
    10. 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)
    11. 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)
    12. 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)
    13. at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
    14. at System.Reflection.Assembly.GetTypes()
    15. at Hermod.PluginFramework.PluginRegistry.ContainsPlugins(Assembly assembly, List`1& pluginTypes) in /Users/simon/Projects/Hermod/Hermod/PluginFramework/PluginRegistry.cs:line 119
    16. at Hermod.PluginFramework.PluginRegistry.LoadPlugin(FileInfo pluginFile) in /Users/simon/Projects/Hermod/Hermod/PluginFramework/PluginRegistry.cs:line 83
    17. at Hermod.Hermod.HandleLoadPlugin(String[] args) in /Users/simon/Projects/Hermod/Hermod/Hermod.Commands.cs:line 111
    18. 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)
    19. File name: 'System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
    20. ---> System.IO.FileLoadException: A strongly-named assembly is required. (0x80131044)
    21. 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)
    22. File name: 'System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
    23. ---> System.IO.FileLoadException: A strongly-named assembly is required. (0x80131044)
    24. 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)
    25. File name: 'System.Data.SqlClient, Version=4.6.1.5, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
    26. ---> System.IO.FileLoadException: A strongly-named assembly is required. (0x80131044)





    Ich werde es wohl oder übel mal auf meinem Windowsrechner ausprobieren, ob's da klappt. Vielleicht ist das einfach eine Inkompatibilität...
    Dann heißt es wohl für heute Adieu schnellere Compilezeiten :D

    @RodFromGermany Auf Windows habe ich exakt das gleiche Verhalten. Sehr kurios...
    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 :)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „siycah“ ()

    Thema markiere ich als erledigt. Ich gebe es auf und setze auf andere Mittel.
    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 :)
    Für alle, die's noch interessieren könnte:

    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
    musste ich händisch in die Debug-PropertyGroup im .csproj einfügen.

    Zusätzlich dazu musste ich mein CurrentDomain_AssemblyResolve etwas überarbeiten:

    C#-Quellcode

    1. private Assembly? CurrentDomain_AssemblyResolve(object? sender, ResolveEventArgs args) {
    2. AppLogger?.Warning("Failed to resolve assembly {argname}", args.Name);
    3. var folderPath = Path.GetDirectoryName(args.RequestingAssembly?.Location);
    4. var asmName = new AssemblyName(args.Name);
    5. if (folderPath is null || asmName.Name is null) {
    6. AppLogger?.Error("Could not find assembly in {location}", folderPath);
    7. return default;
    8. }
    9. var rawPath = Path.Combine(folderPath, asmName.Name);
    10. var asmPath = rawPath + ".dll";
    11. if (!File.Exists(asmPath)) {
    12. AppLogger?.Warning("Could not find {asmPath}! Is it an executable?", asmPath);
    13. asmPath = rawPath + ".exe";
    14. if (!File.Exists(asmPath)) {
    15. AppLogger?.Warning("Could not find {asmPath}!", asmPath);
    16. return default;
    17. }
    18. }
    19. AppLogger?.Debug("Resolved assembly @ {asmPath}", asmPath);
    20. return Assembly.LoadFrom(asmPath);
    21. }


    Nun klappt es.


    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 :)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „siycah“ ()