Resources in .NET satellite assembly not used - c#

I am trying to create a batch script to produce localised versions of resource files. Following the various MSDN articles I compile the resources using resgen
resgen.exe "My.Resources\resources.ja-JP.resx" "My.Resources\obj\resources.ja-JP.resources"
I then use Al to create the dll
al.exe" /culture:ja-JP /keyfile:"ResourceKey.snk" /out:"bin\ja-JP\My.Resources.resources.dll" /platform:x64 /template:"bin\My.Resources.resources.dll" /embed:"My.Operator.Resources\obj\resources.ja-JP.resources"
All of this works without error and produces a signed dll. However, when I use a test program to test it (again taken from an MSDN article) it does not find the localised resource but displays the generic language fallback instead. (if I swap the localised dll for one produced in Visual Studio all works fine)
Looking at the output in visual studio, it loads the dll withno errors.
Looking at the ResourceManager object in the debugger it appears to have loaded the fallback resources twice (but this is probably irrelevant)
The Fusion log is silent on the matter (i.e. no errors relating to the resource dlls.
Does anybody have any suggestions about what I am doing wrong? Is there any way of persuading .Net to provide further information about why it is ignoring the localised dll?
Thanks.

I think that the /template switch to al.exe should specify the executable file of the application.
It looks like you have specified the neutral resource file.
If that is not the error, I suggest that you build your project from the command line with msbuild, and examine the exact command lines which it uses.

Related

How to create a dll that includes all the others?

At the moment of creating a project of type "Library of Classes, usually one can generate a dll when compiling, but how could I generate a dll without losing others that I already have included?
I explain with an example: It turns out that Nuget downloaded an S22.Imap dll with the one I worked with, later I generated the dll in the traditional way that I explained in the beginning, but when I wanted to work with dll in another computer, I got errors that were not I found functions that contained the S22.IMAP dll. So to solve this problem, I had to copy the dll of my project, S22.IMAP in an additional way in a specific path of the other computer.
My question is:
How could you generate a dll that includes the ones included in the project you were working with?
All the referred 3rd party dlls (S22.Imap.dll in your example) will be copied to the output folder together with your own dll file (let's say a.dll) when you build your project. That means you should always copy them together (S22 + a.dll) to the place you want to refer them, on another computer/folder/place.
If you really want to make them only one file (although it is not recommended), you can set the S22 one as some "nested resource". Then you will get only one a.dll file and the S22 one is inside the a.dll. See below page for some reference:
Embedding one dll inside another as an embedded resource and then calling it from my code
AND, ILMerge is some tool that can help you do so.
In general, you don't. A DLL is a dynamic linked library, and you would normally only combine static libraries during a build. Here is an answer on the difference between static and dynamic linking.
Typically you would include all the DLLs you need in the installer package. If you use Visual Studio to create the installer, it can detect the dependencies for you. When you run the installer, all of the necessary DLLs are deployed. Nearly all commercial .NET software follows this pattern.
It is possible to merge an assembly into another assembly using a tool called ILMerge. This would be a very unusual thing to do, and could cause issues with intellectual property and code signing, so it is not recommended.

How do I properly handle resources when emitting from a Roslyn workspace?

I'm working on a project where we are compiling, emitting and running code using Roslyn. I've run into an issue where Roslyn does not embed resource files in the DLLs I emit using Compilation.Emit().
I see there is an argument of type IEnumerable<ResourceDescription> which I think I need to use.
Unfortunately, I can't find any information on resources in Project, so I'm not sure how to get the information I need.
Does Roslyn allow users to uncover any information about resource files? Or will I need to fall back to EnvDTE or using MSBuild manually? (If I need to use MSBuild, how do I support DNX projects?)
It looks like this information bypasses the project system, and is instead passed directly from the MSBuild loader to the command line arguments.
Source

c# Use dll with different versions in one directory

How can I use different dll's (other Version) with the same name in one directory?
For Example, LibA (ExternalLib.dll) has Version 1 and LibB (ExternalLib.dll) has Version 2.
I'm deploying all my programs to the same directory (this is our companys standard and I can't change this fact). The problem is if ProgramB which is using the LibB is deployed in the directory where ProgramA is using the LibA then ProgrammA would not longer work.
For my own Libs I use a Major-Version-Number (.01, .02) if there are big changes. But the Lib I'm using is an external Lib and each version of it requires different licensing-keys (which are handled by the programs itself).
I tried to rename the external libs from "ExternalLib.dll" to "ExternalLib.v1.dll" and "ExternalLib.v2.dll", but when I run my fresh compiled programm it throws an exception that says "ExternalLib.dll could not be found". The reference in my project is set to "ExternalLib.v1.dll" and compilation works fine.
Any ideas / suggestions to handle different assembly versions in the same directory?
Unfortunately, the filename of the DLL file has very little do do with how .Net is loading these types. The actual name is written into the meta data of the assembly as part of the compilation process. So at runtime, it will be probing for ExternalLib.dll regardless of what you renamed the file to. The usual way to fix this is to install to the GAC and use Strong Naming to reference the specific version.
Given you may not be able to do this, there are 4 things you could try:
Ask the vendor to produce version specific DLL's for you. They could compile such that the version name is part of the filename and included in the assembly manifest. This would be the simplest solution for you.
Handle the AssemblyResolve event and manually try and use Assembly.Load to point at the file you want such that you can specify specifically which dll to use. See http://support.microsoft.com/kb/837908 for more information, but effectively you'll be using Assembly.LoadFrom(specific_path) to choose the file where the code will load from.
If possible, you might also be able to use ildasm.exe to decompile the dll's to Intermediate Language (IL), then use ilasm.exe to recompile it to a new dll name. You would then reference this new DLL name in your project.
If the assembly is not signed, then you may be able to edit the manifest yourself; you can either use a compatible binary editor or possibly MT.exe.

Launching C# WPF from Java causes FileNotFoundExceptions

I have a existing Java Project which needs functionality from a SDK written in C#. It should open a WPF Window and send the information back to Java on close.
For a basic connection of those two worlds i created a Java Project ("DotNetCaller") calling native functions. These are implemented in a C++/CLI Project ("DotNetBridge") which calls the C# Project ("DotNetApplication").
I already can set Strings from Java in C# and callback from C# to Java.
But as soon as i add a WPF Window and try to launch it with:
Application app = new Application();
app.Run(new DotNetWindow());
in a STA Thread it crashes.
The DotNetApplication doesnt find mscorlib.resources, after i provide the DLL, PresentationFramework.resources is missing and if i provide that, the DotNetApplication.resource is missing (which i cant provide).
If i call the DotNetApplication alone or from the DotNetBridge the Window displays as expected.
Can anyone tell ma what i'm really missing here?
Thanks
Edit:
I looked at this example once more and tried to adapt it to my needs.
I have set the dll directory of the ResolveEventHandler to the .NET dir in "Referenced Assemblies"
C:\Program Files (x86)\Reference
Assemblies\Microsoft\Framework.NETFramework\v4.0
and added a Window in C#.
It failed aswell but with a new exception in the C++ part rather than C#.
The ResolveHandler gets called with an empty argument causing an uncatchable exception in mscorelib.
I added a check if the String is empty and this basic approach works fine now.
I'm still unsure if i have the correct approach for this, so feel free to contribute.
Your AppDomain::AssemblyResolve handler probably needs to be overhauled and based on your own understanding of what you want to do. There is some guidance here. The basic rule is that you return nullptr for requests that you can't handle.
But first you have to plan the locations in which you want to deploy (and/or debug) your assemblies. A simple layout would be to put all of the assemblies that your JNI DLL depends on in the same folder as the JNI DLL (with the exception of any that will be installed in the GAC). You can then use its location to satisfy resolution requests. But remember to return nullptr if no file containing a manifest for an assembly with the requested name is present there. (This is likely the case with your ".resources" requests. If there isn't one it's okay unless you know otherwise.)
I'd be a little surprised if an assembly in a Reference Assemblies folder wasn't also in the GAC—but it'd be up to the assembly provider. Reference Assemblies is for design and build tools (e.g. Visual Studio). (The old way was for each folder that had assemblies in it to be registered for each version of Visual Studio so the assemblies could be used for design and build.) If a dependency is not in the GAC, you can use the "Copy Local" property on the reference to make it available for debugging.
You might find the Assembly Binding Log Viewer useful while designing and troubleshooting. With it you can see all the folders and extensions that are tried before giving over to calling the AppDomain::AssemblyResolve handler chain. (Disable logging when you are done.)

C#: proprietary DLLs requiring access to my assemblies

My solution uses a proprietary assembly, which when debugging the solution throws an Exception saying it can't find an assembly that is meant to be one of the projects in my solution.
I cannot add a reference to the proprietary assembly because all I have is the DLL.
When I compile everything into a single application directory and run the app it works fine, but I want to debug.
Where should assemblies be placed if you want a proprietary assembly in the solution to see them?
I assume the issue is that there is no path specified and it is just looking in a default directory of some kind.
This will get you started.
http://msdn.microsoft.com/en-us/library/yx7xezcf(v=VS.100).aspx
Also search MSDN for AssemblyResolve, this will link you to additional articles to deepen your knowledge on this subject.
HTH!

Categories

Resources