I have a project (WPF) that is using a localization assembly that contains all the resource strings.
This localization assembly is given to a translation service who creates a new localized satellite version of this assembly.
The main application is then supposed to be able to import the newly localized dll. That works, but I can't figure out a way to have the new language available without restarting the application.
Is that possible ?
Related
I have a Visual Studio 2015 solution which consists of an executable and a series of DLL projects. All code is managed C# and running on Windows 10 64-bit.
One of the DLLs needs to load a resource specified by the application. The app provides the full manifest resource path and the DLL uses this to load it.
The resources are set as "Embedded Resource" in solution explorer. An example path would be something like "The.DLL.Assembly.subdir.resources.image.png".
The DLL uses the below code to load the resource.
var asm = Assembly.GetExecutingAssembly();
var resStream = asm.GetManifestResourceStream(path);
This works great! Well, that is if the resource in question is stored inside the DLL assembly which is trying to load it. We'd prefer, though, not to have to locate all the resources in this DLL assembly. We'd like the freedom to let the application locate them in any of the projects and just provide the path letting the loading DLL know how to find them. This would allow the app to better organize the resources based on which project "owns" them as opposed to being forced to put them all in the assembly which will actually load them.
Where I'm stuck is being able to load the resource if it lives in another assembly.
I've tried:
GetEntryAssembly(), this returns the executable assembly, but loading the resource fails even with the full path, it appears GetManifestResourceStream() will only look in that assembly
GetEntryAssembly().GetModules(), thinking I could somehow find the other assembly this way, but this returns a single entry, just the exe itself
Any ideas? I'm thinking there must be a way to load an embedded resource which lives in another assembly, but I haven't yet found it.
I am trying to end up being able to include satellite resources with a "Plugin" component, developed in C# and distributed as a DLL. It runs in a "Host" platform, and there are certain restrictions on how I can build and distribute.
I am using Visual Studio, and would like to figure out how to leverage the standard localization features: component-specific resources for my Forms, and other plugin-wide resources. Please bear with some explanation:
The Visual Studio aspect is set up this way: the platform delivers a VS project that is the host project for all of its Plugins. I develop my Plugin by using this project in VS. The Host also has an embedded code editor and other development tools. The Plugin C# code resides in a Host source folder.
Distributing the Plugin requires a compilation from the Host; and then using Host tools to export my plugin files as a DLL. The host compiles the Plugin source against all other default Plugins, then does code obfuscation, and generates stub files for execution, and also manifest-type files. This is all bundled into a Zip file and that's the distribution assembly for the Plugin. When the user installs the Plugin, this is all actually unZipped into the user's Host folder.
I am trying to use Localization features: I cannot simply localize my forms in VS, since the resources are embedded into the VS build output, which is not bundled with the Host Plugin; and is not accessible for me to include at distribution. Also, the Host does not allow me to select the resx files when it does my build for distribution (that might have solved it; but the "Export Plugin" dialog in the Host only allows selecting the C# files that you want to bundle into a distributable Plugin).
I am aware of the ability to bundle resources into a DLL; and I believe that would be my preferred solution if it is possible; and then perhaps I could use the IDE features, then select all my resource files and generate a satellite assembly with the resources. But I cannot figure out how to reference the resources. This would result in satellite resource DLLs placed alongside the MyPlugin.dll (or in culture subfolders) as pictured above. The Host platform allows including dependent DLLs with your Plugin; and they would be unpacked alongside the MyPlugin.dll as pictured.
I have tried simply running AL, and generating a satellite assembly with resources; and placing that file in the Host folder; and also in culture subfolders. However, the resource loading is failing: it does not find the resources.
I have also tried adding the:
[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
in my Plugin source file; and that did not help.
Can anyone figure this out enough to advise me? It may be a namespace problem; which I do not understand well enough to code for. If I have to change the way resources are loaded, I would do that also; but I do not understand enough about the way the resources are managed to know where to begin at this point.
Even given an explanation about what's under the hood with the resources and files, I may figure something out: but I am just looking at the IDE features, and hoping to use them and just find out how to successfully bundle and include the resources along with the Plugin DLL. I don't understand enough about what's under the hood.
... I wound up solving this just by loading resources myself manually ... Explained here:
Building Resource-Only DLL (With al.exe) Is Raising "assembly is built by a runtime newer than the currently loaded runtime"
Im trying to build a tool that loads an assembly as a byte[] at runtime (Assemly.Load(byte[])
It works without any problems, as long as I dont open up a WPF form in the loaded assembly.
Then my assembly resolve event fires up and asks for a file called [my project name].resources and I really dont understand how to produce this file and neither does google.
Is this somekind of wierd bug? Will I have to go back to using Winforms now that I just got aquinted with WPF?
Thanks!
/Erik
According to the Microsoft AppDomain.AssemblyResolve Event documentation:
Beginning with the .NET Framework 4, the ResolveEventHandler event is
raised for all assemblies, including resource assemblies.
Furthermore, the Microsoft ResourceManager Class documentation sheds some light on where the .resources files can be found:
The ResourceManager class retrieves resources from a binary .resources
file that is embedded in an assembly or from a standalone .resources
file. If an app has been localized and localized resources have been
deployed in satellite assemblies, it looks up culture-specific
resources, provides resource fallback when a localized resource does
not exist, and supports resource serialization.
So, depending on whether the assembly has been localised or not, you should return the assembly that contains the .resources file. For non-localised assemblies this is (typically) the assembly itself; for localised assemblies this is the satelite assembly that contains the localised resources.
Although I've never tried it, I believe that the AssemblyResolve event may be raised several times for localised assemblies. Each time you would need to return the satelite assembly that contained the matching localised .resources file, or NULL if the requested locale is not supported.
I'm moving some code from an application to a helper class project. This application uses resource files that hold texts and their translations.
Is there a way to still access the resource files from the application within that new helper project? This would be very helpful, because then i don't have to move half of those resource files to that new project.
Assembly A (contains the resource file) -> Calls method on Assembly B and this method needs a resource text from Assembly A.
You could use Assembly.GetEntryAssembly().GetFile() method in dll to get the file from application assembly and use ResourceManager class to load it. Or possibly use Assembly.GetEntryAssembly().GetExportedTypes() to get strongly typed resource class. However, you should consider if referencing resources in application from library is the right approach. I would suggest either moving all resources to library assembly and referencing them from application, or (probably the best) - create separate assembly only for resources and use it both from app and dll.
I have two solutions, a solution named Server and a solution named Client. The Server contains a resources file named Server.Properties.Resources. That file is added to the Client solution as an external file.
When I debug inside Visual Studio, everything runs great. When I run the deployed version, I get the error
System.Resources.MissingManifestResourceException:
Could not find any resources appropriate for the specified culture or the neutral culture.
Make sure "Aexeo.DataLayer.Properties.Resources.resources" was correctly embedded or
linked into assembly "Core" at compile time, or that all the satellite assemblies required
are loadable and fully signed.
Is there a way to resolve this, maintaining the usage of the external file link?
I think this is what exactly you are looking for :
http://support.microsoft.com/kb/839861
The problem is caused when you manually create satellite assemblies. Satellite assemblies should be named in such a way that it could automatically be called from the application. To solve the issue you can use Assembly linker al.exe to link the assembly to the application properly.