Quantcast
Jump to content

Assembly Loading Problem in Tizen .NET Applications


STF News
 Share

Recommended Posts

tizen-banner-tizennet.png

You may have encountered the following error when launching a .NET application on your Tizen device, although the DLL file specified by the error message is already included in the application package (.tpk).

Note: You can view the log from the Tizen Log Viewer window or 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

This error appears when the following conditions are met.

  • The application package contains one or more system DLLs (System.* or Tizen.*)
  • The DLLs are newer than DLLs installed in the device image

This usually happens when you reference a system package from your application. The following example shows an application project file (.csproj) that contains such a dependency.

<PropertyGroup>
  <OutputType>Exe</OutputType>
  <TargetFramework>tizen50</TargetFramework>
</PropertyGroup>

<ItemGroup>
  <PackageReference Include="System.Collections.Immutable" Version="1.7.0" />
</ItemGroup>

In some cases, the file doesn't reference the system package directly. However, it may have such a dependency recursively in its dependency graph.

<ItemGroup>
  <!-- This library is dependent on System.Collections.Immutable 1.7.0. -->
  <PackageReference Include="SomeLibrary" Version="1.0.0" />
</ItemGroup>

Why do I see this error?

As the error message implies, the error results from an AssemblyVersion mismatch. Your application expects a newer version of system DLL than the device has.

Note: AssemblyVersion, AssemblyFileVersion, and NuGet PackageVersion are all different properties. For example, the NuGet package System.Collections.Immutable 1.7.0 comes with System.Collections.Immutable.dll of version 1.2.0.5 (AssemblyVersion). Only AssemblyVersion is used by the runtime to verify DLL dependencies.

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

The current implementation of the application launcher in Tizen (which hosts the .NET runtime) always prioritizes DLLs found in the system image and disregards application-owned DLLs, even though they are newer. It also ignores any properties defined in the application's .deps.json file.

In fact, this restriction is intentionally added in Tizen for performance reasons. The launcher prefetches several runtime components commonly used by applications (for reduced startup time) by assuming a unified set of Trusted Platform Assemblies across all applications. Because of the fundamental design of CoreCLR, a DLL cannot be loaded into the default LoadContext if there exists a DLL with the same name in Trusted Platform Assemblies.

For further details, you can read:

Possible solutions

Here are some solutions you can try:

  • Remove or downgrade the package

    The first, most basic thing you can try is to eliminate the dependency itself. Check if the package is being used in the code and, if possible, reimplement the code without the package. You can otherwise downgrade the package from NuGets so that its DLL versions are compatible with all target devices. However, this is not always feasible if you cannot find a working version or you cannot control dependencies of libraries used by your application.

    <ItemGroup>
      <!--<PackageReference Include="System.Collections.Immutable" Version="1.7.0" />-->
      <PackageReference Include="System.Collections.Immutable" Version="1.6.0" />
    </ItemGroup>
    
  • Handle AssemblyResolve events

    Another workaround is to install a custom AssemblyResolve event handler inside your application. This handler is invoked when the runtime cannot find a DLL with a matching version. Note that if an application DLL has its native image, the native image is not automatically resolved by 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);
    }
    

    Use this API with care since it can cause some unexpected behaviors, such as a type identity problem (see Best Practices for Assembly Loading). Also, you cannot use Assembly.Load() (with a full assemblyRef) or Assembly.LoadFrom(), because they implicitly load an assembly into the default 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
    
  • Use custom AssemblyLoadContext

    For advanced scenarios, you can create your own AssemblyLoadContext in your application to isolate any specific DLLs. The following CustomAssemblyLoadContext class overrides Load() method to resolve DLLs explicitly from an application directory. See Understanding System.Runtime.Loader.AssemblyLoadContext for detailed information.

    // 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);
    

The sample code shown above may not work if the prefer_dotnet_aot manifest property is enabled in tizen-manifest.xml file, because application DLLs can have their native images in either bin or bin/.native_image. In such cases, consider using ApplicationInfo.ExecutablePath in TizenFX API instead of Assembly.Location.

If you need help, please contact me at swift.[email protected]

View the full blog at its source

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...