Skip to content

Remove always searching executable directory for native libraries in single-file applications #114717

Closed
@elinor-fung

Description

@elinor-fung

Currently, in single-file .NET applications, the directory of the single-file executable is added to the NATIVE_DLL_SEARCH_DIRECTORIES property during startup. This means that the application directory is always probed when loading unmanaged libraries. This includes for p/invoke library load in the runtime itself, which the developer cannot control via the resolution extension points (DllImportResolver, AssemblyLoadContext.LoadUnmanagedDll).

This means that the following p/invoke will actually look in the application directory first and load lib from there if it exists:

[DllImport("lib")
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
static extern void Method()

In NativeAOT on non-Windows, we set the rpath to the application directory, such that the OS search will always look in the application directory. As a result, the above p/invoke on non-Windows will still look in the application directory.

At the time this was done, self-contained, single-file publish on Windows still had separate native runtime libraries next to the app (such that it would always have the executable location in the search directories anyways). This is no longer the case and the behaviour has caused confusion for developers. NativeAOT behaviour was made to match the regular single-file behaviour.

We should make single-file stop always adding the executable directory and properly handle bundled assembly p/invoke resolution in the runtime to have assembly directory mean next to the bundled app - the option not taken in #42772. NativeAOT should also stop setting the rpath.

This should result in:

// Look in System32 on Windows, OS search on non-Windows
[DllImport("lib")
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
static extern void Method()

// Look next to the single-file app because assembly directory means application directory for single-file
[DllImport("lib")
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
static extern void Method()

// Look next to the single-file app (because we search assembly directory by default), then default OS search
[DllImport("lib")
static extern void Method()

Related:

cc @dotnet/appmodel @dotnet/interop-contrib @GrabYourPitchforks

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-Single-Filebreaking-changeIssue or PR that represents a breaking API or functional change over a prerelease.

    Type

    No type

    Projects

    Status

    No status

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions