Problème de chargement d’assembly dans les applications Tizen .NET

Vous pouvez avoir rencontré l’erreur suivante lors du lancement d’une application .NET sur votre appareil Tizen, bien que le fichier DLL spécifié par le message d’erreur soit déjà inclus dans le package d’application (.tpk).

Remarque: Vous pouvez consulter le journal depuis Tizen Log Viewer fenêtre ou dlogutil.

Unhandled exception.System.IO.FileNotFoundException: Could not load file or assembly 'System.Collections.Immutable, Version=1.2.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.File name: 'System.Collections.Immutable, Version=1.2.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'   at TizenAppTemplate.App.OnCreate()   at Tizen.Applications.CoreBackend.UICoreBackend.OnCreateNative(IntPtr data)   at Tizen.Applications.CoreBackend.UICoreBackend.Run(String[] args)   at Tizen.Applications.CoreApplication.Run(String[] args)   at Tizen.Applications.CoreUIApplication.Run(String[] args)   at TizenAppTemplate.App.Main(String[] args)onSigabrt called
tpkroot└── bin    ├── System.Collections.Immutable.dll    ├── System.Runtime.CompilerServices.Unsafe.dll    └── TizenAppTemplate.dll

Cette erreur apparaît lorsque les conditions suivantes sont remplies.

  • Le dossier de candidature contient un ou plusieurs système DLL (System.* ou Tizen.*)
  • Les DLL sont plus récentes que les DLL installées dans l’image du périphérique

Cela se produit généralement lorsque vous référencez un package système à partir de votre application. L’exemple suivant montre un fichier de projet d’application (.csproj) qui contient une telle dépendance.

  Exe  tizen50  

Dans certains cas, le fichier ne fait pas directement référence au package système. Cependant, il peut avoir une telle dépendance récursivement dans son graphique de dépendance.

    

Pourquoi est-ce que je vois cette erreur?

Comme le message d’erreur l’indique, l’erreur résulte d’un AssemblyVersion décalage. Votre application attend une version de DLL système plus récente que celle du périphérique.

Remarque: AssemblyVersion, AssemblyFileVersion, et NuGet PackageVersion sont toutes des propriétés différentes. Par exemple, le package NuGet System.Collections.Immutable 1.7.0 livré avec System.Collections.Immutable.dll de version 1.2.0.5 (AssemblyVersion). Seulement AssemblyVersion est utilisé par le runtime pour vérifier les dépendances DLL.

### Application-owned DLL$ sdb pull /opt/usr/globalapps/org.tizen.example.TizenAppTemplate/bin/System.Collections.Immutable.dll$ dotnet-ildasm System.Collections.Immutable.dll | grep '.ver' | tail -n 1.ver 1:2:0:5### Pre-installed DLL$ sdb pull /usr/share/dotnet.tizen/netcoreapp/System.Collections.Immutable.dll$ dotnet-ildasm System.Collections.Immutable.dll | grep '.ver' | tail -n 1.ver 1:2:0:4

L’implémentation actuelle du lanceur d’applications dans Tizen (qui héberge le runtime .NET) donne toujours la priorité aux DLL trouvées dans l’image système et ignore les DLL appartenant à l’application, même si elles sont plus récentes. Il ignore également toutes les propriétés définies dans l’application .deps.json fichier.

En fait, cette restriction est intentionnellement ajoutée dans Tizen pour des raisons de performances. Le lanceur prélève plusieurs composants d’exécution couramment utilisés par les applications (pour un temps de démarrage réduit) en supposant un ensemble unifié de Assemblages de plateforme sécurisés dans toutes les applications. En raison de la conception fondamentale de CoreCLR, une DLL ne peut pas être chargée dans la valeur par défaut LoadContext s’il existe une DLL du même nom dans Assemblages de plate-forme sécurisés.

Pour plus de détails, vous pouvez lire:

Solutions possibles

Voici quelques solutions que vous pouvez essayer:

  • Supprimer ou rétrograder le package

    La première chose la plus fondamentale que vous pouvez essayer est d’éliminer la dépendance elle-même. Vérifiez si le package est utilisé dans le code et, si possible, réimplémentez le code sans le package. Vous pouvez sinon rétrograder le package de NuGets afin que ses versions de DLL soient compatibles avec tous les appareils cibles. Cependant, cela n’est pas toujours possible si vous ne trouvez pas de version de travail ou si vous ne pouvez pas contrôler les dépendances des bibliothèques utilisées par votre application.

        
  • Manipuler AssemblyResolve événements

    Une autre solution consiste à installer un AssemblyResolve gestionnaire d’événements dans votre application. Ce gestionnaire est appelé lorsque le runtime ne trouve pas de DLL avec une version correspondante. Notez que si une DLL d’application a son image native, l’image native n’est pas automatiquement résolue par Assembly.LoadFile ().

    static void Main(string[] args){    AppDomain.CurrentDomain.AssemblyResolve += (object s, ResolveEventArgs eventArgs) =>    {        var appDir = Path.GetDirectoryName(typeof(App).Assembly.Location);        var assemblyName = eventArgs.Name.Split(',')[0];        var assemblyPath = Path.Combine(appDir, assemblyName + ".dll");        return File.Exists(assemblyPath) ? Assembly.LoadFile(assemblyPath) : null;    };    ...    app.Run(args);}

    Utilisez cette API avec précaution car elle peut provoquer des comportements inattendus, tels qu’un problème d’identité de type (voir Meilleures pratiques pour le chargement de l’assembly). En outre, vous ne pouvez pas utiliser Assembly.Load () (avec un assemblyRef) ou Assembly.LoadFrom (), car ils chargent implicitement un assembly dans la valeur par défaut LoadContext.

    Unhandled exception.System.IO.FileLoadException: Could not load file or assembly 'System.Collections.Immutable, Version=1.2.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. Could not find or load a specific file. (0x80131621)File name: 'System.Collections.Immutable, Version=1.2.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' ---> System.IO.FileLoadException: Could not load file or assembly 'System.Collections.Immutable, Version=1.2.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.   at System.Runtime.Loader.AssemblyLoadContext.InternalLoadFromPath(String assemblyPath, String nativeImagePath)   at System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyPath(String assemblyPath)   at System.Reflection.Assembly.LoadFrom(String assemblyFile)   ...onSigabrt called
  • Utilisez personnalisé AssemblyLoadContext

    Pour les scénarios avancés, vous pouvez créer le vôtre AssemblyLoadContext dans votre application pour isoler les DLL spécifiques. Le suivant CustomAssemblyLoadContext remplacements de classe Load() pour résoudre explicitement les DLL à partir d’un répertoire d’application. Voir Comprendre System.Runtime.Loader.AssemblyLoadContext pour des informations détaillées.

    // Inherit AssemblyLoadContext.private class CustomAssemblyLoadContext : AssemblyLoadContext{    protected override Assembly Load(AssemblyName assemblyName)    {        var appDir = Path.GetDirectoryName(typeof(App).Assembly.Location);        var assemblyPath = Path.Combine(appDir, assemblyName.Name + ".dll");        return File.Exists(assemblyPath) ? LoadFromAssemblyPath(assemblyPath) : null;    }}// In application code,var alc = new CustomAssemblyLoadContext();var assembly = alc.LoadFromAssemblyName(new AssemblyName("SomeLibrary"));assembly.GetType("SomeLibrary.SomeClass").GetMethod("SomeMethod").Invoke(null, null);

L’exemple de code ci-dessus peut ne pas fonctionner si le prefer_dotnet_aot la propriété du manifeste est activée dans tizen-manifest.xml parce que les DLL d’application peuvent avoir leurs images natives dans bin ou bin/.native_image. Dans de tels cas, envisagez d’utiliser ApplicationInfo.ExecutablePath dans l’API TizenFX au lieu de Assembly.Location.

Si vous avez besoin d’aide, veuillez me contacter à swift.kim@samsung.com.

Soyez le premier à commenter

Poster un Commentaire

Votre adresse de messagerie ne sera pas publiée.


*