【问题标题】:GetManifestResourceStream returns NULLGetManifestResourceStream 返回 NULL
【发布时间】:2014-03-05 11:02:21
【问题描述】:

这是一个 C# .NET 4.0 应用程序:

我将文本文件作为资源嵌入,然后尝试在对话框中显示它:

    var assembly = Assembly.GetExecutingAssembly();
    var resourceName = "MyProj.Help.txt";

        using (Stream stream = assembly.GetManifestResourceStream(resourceName))
        {
            using (StreamReader reader = new StreamReader(stream))
            {
                string result = reader.ReadToEnd();
                System.Windows.Forms.MessageBox.Show(result, "MyProj", MessageBoxButtons.OK);
            }
        }

解决方案是 MyProjSolution,可执行文件是 MyProj.exe。 Help.txt 是一个嵌入式资源。但是,流为空。我已经尝试过 MyProjSolution.Help.txt 和 MyProjSolution.MyProj.Help.txt 但似乎没有任何效果。

【问题讨论】:

  • 使用 ildasm.exe 查看程序集清单中的 .mresource 名称。请避免陷入这个痛苦的深渊,请改用 Project + Properties,Resource 选项卡。因此,您可以在源代码中使用 Properties.Resources.Help。

标签: c# embedded-resource


【解决方案1】:

您可以通过使用检查资源是否正确嵌入

//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()

调试时。这将列出您编写代码的程序集中嵌入的所有资源的所有(完全限定)名称。

请参阅 MSDN 上的 Assembly.GetManifestResourceNames()

只需复制相关名称,然后使用它代替您在变量“resourceName”中定义的任何名称。

注意 - 资源名称区分大小写,如果您错误地嵌入了资源文件,它将不会显示在调用 GetManifestResourceNames() 返回的列表中。另外 - 确保您从正确的程序集中读取资源(如果使用多个程序集) - 从当前执行的程序集中而不是从引用的程序集中获取资源太容易了。

编辑 - .NET Core
有关如何使用 .NET Core 嵌入的详细信息,请参阅此SO post

检索清单信息看起来很相似 - 只需使用 this.GetType().GetTypeInfo().Assembly.GetManifestResourceNames() 从执行代码的程序集中获取清单。

我还没有想出如何在 .NET Core 中做相当于 Assembly.GetExecutingAssembly() 的操作!如果有人知道 - 请告诉我,我会更新这个答案。

【讨论】:

  • 那行得通。 ProjectName.Resources.Help.txt 是嵌入的资源名称。
  • 我很高兴能帮上忙!如果您觉得这篇文章回答了您的问题,请不要忘记将其标记为已接受的答案。
  • 是的,所以在 .Net Standard 中它应该是 [ProjectName].[Namespace].[Resource]。我错过了项目名称。谢谢!
  • 我的问题是使用 GetExecutingAssembly() 而不是 GetEntryAssembly()。我想要的资源在可执行文件中,但加载资源的函数位于同一解决方案中的另一个引用项目中。
  • 我通过 GUI 添加资源时遇到了同样的问题。然后我读了这篇文章c-sharpcorner.com/uploadfile/40e97e/…。我通过VS添加一个现有项目,然后使用这个名称:“ConsoleApp1.myfile.txt”所以它:“.”。
【解决方案2】:

我有一个类似的问题,首先检查该文件是否包含在您的项目中,然后转到属性并将该文件的构建操作设置为 Embedded Resource 。这对我有用。

【讨论】:

  • 这对我有帮助!我之前添加了一些默认为嵌入式资源的文件,然后我稍后添加的文件设置为“无”。 Visual Studio 有时很烦人。最糟糕的部分是资源的所有 XML 文件都没有构建操作的设置。应该在那里设置构建操作。
  • 记得使用默认的命名空间和资源路径。例如DefatultNameSpace.Infrastructure.Help.txt。项目属性页面中的默认命名空间和Infrastructure 将是您的文件所在的文件夹
  • 这就是我想要的干杯!
【解决方案3】:

嵌入文件的 "Build Action" 属性应设置为 "Embedded Resource" 以正确运行如下所示的行:

Stream stream = assembly.GetManifestResourceStream(resourceName)

右击文件,点击属性,然后将“Build Action”属性设置为“Embedded Resource”:

【讨论】:

  • 正是我的问题。谢谢!
  • 这是我的问题。我使用 Resources.resx 添加了它,但它不起作用。
【解决方案4】:

这是我的空值的原因。

http://adrianmejia.com/blog/2011/07/18/cs-getmanifestresourcestream-gotcha/

如果资源“构建操作”属性未设置为“嵌入资源”,GetManifestResourceStream 方法将始终返回 NULL

在使用所有需要的文件设置此属性后,assembly.GetManifestResourceStream 开始返回正确的流而不是 NULL

【讨论】:

  • 再次感谢。这在一两个月前解决了我的问题,然后我忘记了它并且遇到了同样的问题,它再次解决了它。
  • 谢谢你拯救了我的一天
【解决方案5】:

只是一个警告。

我无法将我的文件作为嵌入式资源访问,即使我指定它是并且即使它具有 Build Action 属性。浪费了很多时间敲我的头。我嵌入了一个 csharp 代码文件,其名称后附加了 .txt (xxx.cs.txt)。由于某种原因,GetManifestResourceNames() 和 GetManifestResourceStream() 方法不会看到名称中包含 .cs 的文件。

我将它简单地重命名为 xxx.txt,一切都很好。

很奇怪。

【讨论】:

  • 今天浪费了太多时间!如果您使用Resource 而不是Embedded Resource,它将嵌入它,这使得它更加奇怪......从名称中删除.cs. 使其工作。啊。
  • 问题不在于.cs。文件中的路径/段被识别为 C# 文件,而不是 CultureInfo。
  • 看来双扩展根本行不通。
【解决方案6】:

我遇到了同样的问题,感谢 Jay,我发现它是目录名称中的连字符。

当您引用资源流时,ProjectName.ResourceFolder.Sub-Directory 变为 ProjectName.ResourceFolder.Sub_Directory

【讨论】:

    【解决方案7】:

    在我的情况下,问题在于寻找资源的代码与资源本身位于不同的项目中。

    您只能访问代码所在项目中的资源。我以为我可以把我所有的资源放在网页项目中,但是我也需要在邮件项目中的图片。

    希望这可以帮助和我遇到同样情况的人。

    我发现拨打Assembly.GetExecutingAssembly().GetManifestResourceNames(); 非常有用。

    【讨论】:

    • 这不是真的,至少从 2011 年开始:通过Assembly.LoadFrom()typeof,您可以访问另一个项目中的资源
    【解决方案8】:

    一个简单而精简的解决方案是拥有这个 base 类:

    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();
            }
        }
    }
    

    然后,当您添加资源时,您会在同一文件夹中创建一个阅读器 C# 类:

    阅读器类 MyResource.cs 的地方很简单:

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

    因此,每个资源都有一个“影子”类,知道如何正确读取它。

    这是您在代码中读取资源的方式:

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

    正如其他答案所建议的,不要忘记在资源文件的 Build Action 属性中设置“Embedded Resource”。

    这种统一解决方案的优点是

    1. 找到正确的资源全名更轻松,尤其是放在嵌套文件夹中时
    2. 如果重命名文件夹或更改项目设置中的默认命名空间,代码不会中断

    【讨论】:

      【解决方案9】:

      如果它对其他人有帮助,请确保从具有嵌入式资源的同一程序集中调用 Assembly.GetExecutingAssembly() 行。

      【讨论】:

      • 除非你从另一个项目中调用它,在这种情况下你应该使用Assembly.LoadFrom()typeof 这样你就可以访问另一个项目中的资源......
      【解决方案10】:
          First Unload the project and click on edit the project file. 
      
          Inside the project file make sure that the item you are fetching from the assembly is included inside <EmbeddedResource> tag.
      
          Eg: 
      
               <ItemGroup>
                <EmbeddedResource Include="Template\ForExampleFile.html" />
               </ItemGroup>
      
      
          The files I added into the project were just in Content tag but not in the EmbeddedResource as shown below by default. Hence the stream was returning null.
          <ItemGroup>
              <Content Include="Template\ForExampleFile.html" />
        </ItemGroup>
      

      【讨论】:

        【解决方案11】:

        您需要卸载您的解决方案。然后编辑项目。找到您的文件夹并更改如下:

        <EmbeddedResource Include="yourpath" />
        

        【讨论】:

          【解决方案12】:

          虽然 OP 从同一个程序集中的资源中获得了 GetManifestResourceStream 返回 NULL,但一些答案表明,当资源在另一个项目或程序集中时,它们无法检索,并且是 GetManifestResourceStream 返回 NULL 的合理原因。

          这不是真的,至少从 2011 年开始是这样;正如我在其他地方的一些 cmets 中指出的那样,Assembly.LoadFrom()typeof 可以做到这一点,因此您可以访问另一个项目中的资源。

          我这里有一个比较复杂的例子来说明;这是我的测试设置:

          另一个项目的路径:

          在这里拍摄:

           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";
          

          在我指定的 WinFormFramework 的 Form1.cs 上

          命名空间.文件夹.资源

          这样:

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

          结果显示在文本框中:

          我花了几个小时才把它弄好;为此,我不得不在即时窗口中大量使用这些:

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

          希望对某人有所帮助

          【讨论】:

            【解决方案13】:

            您可能需要在 GetManifestResourceStream 参数中指定 txt 文件的路径,或者您可以尝试将 txt 文件粘贴在与可执行文件相同的目录中。希望对您有所帮助!

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2014-04-25
              • 2013-01-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-06-28
              • 1970-01-01
              相关资源
              最近更新 更多