5

I'm having some trouble merging the localization satellite assemblies into the plugin DLL for CRM2011.

Either that, or I don't know how to use the merged resources afterwards.

I create a few plugins and create a basic resource file (default - English) and one for a specific culture (at the time of writing it's for Polish localizations, but later I'll need to add French as well).

I make sure not to sign the assembly itself, as ILMerge will sign the finished assembly itself.

This is the command I use to merge the extra satellite assembly:

ilmerge /targetplatform:v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319 /log:log.txt /keyfile:KeyFile.snk /out:Plugins.dll DynamicsCRM2011.Plugins.dll pl-PL\DynamicsCRM2011.Plugins.resources.dll

As you can see, the plugins are in .NET 4.0 and I've got the required .config file for ILMerge to use the required assemblies for merging.

The generated file appears fine, I can register it with CRM plugin-registrator, add new steps and so forth.

However, it will always use the default language. I've tried changing the System.Threading.Thread.CurrentThread.UICulture, but this didn't help. When I created a ResourceManager class and used GetString("ErrorMessage", new System.Globalization.CultureInfo("pl-PL")), I got an Exception that the specified ResourceManager doesn't know what to do with the specified culture.

I know of this question here. However, the posted solution seems to be an old one. The generated resource .cs files do not use a ComponentResourceManager. Also, parts of the code posted there have been marked as deprecated.

I'm not really sure what I'm am to do now, or how to further debug this, as I have very little experience when it comes to working with assemblies themselves. Please, help me get those satellite assemblies under control.


Update:

I've been working with sandbox plugins for a while now, and thus I no longer have access to things such as CurrentCulture (or at least I cannot change such things). I've tried tackling this problem once more: I've created a simple plugin which is fired when a new Account is saved. Nothing fancy. Here's the actual plugin code:

        ResourceManager rm = new ResourceManager(typeof(Properties.Resources));
        var s = rm.GetString("ErrorAlreadyPosted", new System.Globalization.CultureInfo("pl-PL"));
        throw new InvalidPluginExecutionException(s);

The code no longer throws an exception about not being able to find the specified culture... also the code obviously throws an exception at the end, but the important thing is WHAT the exception message is. I'd expect it to be in Polish.

Alas, it is not. The string returned by GetString is still in English.

The command I used for ILmerge is the same as before, but with the /lib parameter specified so that I don't have to copy all the CRM SDK dlls...

Community
  • 1
  • 1
MBender
  • 5,395
  • 1
  • 42
  • 69
  • I have what I suspect is the same issue as you - wanting to display localised error messages from plugins and have had absolutely no luck getting the ResourceManager to work with Plugins installed into the DB. Time is short for me so I am implementing a custom solution using XML files. Not ideal at all. Will be interesting to see if anyone comes up with a solution here. – glosrob Dec 01 '11 at 08:38
  • What is the full error message with stack trace? Does it work if you don't use ilmerge? – Rami A. Dec 17 '11 at 19:09
  • Can you attach a sample unit test that can reproduce this issue? – Rami A. Apr 18 '12 at 03:09
  • I've never created unit tests. :-/ I can most certainly try, but no guarantee it will be anything useful. Also, my knowledge of unit tests is minimal... but aren't they meant for specific methods? Which method do you have in mind? `GetString`? – MBender Apr 18 '12 at 07:32

3 Answers3

1

Apparently it is not possible to read resources from with the context of a Plugin.

Read up on MSDN: http://msdn.microsoft.com/en-us/library/hh670609.aspx#BKMK_UseXMLWebResourcesAsLanguageResources

Quote: When a plug-in requires localized text, you can use an XML web resource to store the localized strings so the plug-in can access them when needed. The structure of the XML is your option, but you may want to follow the structure used by ASP.NET Resource (.resx) files to create separate XML web resources for each language. For example, the following is an XML web resource named localizedString.en_US that follows the pattern used by .resx files.

This is all I know so far - have yet to build my own solution for localization of a crm plugin.

ueberboss
  • 51
  • 5
  • This article is for CRM 2015, but I'm guessing that if the new version doesn't allow it, then the older versions most definitely don't. – MBender Dec 03 '14 at 14:26
0

The way we eventually handled this is by adding the localization XML files (generated by Visual Studio) as CRM resources, and created a bit of custom code which seeks the appropriate resource and then seeks the localization text inside.

It's, obviously, not as simple as just using the generated C# localization class, and requires some prep work. However, with that prep-work in place and with using nameof it's now almost as simple as the aforementioned resource classes.

MBender
  • 5,395
  • 1
  • 42
  • 69
0

If you use a reflector tool to look at the generated assembly, do you see your resource(s) embedded correctly? You may be experiencing the bug as outlined in the link you posted.

Try setting Thread.CurrentThread.CurrentUICulture and\or Thread.CurrentThread.CurrentCulture.

Also try hooking into the AppDomain.CurrentDomain.AssemblyLoad and\or AppDomain.CurrentDomain.AssemblyResolve to debug which assemblies are being attempted to load and from where. You might need to customize their behavior so that instead of loading an external assembly to load an internal resource instead.

You can try embedding project references as resources instead of using ilmerge as well.
See this: http://bartlomiej.net/dotnet/embeded-assembies-into-an-executable/

Rami A.
  • 10,302
  • 4
  • 44
  • 87
  • Apologies for answering so late. I've been busy with other projects, and well... Christmas and so forth. The CurrentCulture/UICulture were definitely set. Hooking up the events sounds like a good idea, but I'm not entirely sure how that'll work in a CRM setting. – MBender Jan 02 '12 at 09:42
  • Check out the sample code from the docs: http://msdn.microsoft.com/en-us/library/system.appdomain.assemblyload.aspx http://msdn.microsoft.com/en-us/library/system.appdomain.assemblyresolve.aspx – Rami A. Jan 02 '12 at 09:48
  • `AppDomain.CurrentDomain.AssemblyLoad` isn't available in a Sandbox CRM plugin as it turns out. It's good for debugging, but I cannot rely on it to actually do anything. :( – MBender Apr 05 '12 at 09:33
  • > What is the full error message with stack trace? Does it work if you don't use ilmerge? – Rami A. Apr 06 '12 at 00:38
  • No, it's not an ILmerge problem. It's just that a CRM2011 plugin working in Sandbox doesn't allow the use of `AppDomain.CurrentDomain.AssemblyLoad`; it throws a security exception and suggests to use a non-sandbox plugin. Alas, I cannot do that. I suspect being able to load a custom DLL would indeed pose a rather big security risk... – MBender Apr 16 '12 at 15:20
  • In your original post, you indicated "When I created a ResourceManager class and used GetString..., I got an Exception" What is the full error message with stack trace? Does it work if you don't use ilmerge? – Rami A. Apr 17 '12 at 02:47
  • Apologies, I completely missed this. I'll modify my original post to answer this. – MBender Apr 17 '12 at 12:27