Yes, I know this question looks similar to C# - 'Resources' DLL failing to be loaded as it doesn't exist, but my question is about a DLL that I do not own. That other question involves the author's own DLL that they wrote.
EDIT: after solving the problem, it turns out to have been the exact same scenario. I have self-flagged my own question as a duplicate.
Background
I am writing a C# library that uses the Cosmos DB .NET SDK 3.32.2. Sometimes, this library throws an exception because it could not find Microsoft.Azure.Cosmos.Direct.resources.dll
. This file never existed in the first place; the Cosmos.Direct
DLL ships with en-US
invariant culture resources embedded inside the DLL. Yes, I decompiled it to check - Cosmos.Direct
seems to be part of the SDK that the Cosmos team didn't release as open-source.
To be clear, I do not control Microsoft.Azure.Cosmos.Direct.dll
. That is my dependency. FYI, the NuGet package for Microsoft.Azure.Cosmos
ships with four DLLs, one of them being Microsoft.Azure.Cosmos.Direct.dll
.
FooBar.OurCustomExceptionType: One or more errors occurred. ---> System.AggregateException: One or more errors occurred. ---> System.IO.FileNotFoundException: Could not load file or assembly 'file:///C:\Foo\Bar\Microsoft.Azure.Cosmos.Direct.resources.dll' or one of its dependencies. The system cannot find the file specified.
at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalGetSatelliteAssembly(String name, CultureInfo culture, Version version, Boolean throwOnFileNotFound, StackCrawlMark& stackMark)
at System.Resources.ManifestBasedResourceGroveler.GetSatelliteAssembly(CultureInfo lookForCulture, StackCrawlMark& stackMark)
at System.Resources.ManifestBasedResourceGroveler.GrovelForResourceSet(CultureInfo culture, Dictionary`2 localResourceSets, Boolean tryParents, Boolean createIfNotExists, StackCrawlMark& stackMark)
at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo requestedCulture, Boolean createIfNotExists, Boolean tryParents, StackCrawlMark& stackMark)
at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo culture, Boolean createIfNotExists, Boolean tryParents)
at System.Resources.ResourceManager.GetString(String name, CultureInfo culture)
at Microsoft.Azure.Documents.StoreResult.CreateStoreResult(StoreResponse storeResponse, Exception responseException, Boolean requiresValidLsn, Boolean useLocalLSNBasedHeaders, Uri storePhysicalAddress)
at Microsoft.Azure.Documents.StoreReader.<ReadMultipleReplicasInternalAsync>d__14.MoveNext()
... long stack trace ...
at FooBar.OurCustomCosmosWrapper`1.<GetItemAsync>d__4.MoveNext()
Looking at the stack trace, the library is searching for a "satellite assembly" of resources that never existed, even though the resources are embedded in the DLL.
I have set my own app to use [assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.MainAssembly)]
in AssemblyInfo.cs, but clearly that is not affecting this Cosmos dependency library. It only affects my own FooBar assembly that takes a dependency on the Cosmos SDK.
My question
How do I force my one of my dependency DLLs (in this case, Microsoft.Azure.Cosmos.Direct.dll) to use its own embedded resources instead of trying to find a separate resources.dll
file that doesn't exist?
I bet this could be one of a few problems:
- There is some way to set dependency assembly resource loading in App.config or some other project config file that I don't know about. Remember: I don't need to set this for my own library; I need to set this for one of my dependencies.
- This is a bug in the Cosmos SDK.
- I missed a culture-related setting somewhere when importing the Microsoft.Azure.Cosmos package.