From 867721c1c4e084c7c2837459acf3b92f6076b532 Mon Sep 17 00:00:00 2001 From: Genevieve Warren <24882762+gewarren@users.noreply.github.com> Date: Wed, 25 Jun 2025 11:30:14 +0200 Subject: [PATCH 1/3] native library breaking change --- docs/core/compatibility/10.0.md | 1 + .../interop/10.0/native-library-search.md | 75 +++++++++++++++++++ .../interop/10.0/search-assembly-directory.md | 14 ++-- docs/core/compatibility/toc.yml | 2 + 4 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 docs/core/compatibility/interop/10.0/native-library-search.md diff --git a/docs/core/compatibility/10.0.md b/docs/core/compatibility/10.0.md index 5586be97f2b1e..e32ba071a7579 100644 --- a/docs/core/compatibility/10.0.md +++ b/docs/core/compatibility/10.0.md @@ -60,6 +60,7 @@ If you're migrating an app to .NET 10, the breaking changes listed here might af | Title | Type of change | Introduced version | |-------|-------------------|--------------------| +| [Single-file apps no longer look for native libraries in executable directory](interop/10.0/native-library-search.md) | Behavioral change | Preview 6 | | [Specifying DllImportSearchPath.AssemblyDirectory only searches the assembly directory](interop/10.0/search-assembly-directory.md) | Behavioral change | Preview 5 | ## Networking diff --git a/docs/core/compatibility/interop/10.0/native-library-search.md b/docs/core/compatibility/interop/10.0/native-library-search.md new file mode 100644 index 0000000000000..77ddbb5ba3bb4 --- /dev/null +++ b/docs/core/compatibility/interop/10.0/native-library-search.md @@ -0,0 +1,75 @@ +--- +title: "Breaking change - Single-file apps no longer look for native libraries in executable directory" +description: "Learn about the breaking change in .NET 10 where single-file apps no longer look for native libraries in the executable directory." +ms.date: 06/25/2025 +ms.custom: https://github.com/dotnet/docs/issues/46356 +--- + +# Single-file apps no longer look for native libraries in executable directory + +Previously, in [single-file .NET applications](../../../deploying/single-file/overview.md), the directory of the single-file executable was added to the `NATIVE_DLL_SEARCH_DIRECTORIES` property during startup. Consequently, .NET always [probed](../../../dependency-loading/default-probing.md#unmanaged-native-library-probing) the application directory when unmanaged libraries were loaded. On non-Windows with [NativeAOT](../../../deploying/native-aot/index.md), the `rpath` was set to the application directory by default, such that it also always looked for native libraries in the application directory. + +The application directory is no longer added to `NATIVE_DLL_SEARCH_DIRECTORIES` in single-file apps, and the `rpath` setting has been removed in NativeAOT. In both cases, (included in the default behaviour for p/invokes) means the application directory - specifying that flag or leaving the default will look in the application directory. Specifying flags without that value will no longer look in the application directory. + +## Version introduced + +.NET 10 Preview 6 + +## Previous behavior + +Previously, single-file applications always looked in the application directory when loading native libraries. On non-Windows operating systems, NativeAOT applications always looked in the application directory when loading native libraries. + +For example, the following P/Invoke looked *in the application directory* for `lib` and loaded it from there if it existed: + +```csharp +[DllImport("lib") +[DefaultDllImportSearchPaths(DllImportSearchPath.System32)] +static extern void Method() +``` + +## New behavior + +Starting in .NET 10, single-file applications only look in the application directory if the search paths for a native library load indicate including the assembly directory. + +```csharp +// Look in System32 on Windows. +// Search the OS 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 apps. +[DllImport("lib") +[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)] +static extern void Method() + +// Look next to the single-file app (because assembly +// directory is searched by default), then default OS search. +[DllImport("lib") +static extern void Method() +``` + +## Type of breaking change + +This is a [behavioral change](../../categories.md#behavioral-change). + +## Reason for change + +The existing behavior (always look in the application directory even if search paths exclude it) has caused confusion. It's also inconsistent with how the search flags are handled in regular (non-single-file, non-NativeAOT) .NET applications. + +## Recommended action + +If the application/assembly directory is desired for a P/Invoke or native library load and wasn't previously specified, specify . + +If the `RPATH` setting is desired in NativeAOT, explicitly add the corresponding [linker arguments](../../../deploying/native-aot/interop.md#linking) to your project. + +## Affected APIs + +- P/Invokes +- +- + +## See also + +- [Specifying DllImportSearchPath.AssemblyDirectory only searches the assembly directory](search-assembly-directory.md) diff --git a/docs/core/compatibility/interop/10.0/search-assembly-directory.md b/docs/core/compatibility/interop/10.0/search-assembly-directory.md index 27b50dbba4779..ab6a92192c018 100644 --- a/docs/core/compatibility/interop/10.0/search-assembly-directory.md +++ b/docs/core/compatibility/interop/10.0/search-assembly-directory.md @@ -1,6 +1,6 @@ --- title: "Breaking change - Specifying DllImportSearchPath.AssemblyDirectory only searches the assembly directory" -description: "Learn about the breaking change in .NET 10 Preview 5 where specifying DllImportSearchPath.AssemblyDirectory as the only search flag restricts the search to the assembly directory." +description: "Learn about the breaking change in .NET 10 where specifying DllImportSearchPath.AssemblyDirectory as the only search flag restricts the search to the assembly directory." ms.date: 5/9/2025 ai-usage: ai-assisted ms.custom: https://github.com/dotnet/docs/issues/45911 @@ -18,20 +18,18 @@ Starting in .NET 10, if you specify was specified as the only search flag, the runtime searched the assembly directory first. If the library was not found, it fell back to the operating system's default library search behavior. -Example: +For example, with the following code, the runtime would search the assembly directory and then fall back to the OS search paths. ```csharp [DllImport("example.dll", DllImportSearchPath = DllImportSearchPath.AssemblyDirectory)] public static extern void ExampleMethod(); ``` -In this case, the runtime would search the assembly directory and then fall back to the OS search paths. - ## New behavior -When is specified as the only search flag, the runtime searches only in the assembly directory. It does not fall back to the operating system's default library search behavior. +When is specified as the only search flag, the runtime searches only in the assembly directory. It *doesn't* fall back to the operating system's default library search behavior. -The previous code example would now only search the assembly directory for *example.dll*. If the library is not found there, a will be thrown. +The previous code example now only searches the assembly directory for *example.dll*. If the library is not found there, a is thrown. ## Type of breaking change @@ -57,3 +55,7 @@ public static extern void ExampleMethod(); - P/Invokes using - - + +## See also + +- [Single-file apps no longer look for native libraries in executable directory](native-library-search.md) diff --git a/docs/core/compatibility/toc.yml b/docs/core/compatibility/toc.yml index 94ba8201f7ba1..57016222001d3 100644 --- a/docs/core/compatibility/toc.yml +++ b/docs/core/compatibility/toc.yml @@ -54,6 +54,8 @@ items: href: globalization/10.0/version-override.md - name: Interop items: + - name: Single-file apps no longer look for native libraries in executable directory + href: interop/10.0/native-library-search.md - name: Specifying DllImportSearchPath.AssemblyDirectory only searches the assembly directory href: interop/10.0/search-assembly-directory.md - name: Networking From 6fc979476515d6b3def50e651e6091e66701e4d2 Mon Sep 17 00:00:00 2001 From: Genevieve Warren <24882762+gewarren@users.noreply.github.com> Date: Wed, 25 Jun 2025 11:30:36 +0200 Subject: [PATCH 2/3] update description verbiage to remove preview --- .../core/compatibility/cryptography/10.0/x509-publickey-null.md | 2 +- .../compatibility/networking/10.0/default-http-streaming.md | 2 +- docs/core/compatibility/sdk/10.0/default-workload-config.md | 2 +- docs/core/compatibility/sdk/10.0/dotnet-cli-interactive.md | 2 +- docs/core/compatibility/sdk/10.0/http-warnings-to-errors.md | 2 +- .../compatibility/windows-forms/10.0/menuitem-contextmenu.md | 2 +- docs/core/compatibility/wpf/10.0/dynamicresource-crash.md | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/core/compatibility/cryptography/10.0/x509-publickey-null.md b/docs/core/compatibility/cryptography/10.0/x509-publickey-null.md index 6dec01cbf55f6..45fbfc0d3cf73 100644 --- a/docs/core/compatibility/cryptography/10.0/x509-publickey-null.md +++ b/docs/core/compatibility/cryptography/10.0/x509-publickey-null.md @@ -1,6 +1,6 @@ --- title: "Breaking change - X509Certificate and PublicKey key parameters can be null" -description: "Learn about the breaking change in .NET 10 Preview 3 where key parameters in X509Certificate and PublicKey can be null." +description: "Learn about the breaking change in .NET 10 where key parameters in X509Certificate and PublicKey can be null." ms.date: 3/13/2025 ai-usage: ai-assisted ms.custom: https://github.com/dotnet/docs/issues/45325 diff --git a/docs/core/compatibility/networking/10.0/default-http-streaming.md b/docs/core/compatibility/networking/10.0/default-http-streaming.md index 535beb81c5c5b..4661eee91bc8c 100644 --- a/docs/core/compatibility/networking/10.0/default-http-streaming.md +++ b/docs/core/compatibility/networking/10.0/default-http-streaming.md @@ -1,6 +1,6 @@ --- title: "Breaking change - Streaming HTTP responses enabled by default in browser HTTP clients" -description: "Learn about the breaking change in .NET 10 Preview 3 where streaming HTTP responses are enabled by default in browser HTTP clients." +description: "Learn about the breaking change in .NET 10 where streaming HTTP responses are enabled by default in browser HTTP clients." ms.date: 4/7/2025 ai-usage: ai-assisted ms.custom: https://github.com/dotnet/docs/issues/45644 diff --git a/docs/core/compatibility/sdk/10.0/default-workload-config.md b/docs/core/compatibility/sdk/10.0/default-workload-config.md index c4f80231d736b..2d112145d6e14 100644 --- a/docs/core/compatibility/sdk/10.0/default-workload-config.md +++ b/docs/core/compatibility/sdk/10.0/default-workload-config.md @@ -1,6 +1,6 @@ --- title: "Breaking change - Change default workload configuration from 'loose manifests' to 'workload sets' mode" -description: "Learn about the breaking change in .NET 10 Preview 2 where the default workload update mode changed." +description: "Learn about the breaking change in .NET 10 where the default workload update mode changed." ms.date: 3/12/2025 ai-usage: ai-assisted ms.custom: https://github.com/dotnet/docs/issues/45000 diff --git a/docs/core/compatibility/sdk/10.0/dotnet-cli-interactive.md b/docs/core/compatibility/sdk/10.0/dotnet-cli-interactive.md index c30ac95f61027..c90bb8b6962aa 100644 --- a/docs/core/compatibility/sdk/10.0/dotnet-cli-interactive.md +++ b/docs/core/compatibility/sdk/10.0/dotnet-cli-interactive.md @@ -1,6 +1,6 @@ --- title: "Breaking change - .NET CLI `--interactive` defaults to `true` in user scenarios" -description: "Learn about the breaking change in .NET 10 Preview 3 where the --interactive flag defaults to true in user-centric scenarios." +description: "Learn about the breaking change in .NET 10 where the --interactive flag defaults to true in user-centric scenarios." ms.date: 4/3/2025 ai-usage: ai-assisted ms.custom: https://github.com/dotnet/docs/issues/45548 diff --git a/docs/core/compatibility/sdk/10.0/http-warnings-to-errors.md b/docs/core/compatibility/sdk/10.0/http-warnings-to-errors.md index 2878a7d0042d1..680cc917beedf 100644 --- a/docs/core/compatibility/sdk/10.0/http-warnings-to-errors.md +++ b/docs/core/compatibility/sdk/10.0/http-warnings-to-errors.md @@ -1,6 +1,6 @@ --- title: "Breaking change - HTTP warnings promoted to errors in dotnet package list and dotnet package search" -description: "Learn about the breaking change in .NET 10 Preview 4 where HTTP warnings are promoted to errors in dotnet package operations." +description: "Learn about the breaking change in .NET 10 where HTTP warnings are promoted to errors in dotnet package operations." ms.date: 5/9/2025 ai-usage: ai-assisted ms.custom: https://github.com/dotnet/docs/issues/45985 diff --git a/docs/core/compatibility/windows-forms/10.0/menuitem-contextmenu.md b/docs/core/compatibility/windows-forms/10.0/menuitem-contextmenu.md index 55f5989660024..f281914be35ef 100644 --- a/docs/core/compatibility/windows-forms/10.0/menuitem-contextmenu.md +++ b/docs/core/compatibility/windows-forms/10.0/menuitem-contextmenu.md @@ -1,6 +1,6 @@ --- title: "Breaking change - Applications referencing both WPF and WinForms must disambiguate MenuItem and ContextMenu types" -description: "Learn about the breaking change in .NET 10 Preview 1 where applications referencing both WPF and WinForms must disambiguate MenuItem and ContextMenu types." +description: "Learn about the breaking change in .NET 10 where applications referencing both WPF and WinForms must disambiguate MenuItem and ContextMenu types." ms.date: 3/11/2025 ai-usage: ai-assisted ms.custom: https://github.com/dotnet/docs/issues/44738 diff --git a/docs/core/compatibility/wpf/10.0/dynamicresource-crash.md b/docs/core/compatibility/wpf/10.0/dynamicresource-crash.md index 8b63bec5cecf3..fa7f53e45077e 100644 --- a/docs/core/compatibility/wpf/10.0/dynamicresource-crash.md +++ b/docs/core/compatibility/wpf/10.0/dynamicresource-crash.md @@ -1,6 +1,6 @@ --- title: "Breaking change - Incorrect usage of DynamicResource causes application crash" -description: "Learn about the breaking change in .NET 10 Preview 4 where incorrect usage of DynamicResource now causes application crashes." +description: "Learn about the breaking change in .NET 10 where incorrect usage of DynamicResource now causes application crashes." ms.date: 5/12/2025 ai-usage: ai-assisted ms.custom: https://github.com/dotnet/docs/issues/46089 From ba55b453118d36dab17b68454ce714954a91939e Mon Sep 17 00:00:00 2001 From: Genevieve Warren <24882762+gewarren@users.noreply.github.com> Date: Wed, 25 Jun 2025 18:06:37 +0200 Subject: [PATCH 3/3] Touch ups --- docs/core/compatibility/interop/10.0/native-library-search.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/compatibility/interop/10.0/native-library-search.md b/docs/core/compatibility/interop/10.0/native-library-search.md index 77ddbb5ba3bb4..012ce97ee8864 100644 --- a/docs/core/compatibility/interop/10.0/native-library-search.md +++ b/docs/core/compatibility/interop/10.0/native-library-search.md @@ -9,7 +9,7 @@ ms.custom: https://github.com/dotnet/docs/issues/46356 Previously, in [single-file .NET applications](../../../deploying/single-file/overview.md), the directory of the single-file executable was added to the `NATIVE_DLL_SEARCH_DIRECTORIES` property during startup. Consequently, .NET always [probed](../../../dependency-loading/default-probing.md#unmanaged-native-library-probing) the application directory when unmanaged libraries were loaded. On non-Windows with [NativeAOT](../../../deploying/native-aot/index.md), the `rpath` was set to the application directory by default, such that it also always looked for native libraries in the application directory. -The application directory is no longer added to `NATIVE_DLL_SEARCH_DIRECTORIES` in single-file apps, and the `rpath` setting has been removed in NativeAOT. In both cases, (included in the default behaviour for p/invokes) means the application directory - specifying that flag or leaving the default will look in the application directory. Specifying flags without that value will no longer look in the application directory. +The application directory is no longer added to `NATIVE_DLL_SEARCH_DIRECTORIES` in single-file apps, and the `rpath` setting has been removed in NativeAOT. In both cases, (included in the default behaviour for P/Invokes) means the application directory. If you specify that value or leave the default, .NET looks in the application directory. If you specify flags without that value, .NET no longer looks in the application directory. ## Version introduced