C# Reading resource .resx file outside of assembly throws MissingManifestResourceException
Asked Answered
B

1

7

I am working on a project which consists both Asp.Net web application and windows service application. These two can use a mutual project which I created just to contain resource files. I wanted to put the resource files out side of the assembly so when I want to change them, they could be editable without compiling all solution. I search for a method and find here one as;

ASP.NET Resourcemanager to read local .resx

It worked perfectly on the web application, but after a while I saw, the windows service application cannot read that resources and I got

System.Resources.MissingManifestResourceException: Could not find any resources appropriate for the specified culture (or the neutral culture) on disk.
baseName: abc  locationInfo: <null>  fileName: abc.resx
   at System.Resources.FileBasedResourceGroveler.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.GetObject(String name, CultureInfo culture, Boolean wrapUnmanagedMemStream)
   at System.Resources.ResourceManager.GetObject(String name, CultureInfo culture)
   at yyyy.yyyyyy.yyyyyyy.GetGlobalResourceObject(String classKey, String resourceKey, Boolean getCommon)
   at xxx.xxx.xxx.Entities.xxxxxxxx.get_LocalizedName()
   at yyyyy.Adapters.ArchiverDtoAdapter.CreateArchiverInjectionsDto(InjectionProcedure procedure, INamingService namingService)
   at yyyyy.Adapters.ArchiverDtoAdapter.ConvertInjectionProcedureDto(InjectionProcedure procedure, INamingService namingService)
   at yyyy.Factories.ArchiverDtoFactory.<>c__DisplayClass1.<CreateInjectionProcedureSendRequestDto>b__0(IUnitOfWork unitOfWork)
   at Core.Data.NHibernate.Factory.UnitOfWorkFactoryBase.Create(Action`1 action, IUnitOfWork unitOfWork)
   at Core.Data.NHibernate.Factory.UnitOfWorkFactory.Create(Action`1 action)

I dont understand the problem because, I project works correctly and the other is not. The other strange behaviour is that when i start the service on my machine with debuging to see what happens, it works.

Update: This is the code I am using as referenced

public class ResxResourceManager : ResourceManager
    {
        public ResxResourceManager(string baseName, string resourceDir)
        {
            ObjectFactory.ResolveDependencies(this);

            Type[] paramTypes = new Type[] { typeof(string), typeof(string), typeof(Type) };
            object[] paramValues = new object[] { baseName, resourceDir, typeof(ResXResourceSet) };

            Type baseType = GetType().BaseType;

            ConstructorInfo ci = baseType.GetConstructor(
                BindingFlags.Instance | BindingFlags.NonPublic,
                null, paramTypes, null);

            ci.Invoke(this, paramValues);
        }

        protected override string GetResourceFileName(CultureInfo culture)
        {
            string resourceFileName = base.GetResourceFileName(culture);
            return resourceFileName.Replace(".resources", ".resx");
        }
    }
Brutish answered 4/7, 2014 at 9:13 Comment(6)
Reading a manifest resource is done with a method of Assembly: you need an instance for the assembly containing the resource: please show your code so we can see which assembly you are using.Friede
Hi Richard, the problem rises because I don't want to use assembly to store resources. I created the 'ResxResourceManager' as suggested at the link I gave in the question. I check if the parameters were wrong but culture, directory and filename are all given correctly.Brutish
Looking at hat code: it is using reflection in its call its own base class's constructor on itself. At best that's going to be fragile code (in the four years since the referenced A updates to .NET could have broken this). Why not just call that ctor directly? Also probably worth getting this working in a small focused prototype (eg. no NHibernate or UI).Friede
With default constructor we need to embed the resources into the assembly, so user (end user) cannot change anything specific without recompile all assemblies and signing them. To avoid that we wanted to use resources in outside scope. The question in mind if it wasn't working, it shouldn't work on other project or debug mode at all.Brutish
Sorry, you misunderstand, I am suggesting using … : base(baseName, resourceDir, typeof(ResXResourceSet)) rather that the reflection (and thus not calling two different ResourceManager constructors on the same object). The whole use of reflection appears to be working around ResourceManager's three arg constructor not being public: I can only assume it wasn't in an earlier version of .NET and the code wasn't updated (MSDN only goes back to .NET 2: and it was public then).Friede
I tried the approach you suggested but, there is no base constructor which accepts (baseName, resourceDir, typeof(ResXResourceSet)). But after a while i found the problem which is completely different. It was the path string I was giving. The path was coming from assembly path and it was consisting 20% (whitespace) because of the encoding. When i gave the local path the method worked flawless. Thank you for your time and help.Brutish
L
0

Please have a look into this. Hope this helps.

http://support.microsoft.com/kb/839861

Laraelaraine answered 27/8, 2014 at 12:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.