We meet one issue for loading Mac resource with Xamarin. We have one resource
file named Resource1.resx. It failed when loading one string from this resource
file with below code. Please refer attachment sample to create this issue.
Could you please give some advice to load resource?
If you need any more information, please let me know that. Please check the
codes(in MainWindows.cs) as follow:
partial void loadResourceButtonClicked(MonoMac.Foundation.NSObject sender){
try{
var b = Resources1.ResourceManager;
var name = b.GetString("Name1");
resultLabel.StringValue = name;
}
catch {
resultLabel.StringValue = "Resource load failed.";
}
}
PS.We have attached the test project, please have a check.
Thanks.
Your 'hidden' exception:
Could not find any resources appropriate for the specified culture or
the neutral culture. Make sure
"MacResourceTest.Resources1.resources" was correctly
embedded or linked into assembly "MacResourceTest" at compile time, or
that all the satellite assemblies required are loadable and fully
signed.
The key phase in that exception message is 'Make sure XXXX was correctly embedded or linked into assembly'.
A quick look at your project and the .resx file is flagged incorrectly as a Build Action of BundleResource. OSX/iOS BundleResource's are typically used for binary, xml, text, etc.. but NOT .resx files as they originate via the System.Resources.ResourceManager and need to be added to the CIL assembly in a specific way (mainly due to culture localization).
1) Flag .resx files as a Build Action of EmbeddedResource
2) If your going to 'hide' exceptions and provide a 'user friendly' message, include the actual exception messages in Console debugging messaging, logging, somewhere, etc...
3) In posting questions to StackOverflow, please post the actual exception message / call stack.
Related
Good evening,
I happen to have an issue with Winforms and Resources.resx.
The app I'm working on is built via 'Winforms App' template selectable via Visual Studio.
The issue I'm having is kind of outside of winforms localization - which I think is important to mention.
Here's my issue:
- I've created a 'HistoryManager' class, which has only one method and one action to perform - add a history to the SQL database.
- I've created Resource.resx file, entered a format string into it under "MsgTaskAdded" which is equal to "Task {0} has been added to {1}".
- The said string adds to the database flawlessly.
Resources.resx works well - if I change MsgTaskAdded resource string, it changes what will be added to database .
Now, the issue I'm having is.
- I've created a Resources.de-DE.resx file, copied strings from Resources.resx and translated to german.
- Changed CurrentThread.CurrentCulture and CurrentThread.CurrentUICulture to 'de-DE'.
As a result, the text added to database is STILL in english, as if the file wasn't found and it fell back into using the default Resources.resx.
Make certain that your Resources.de-DE.resx file is contained within the Properties folder of your project, and that it has a Build Action of Embedded Resource, so that it gets properly associated to your default Resources.resx during compile. The culture settings on CurrentThread also need to happen before the call to the database, ideally somewhere in your static void Main() function before the Application.Run(…) call.
This should produce a culture-specific folder in your bin\<build_configuration> folder that contains a file named <your_app>.resources.dll. If needed, you can crack this open with a tool like ILSpy or Reflector to verify that the translated resources exist in the expected place within the assembly.
Maybe the reason in that how you're changing the thread culture. I did exectly what you did and its worked. That is how I've changed the culture
static void Main(string[] args)
{
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("de-DE");
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("de-DE");
Console.WriteLine(Resources.Hello);
}
it prints "Hallo"
I found a solution.
If you guys ever have issue with the Resources.resx, make sure the localized file isn't: Resources.de-DE.resx or Resources.pl-PL.resx, instead - use only the first bit (Resources.de.resx) and make sure to open the file and set accessors to 'Internal' so it generates you a Designer file with proper code.
I'm decompiling some .NET code for diagnosing an issue but the object is very large. To that end, I've been trying to see where .NET would raise the error I'm looking for by resource string as the exception type is fairly generic but the error message is specific to ultimate issue I'm looking into.
Decompiling the code, I see that it uses a string resource manager to pull out the text but without being able to match the resource key to the text, I cannot trace from the error message to the point in decompiled code.
E.g., exceptions are generated like the following in the decompiled code:
throw new ArgumentOutOfRangeException("value", SR.GetString("net_io_timeout_use_ge_zero"));
Where would I find the .NET's localized error text and associated resource key (e.g. "net_io_timeout_use_ge_zero")?
I've tried using ResHacker on System.dll and System.Net.dll (the assembly with the object I'm investigating) but both of these yield nothing. Likewise, while there's a culture subfolder of en-US under %windir%\Microsoft.NET\Framework\v4.0.30319 and the 64 equivalent but these don't show any text bar the assembly details and some icons in the System.dll
This is really PetSerAl's answer (if he posts one, I'll mark it as such) but to find the resource strings you can use ILSpy to load up the assembly and the resources can be found on the Resources node like so;
Going further, while ILSpy does list the resources, it doesn't provide a direct way to search for them. Saving saves out the compiled details which are not easily readable (there's a github request for this). In the meantime, you can select the contents the grid by selecting a single item, CTRL+A to select all, CTRL+C to copy the grid to the clipboard. From there you can paste into the likes of Excel or Notepad and search for the text you need.
I have an application where users can define custom elements by adding their own xaml files. These files are loaded by the application on startup. The idea is to be able to extend the application without having to recompile it. These elements will be shown on screen to the user, and the xaml files may contain resource keys which are not included in the resx files of the application itself. So I have a requirement to have separate resx files which the user can edit, that will also be loaded at runtime.
I've looked at the ResourceManager class, and I know that it can be set to access resources from various other assemblies. But from what I gather the resources must be part of an assembly, which is precisely what I don't want. What I want is to have a bunch of files like these:
%ProgramData%\MyApplication\Resources\strings.resx
%ProgramData%\MyApplication\Resources\strings.de-DE.resx
%ProgramData%\MyApplication\Resources\strings.zh-CN.resx
and I want my application to be able to load these files and access the strings in them.
This article https://msdn.microsoft.com/en-us/library/gg418542(v=vs.110).aspx shows two approaches using ResXResourceReader and ResXResourceSet. However, it appears that these classes take a path to a specific file (or a stream), and therefore won't be able to pick the correct file according to current culture and the naming convention. I know I can code this myself, and that's what I'll do if I don't find a better solution. But ideally I'd want something that handles this for me. For instance if it would be possible to point a ResourceManager to a folder instead of an assembly. Is something like this possible?
after a long long searching i found this:
If i understand you in the right way you want to create user defined forms in WPF at runtime using xaml.
I am not sure but, i think the resource files will not help you out, because all xaml forms precompiled in the assembly. I found something that maybe sounds like a solution for your problem. Its called Sattalite Assembly. In the first step you have to create a new resource file. Second step is to link it with the Assembly Linker (Al.exe). form .net Framework. MSDN Creating Satellite Assemblies
First step create a ResourceFile at Runtime (here a little help)
public static void CreateResourceFile()
{
string resourceFileName = "externeresource";
System.Xml.XmlDocument xmldoc = new XmlDocument();
XmlTextReader reader = new XmlTextReader("/runtimeWPForm.xml");
reader.WhitespaceHandling = WhitespaceHandling.None;
xmldoc.Load(reader);
ResourceWriter resourceWriter = new ResourceWriter(resourceFileName);
/*Add XmlDocument must be Serializable to store it in
resourceWriter.AddResource("xamlgrid", xmldoc.ToString());
the Resource, so i stored a String here. (not testet)*/
resourceWriter.Close();
MessageBox.Show("File " + resourceFileName + " created");
reader.Close();
}
Second step create a Sattlelite Assembly from resource file with Assembly Linker Al.exe
Last step is to load the xaml Forms from the Sattalite Assembly (here a little help)
Uri GridUri = new Uri(/*Note1*/, UriKind.Relative);
Windows.Resources.StreamResourceInfo sri = Application.GetResourceStream(GridUri);
System.Windows.Markup.XamlReader xrdr = new System.Windows.Markup.XamlReader();
Grid grd = (Grid)xrdr.LoadAsync(sri.Stream);
this.Content = grd;
Note1:
Resource file - referenced assembly Pack URIs in WPF
Uri uri = new Uri("/ReferencedAssembly;component/ResourceFile.xaml",UriKind.Relative);
Here some usefull Information as i think Construct XAML Forms at Runtime with Resource Files
This is all i found for you and no guarantee for functionallity.
Im interested in if this will work for you, so please send an answer on success or if you solved your issue.
PS.: if this works i think you only have to restart you main application to load the new sattalite assembly. Maybe you have to start an ohter application that do the job and after finish automaticly start your main app again.
Best reguards
GatewayToCode
I am writing a plugin in C#, in which I have a user control with a linklabel on it that controls a form that shows up like a tooltip and a picturebox next to the label to show the status whether or not the form is visible or hidden.
I have two images that are added as resources by the book via the Visual Studio PludingResources Designer. (I tried setting the Persistence of the images both to Linked at compile time and to embedded to solve the problem.)
The rubber meets the road in the following code:
pictureBox1.Image = SubAsst.PluginResources.SubAsst_Enabled1;
When the code execution hits this line to display the image, I get the
System.Resources.MissingManifestResourceException exception. The exception reads:
"Could not find any resources appropriate for the specified culture or the neutral culture. Make sure "SubAsst.PluginResources.resources" was correctly embedded or linked into assembly "SubtitlingAssistant" at compile time, or that all the satellite assemblies required are loadable and fully signed."
I looked all over on msdn and everywhere else I could but I could not find a solution yet. Except, if I change the code to use the built-in system icons, that works:
pictureBox1.Image = System.Drawing.SystemIcons.Information.ToBitmap();
So that is my workaround so far. However I would like to use my custom images for the plugin.
I suspect that the API does not allow image resources to be used, but this is not documented. I guess this from the fact that an icon can be imported and is displayed on the default button for the plugin.
I would appreciate any advice on this.
Looks like some resource file is missing, check these
MSDN links
You may receive a "System.Resources.MissingManifestResourceException" error message when you access the .resources file of the form at run time
A System.Resources.MissingManifestResourceException exception occurs when you try to access a localized resource
C#: What does MissingManifestResourceException mean and how to fix it?
Here is the solution:
What was missing is the CustomToolNamespace in the properties box:
Build action: Embedded Resource
Copy to Output Directory: Do not copy
Custom Tool: ResXFileCodeGenerator
Custom Tool Namespace: [myapplicationnamespace]
The namespace matches the NameSpace of my application. As soon as I set this and rebuilt the application, the error was gone and the image displayed.
Thanks for the link in Meysam Tolouee's answer, which lead to this "off-topic" answer. Here it is definitely not off-topic, and I wish I found this earlier.
What a great tool this StackOwerflow is!
I've working on a project where I'm using ResourceManager extensively and this question just crossed my mind.
Can we read from .resx files without using ResourceManager? I mean, is there another way?
ResourceManager is a convenience class, it works very well with the way the build system supports .resx files. No, it is not a strict necessity.
A .NET assembly has the generic capability of embedding arbitrary data into the manifest of the assembly. Just a blob of bytes, it can be anything you want. Directly supported by the build system as well, just add a file to your project and set its Build Action to "Embedded Resource". At runtime, you retrieve the data in that file with Assembly.GetManifestResourceStream().
You can stop right there, but that's just a single file, it doesn't scale very well if you have many small resources you want to embed. Which is where a .resx file starts, it is an XML file that contains resources in a friendly format. One that gives you a fighting chance to recover the source again when the original got lost.
But an XML format is not a very good format for resource data, it is bulky and it is expensive to find data back. So .NET has resgen.exe, a build tool that turns the XML file into a binary file, a .resources file. Compact and easy to find stuff back. And fit to be embedded directly as a single manifest resource.
What you don't want to do is having to read the .resources data yourself. You'll want to use a helper class that can find specific resources back from the blob of bytes. You want use the ResourceReader class, its GetResourceData() lets you specify the resource name and it will spit the resource type and data back out.
You can stop right there, but an app often has a need for different sets of resources. A very common localization need. Which is what satellite assemblies are all about, different assemblies that contain nothing but resources, each for a specific culture. They are separate so you don't pay for the virtual memory that's required to store all the localized resources when you need only one set of them. What's needed here is a helper class that automatically locates and loads the correct satellite assembly and retrieves the resource for you, based on the current culture.
That helper class is ResourceManager.
If you choose to skip the use of the ResourceManager you can let Visual Studio handle code generation for you. Ultimately the generated code uses a ResourceManager, but you're no longer writing that code manually. Additionally, you get compile-time checking since you're referencing a generated static class.
If you add a resource file to your project and double click it from the Solution Explorer, Visual Studio presents you with a dialog where you can enter a name for a resource, and its value. The dialog presents you with options to add resources as strings, images, audio, etc. (look at the dropdowns at the top of the dialog). Next, to get the code generation bit, you need to set the Access Modifier to either "Public" or "Internal". The third option is "No code generation."
For example, add a resource file called "MyResources", then add a string resource with the name Greeting and a value of Hello! With one of the former two options selected for code generation (start off with public to test it, restrict the access as needed), you should now be able to reference the resources from your code via MyResources.Greeting. If you don't see it right away, make sure you've saved the file and try compiling.
string greeting = MyResources.Greeting; // "Hello!"
If you add other resource types (image, audio, etc.) then the return types will differ, of course.
At this point you could inspect the generated .cs file and see that the generated code is using a ResourceManager. The other use for resource files is localization. Let's say you wanted a Spanish version of MyResources. You would add a new file called MyResources.es.resx, where es corresponds to the language code desired (Spanish in this case). Now add the same resource name of Greeting with a Spanish value of Hola!.
If you change the thread culture to Spanish, referencing the resource will now return the Spanish version:
string defaultGreeting = MyResources.Greeting; // "Hello!"
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("es");
string spanishGreeting = MyResources.Greeting; // "Hola!"
Note that you only really need to set the access modifier to one of the code generation options for your default resource file (i.e., MyResources.resx), not for all the other localized versions you add. There's no harm in doing so, but in my opinion it's cleaner to have the main file generated while the others just have the resource values desired without code generation.
Well, Resources are compiled into the assembly. You could try to read the assembly by reading the bytes (or the IL), and extract the resources from there.
ResourceManager does this all for you, so I could not think of any reason you want to do this... Maybe one, if you don't want to load the assembly in memory, you could do it without ResourceManager.
Ref Microsoft: Represents a resource manager that provides convenient access to culture-specific resources at run time.
I expect, I'd you use multi Lang, you will get a more consistent result and better compatibility.
IMHO