GetManifestResourceStream returns NULL

前端 未结 13 2557
走了就别回头了
走了就别回头了 2020-11-28 05:41

This is a C# .NET 4.0 application:

I\'m embedding a text file as a resource and then trying to display it in a dialog box:

    var assembly = Assembl         


        
相关标签:
13条回答
  • 2020-11-28 06:03

    The embedded file's "Build Action" property should be set as "Embedded Resource" to run the line, which is given below, properly:

    Stream stream = assembly.GetManifestResourceStream(resourceName)
    

    Right click on the file, click the property and then set "Build Action" property as "Embedded Resource":

    0 讨论(0)
  • 2020-11-28 06:04

    Although OP got GetManifestResourceStream returning NULL from resources in the same Assembly, some Answers suggested that when Resources are in another Project or Assembly they cannot be retrieved, and are a fair cause of GetManifestResourceStream returning NULL.

    This is not true, at least since 2011; as I pointed in some comments elsewhere, Assembly.LoadFrom() or typeof do the trick and as a result you can access resources that are in another project.

    I have a moderately complex example here to illustrate; this is my test setup:

    Path to another project:

    Captured here:

     var sharedXMLResource =
                    "D:\\My Documents\\Consultório Impressos\\DB Pacientes\\Teste\\TestesVariados\\WinFormFramework\\Read_Embedded_XML_File_CS\\bin\\Debug\\Read_Embedded_XML_File_CS.exe";
    

    And on Form1.cs from WinFormFramework I specify with

    Namespace.Folder.Resource

    like that:

    StreamReader reader = 
                    new StreamReader(Assembly.LoadFrom(sharedXMLResource).GetManifestResourceStream("Read_Embedded_XML_File_CS.SharedResources.ContactList.xml") ?? throw new InvalidOperationException());
    

    And the result displayed at textbox:

    I spent several hours to get it right; for that, I had to use a lot these at Immediate Window:

    Environment.CurrentDirectory
    AppDomain.CurrentDomain.BaseDirectory
    System.Reflection.Assembly.GetExecutingAssembly().Location
    System.Reflection.Assembly.GetAssembly(typeof(WinFormFramework.Program)).Location
    

    Hope it helps someone

    0 讨论(0)
  • 2020-11-28 06:05

    You can check that the resources are correctly embedded by using

    //From the assembly where this code lives!
    this.GetType().Assembly.GetManifestResourceNames()
    
    //or from the entry point to the application - there is a difference!
    Assembly.GetExecutingAssembly().GetManifestResourceNames()
    

    when debugging. This will list all the (fully qualified names) of all resources embedded in the assembly your code is written in.

    See Assembly.GetManifestResourceNames() on MSDN.

    Simply copy the relevant name, and use that instead of whatever you have defined in the variable 'resourceName'.

    Notes - the resource name is case sensitive, and if you have incorrectly embedded the resource file, it will not show up in the list returned by the call to GetManifestResourceNames(). Also - make sure you are reading the resource from the correct assembly (if multiple assemblies are used) - it's all too easy to get the resources from the currently executing assembly rather than from a referenced assembly.

    EDIT - .NET Core
    Please see this SO post for details on how to embed using .NET Core.

    Retrieving the manifest info looks to be similar - just use this.GetType().GetTypeInfo().Assembly.GetManifestResourceNames() to get the a manifest from the assembly where the code is executing.

    I haven't figured out how to do the equivalent of Assembly.GetExecutingAssembly() in .NET Core yet! if anyone knows - please let me know and I will update this answer.

    0 讨论(0)
  • 2020-11-28 06:05

    In my case the problem was that the code looking for the resource was in a different project that the resource itself.

    You can only access resources that are in the same project the code is. I thought I could put all my resources in the web page project, but I need images in the mail project too.

    Hope this helps someone in the same situation I was.

    I find really useful calling Assembly.GetExecutingAssembly().GetManifestResourceNames();.

    0 讨论(0)
  • 2020-11-28 06:07

    A simple and streamlined solution is to have this base class:

    public class EmbededResourceReader
    {
        protected string LoadString(string fileName)
        {
            return LoadString(fileName, Encoding.UTF8);
        }
    
        protected string LoadString(string fileName, Encoding encoding)
        {
            var assembly = this.GetType().Assembly;
            var resourceStream = assembly.GetManifestResourceStream($"{this.GetType().Namespace}.{fileName}");
            using (var reader = new StreamReader(resourceStream, encoding))
            {
                return reader.ReadToEnd();
            }
        }
    }
    

    Then, when you add a resource, you create a reader C# class in the same folder:

    where the reader class MyResource.cs is very simple:

    public class MyResource : EmbededResourceReader
    {
        public string LoadString() => LoadString($"{nameof(MyResource)}.txt");
    }
    

    So, each resource will have a "shadow" class that knows how to read it properly.

    This is how you read the resource in your code:

    var text = new MyResource().LoadString();
    

    And as other answers suggested, do not forget to set "Embedded Resource" in the Build Action property of the resource file.

    The advantage of this uniform solution is

    1. less hassle with finding correct full name of the resource, especially when placed in nested folders
    2. in case when folder is renamed OR Default Namespace in project settings is changed, the code will NOT break
    0 讨论(0)
  • I had a similar issue check first that the file is included in your project , then go to properties and set the build action of that file to Embedded Resource . this worked for me .

    0 讨论(0)
提交回复
热议问题