Accessing Resources at Runtime - c#

I have an XML file included as part of my Silverlight 4.0 project that I'd like to access at runtime. I have the file saved in a directory named Resources with the Build Action set to "Content" and the Copy to Output Directory set to "Do not copy". If I decompress the XAP file, I see the XML file in the location I expect it to be, but I'm not sure how to reference it from code. I currently have the following:
Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(#"/AssemblyName;component/Resources/MyFile.xml")
Unfortunately, stream is null after running the code above. In addition to the path mentioned above, I've tried "/Resources/MyFile.xml", "/MyFile.xml" and "MyFile.xml", but they all experience the same behavior.
What is the correct way to access an XML file embedded as a resource in a Silverlight application?

A resource with build action "Content" just gets embedded into the xap file, with the same relative directory structure as the application. It does not get embedded as a resource in the assembly.
When set to build action "Content", you should be able to just load the file using something like (or whatever suits your needs):
XElement.Load(<relative directory>/<file>)
The method you're using currently (using a resource stream) is for embedded resources (which have their build action set to "Resource"). And for those, although I haven't tried yet if your method works, usually you'll get the resources using
Application.GetResourceStream

I have used the code snip below to get access to drawables. Not sure it's completely relevant, but hoping this will give you a hint one way or another ...
Resources res = getResources();
spec = tabHost.newTabSpec("groups").setIndicator("Groups", res.getDrawable(R.drawable.ic_tab_groups)).setContent(intent);

As was mentioned by Willem van Rumpt, "content" resources are not usual resources (they aren't stored in assembly). I've checked out this article and could't found at all that you could reference resource, marked as "content" from other assembly.
So, you have two options:
Define XML as embedded resource
Define XML as resource
In first case stream request looks like:
var a = Assembly.Load("AssemblyName");
var s = a.GetManifestResourceStream(#"DefaultNamespace.Resources.XMLFile2.xml");
In second case:
var a = Assembly.Load("AssemblyName");
var rm = new ResourceManager("AssemblyName.g", a);
using (var set = rm.GetResourceSet(CultureInfo.CurrentCulture, true, true))
{
var ums = (UnmanagedMemoryStream)set.GetObject(#"Resources/XMLFile1.xml", true);
}
Hope this helps.

Related

Xamarin.Forms Can not Read Text file from Resources Returned Null

I am using Xamarin.Forms, and I am trying to read text file from Resources, Code Below Returned Null value when trying to fetch text file.
var assembly = typeof(BookPage).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream("AboutResources.txt");
//assembly here return null value, I can not find Text Resources
My Code under the following Class Inherited From ContentPage On PLC Project
public class BookPage : ContentPage
//First get the list of all resources available for debugging purpose
assembly.GetManifestResourceNames()
This will list all the (fully qualified names) of all resources embedded in the assembly your code is written in.
Link: http://msdn.microsoft.com/en-us/library/system.reflection.assembly.getmanifestresourcenames(v=vs.110).aspx
Check if it has "AboutResources.txt" that you are expecting.
Check if you have incorrectly embedded the resource file, it will not show up in the list returned by the call to GetManifestResourceNames(). Make sure you you match the case of the name.
The following steps working fine for me:
1-First of all I added resource text file to same project
2-The file path must be like "Your Project name.your custom folder.filename".
var fileName = "MySampleProject.XMLData.rawxmldata.xml".
3-Make sure that Build Action is EmbeddedResource.

How to embed a file and then save it to a location?

I've added a test.zip to a C# project by creating a Resource1.resx and dragged to the resx tab. It is now visible in the Solution Explorer as a child of Resources.
When the program runs, I'd like to move it from the .exe to a location on the computer like My Documents.
I've a feeling I need to convert the resource to a memory stream before I can write it to file but I'm not sure how to access the file as resource or how to convert it.
I think the following extracts the resource object (then again, it doesn't error no matter what the first param is) but I'm not sure how to proceed:
var resource = new ResourceManager("test", Assembly.GetExecutingAssembly());
Since you activate the resources you have already a ResourceManager.Just use GetObject method,get the bytes of your file and write the them to a new file with File.WriteAllBytes:
var bytes = Properties.Resources.ResourceManager.GetObject("resourceName") as byte[];
File.WriteAllBytes("newFile.zip", bytes);
You should use Assembly.GetManifestResourceStream.
using (Stream x = Assembly.GetExecutingAssembly().GetManifestResourceStream("test"))
{
...
}
Reference to MSDN.

Assembly.GetManifestResourceStream not working with Xamarin on iOS

The following code works fine in Windows, however, when using Xamarin and targeting iOS, GetManifestResourceStream() returns null.
Assembly assembly = Assembly.GetExecutingAssembly();
Stream stream = assembly.GetManifestResourceStream("CommunicationModel.XmlSchemas.DeviceCommon.xsd");
I have set the file 'DeviceCommon.xsd' as an Embedded Resource. Not sure why it is not returning a valid stream.
Does anybody know why this is not working in iOS using Xamarin?
UPDATE:
Ok, so I followed the advice in the comments and set the file to Content.
I can now detect the file, but cannot open it:
if (File.Exists("DeviceCommon.xsd"))
{
try
{
myStream = new FileStream("DeviceCommon.xsd", FileMode.Open);
}
....
}
When I run the above code, the 'File.Exists()' call works, but when I attempt to open it, I get the following exception:
Access to the path "/private/var/mobile/Applications/8BD48D1F-F8E8-4A80-A446-F807C6728805/UpnpUI_iOS.app/DeviceCommon.xsd" is denied.
Anybody have some ideas how I can fix this???
Thanks,
Curtis
Ok, I finally got it to work. In my case, I was using the same files for a windows .dll and for a Xamarin.iOS.dll. I had named the .dll projects differently, though the namespaces were the same. Unfortunately, the microsoft documentation says that they use the namespace as part of the filename. That is no true.. They use the .dll name as part of the namespace. Just a slight difference, but makes all the difference.
So, to the point.. I set the file properties to: 'Embedded Resource' and 'Do not copy'. The resources I needed to process were all files with an .xsd extension, so I just looped through all resource names and used those that ended in .xsd. This way, no matter what operating system they were on, the name would be right because I retrieved it programmatically and didn't hard code it:
Assembly assembly = Assembly.GetExecutingAssembly();
string[] resources = assembly.GetManifestResourceNames();
foreach (string resource in resources)
{
if(resource.EndsWith(".xsd"))
{
Stream stream = assembly.GetManifestResourceStream(resource);
if (stream != null)
{
XmlSchema schema = XmlSchema.Read(stream, null);
_schemas.Add(schema);
}
}
}
As for me what I had to do is prefix it properly. Instead of looking for "fooBar.baz", look for "The.Name.Of.The.Assembly.The.Folder.Inside.fooBar.baz".

How to embed multilanguage *.resx (or *.resources) files in single EXE?

There are plenty of tutorials how to create multilanguage RESX files and how to create satellite assemblies with AL.exe, but I haven't found working example how to embed RESX/Resources/satellite-DLL files in single EXE file and distribute whole multilanguage app as such EXE.
I tried to use ilmerge.exe, but it looks like it doesn't work for multiple DLLs with the same name (culture satellite DLLs have identical names, originally residing in different subdirs named after culture).
I also don't know how to create ResourceManager instance to work with embedded resources.
My goals is to enable dynamical switching between closed, pre-defined set of languages. I need class/method which will get culture string (i.e. "de-DE"), resource name (i.e. "CancelText") and return translated text based on embedded resx/resource/dll.
I'm using VS2008, please note what setting for "build action" is needed in resx/resource files properties sheet. Working code sample or link to tutorial project would be the best.
My solution: program contains only one default language resource file (resx). All other languages are compiled from .resx to .resources and embedded as resource file. Important! I have changed extension because ".resources" is recognized as a special type of resource, so my French files is named "PIAE.LangResources.fr".
Here is simple code to retrieve translated string (it should be improved with caching values from resource):
internal static string GetString(string str, string lang)
{
if (string.IsNullOrEmpty(str)) throw new ArgumentNullException("empty language query string");
if (string.IsNullOrEmpty(lang)) throw new ArgumentNullException("no language resource given");
// culture-specific file, i.e. "LangResources.fr"
Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("PIAE.LangResources."+lang);
// resource not found, revert to default resource
if (null == stream)
{
stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("PIAE.Properties.LangResources.resources");
}
ResourceReader reader = new ResourceReader(stream);
IDictionaryEnumerator en= reader.GetEnumerator();
while (en.MoveNext())
{
if (en.Key.Equals(str))
{
return en.Value.ToString();
}
}
// string not translated, revert to default resource
return LangResources.ResourceManager.GetString(str);
}
You didn't find it because it's not the way the .NET framework works. .NET expects satellite DLLs in specifically named location (iow directories named after the language of the resources it contains. eg. de, de-DE, chs,...). If you don't work that way, .NET won't be able to apply its magic (which is to automatically pick the correct resource according to the current UI culture: Thread.CurrentThread.CurrentUICulture).
Use this program, it Works with me: EXEPack
You just need to do manually everytime you compile, not sure if there is a command tool.
I used the GetString approach above. The article Can't load a manifest resource with GetManifestResourceStream() describes how to correctly retrieve your resource as a stream object. After that, everything worked.

Embedding a binary file inside a class library

Is it possible to embed a custom binary file inside a C# class library and then at runtime read it with a binary reader?
I'm guessing it might be possible through resources.
Many thanks
You can do this by adding the file to the Resources through the project properties. Visual studio will then give you a handy class to access your file using the following code
byte[] theFile = myNamespace.Properties.Resources.theBinaryFile;
Where the resource name is theBinaryFile.
Yes it is easy:
Add the file to your project and set the "Build action" to "Embedded resource".
In your program do
foreach (string name in Assembly.GetExecutingAssembly().GetManifestResourceNames())
{
if (name.EndsWith("<name>", StringComparison.InvariantCultureIgnoreCase))
{
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name))
{
// ...
}
break;
}
}
Finding the right resource is a little bit complicating because there is stuff in front of the file name (namespaces etc. set a breakpoint to the if(...) to see the real resource name).

Categories

Resources