GetManifestResourceStream이 NULL을 반환합니다.


105

이것은 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는 포함 된 리소스입니다. 그러나 스트림은 null입니다. MyProjSolution.Help.txt 및 MyProjSolution.MyProj.Help.txt를 시도했지만 아무것도 작동하지 않는 것 같습니다.


1
ildasm.exe를 사용하여 어셈블리 매니페스트에서 .mresource 이름을 확인합니다. 이 불행한 구덩이에 빠지지 않도록 대신 프로젝트 + 속성, 리소스 탭을 사용하십시오. 따라서 소스 코드에서 Properties.Resources.Help를 사용할 수 있습니다.
— Hans Passant 2014

답변:


189

다음을 사용하여 리소스가 올바르게 포함되었는지 확인할 수 있습니다.

//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 게시물 을 참조하십시오.

매니페스트 정보 검색은 비슷해 보입니다 this.GetType().GetTypeInfo().Assembly.GetManifestResourceNames(). 코드가 실행중인 어셈블리에서 매니페스트를 가져 오는 데 사용 하면됩니다.

Assembly.GetExecutingAssembly()아직 .NET Core에서 해당 작업을 수행하는 방법을 찾지 못했습니다! 아는 사람이 있으면 알려주세요.이 답변을 업데이트하겠습니다.


5
작동했습니다. ProjectName.Resources.Help.txt는 포함 된 리소스 이름입니다.
— 론

2
도움이되어 기쁩니다! 이 게시물이 귀하의 질문에 대한 답변을 받았다고 생각되면 수락 된 답변으로 표시하는 것을 잊지 마십시오.
— 제이

1
예, .Net Standard에서는 [ProjectName]. [Namespace]. [Resource] 여야합니다. 프로젝트 이름이 누락되었습니다. 감사!
— Billy Jake O'Connor

내 문제는 GetEntryAssembly () 대신 GetExecutingAssembly ()를 사용하고있었습니다. 내가 원했던 리소스는 실행 파일에 있었지만 리소스를로드하는 기능은 동일한 솔루션의 다른 참조 프로젝트에있었습니다.
— lettucemode 2010

63

먼저 파일이 프로젝트에 포함되어 있는지 비슷한 문제를 확인한 다음 속성으로 이동하여 해당 파일의 빌드 작업을 Embedded Resource로 설정했습니다. 이것은 나를 위해 일했습니다.


이것은 나를 도왔다! 기본적으로 포함 된 리소스로 설정된 일부 파일을 이전에 추가 한 다음 나중에 "없음"으로 설정 한 파일을 추가했습니다. Visual Studio는 때때로 너무 짜증이납니다. 이것의 최악의 부분은 리소스에 대한 모든 XML 파일에 빌드 작업에 대한 설정이 없다는 것입니다. 거기에 빌드 조치가 설정되어 있어야합니다.
— John Suit

1
기본 네임 스페이스와 리소스 경로를 사용해야합니다. 예 : DefatultNameSpace.Infrastructure.Help.txt. 기본 프로젝트 속성 페이지에서 네임 스페이스와 Infrastructure당신 파일이있는 폴더 것
— jabu.hlong

이것이 내가 원했던 건배!
— tabby

19

포함 된 파일의 "Build Action" 속성을 "Embedded Resource" 로 설정하여 아래에 제공된 줄을 올바르게 실행해야합니다.

Stream stream = assembly.GetManifestResourceStream(resourceName)

파일을 마우스 오른쪽 버튼으로 클릭하고 속성을 클릭 한 다음 "Build Action"속성을 "Embedded Resource"로 설정합니다.

여기에 이미지 설명 입력


내 문제가 정확히 무엇 이었습니까? 감사!
— Riki

1
이것은 내 문제였습니다. Resources.resx를 사용하여 추가했지만 작동하지 않았습니다.
— Hélder Lima

11

내 null 값의 원인은 다음과 같습니다.

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

이 GetManifestResourceStream메서드는 NULL리소스 'built action'속성이 'embedded resource'로 설정되지 않은 경우 항상 반환 합니다.

모든 필요한 파일이 속성을 설정 한 후 assembly.GetManifestResourceStream대신 올바른 스트림을 반환 시작합니다 NULL.


1
다시 한 번 감사드립니다. 이것은 한두 달 전에 내 문제를 해결 한 다음 잊어 버렸고 같은 문제가 있었고 다시 해결되었습니다.
— Rich

8

경고 일뿐입니다.

파일이 포함 된 리소스로 지정했지만 해당 빌드 작업 속성이 있어도 파일에 액세스 할 수 없습니다. 머리를 두드리는 데 많은 시간을 낭비했습니다. 이름에 .txt가 추가 된 csharp 코드 파일 (xxx.cs.txt)을 삽입했습니다. 어떤 이유로 GetManifestResourceNames () 및 GetManifestResourceStream () 메서드는 이름에 .cs가 포함 된 파일을 볼 수 없습니다.

나는 그것을 단순히 xxx.txt로 이름을 바꾸었고 모든 것이 잘되었습니다.

기묘한.


1
이것은 오늘 너무 많은 시간을 낭비했습니다! 사용 Resource하지만 사용 하지 않으면 Embedded Resource포함되므로 더 이상해집니다 ... .cs.이름에서 제거 하면 작동합니다. 아아.
— Matt

문제는 .cs가 아닙니다. 파일의 경로 / 세그먼트는 C # 파일로 인식되지만 CultureInfo로 인식됩니다.
— frontlinebg

2
이중 확장으로 전혀 작동하지 않는 것 같습니다.
— Darion Badlydone

3

Jay 덕분에 디렉토리 이름에 하이픈이 있다는 것을 알았습니다.

ProjectName.ResourceFolder.Sub-Directory된다 ProjectName.ResourceFolder.Sub_Directory당신이 자원 스트림을 참조 할 때.


2

제 경우 문제는 리소스를 찾는 코드가 리소스 자체와 다른 프로젝트에 있다는 것입니다.

코드와 동일한 프로젝트에있는 리소스에만 액세스 할 수 있습니다. 웹 페이지 프로젝트에 모든 리소스를 넣을 수 있다고 생각했지만 메일 프로젝트에도 이미지가 필요합니다.

이것이 나와 같은 상황에있는 누군가에게 도움이되기를 바랍니다.

나는 정말 유용한 전화를 찾습니다 Assembly.GetExecutingAssembly().GetManifestResourceNames();.


이것은 적어도 2011 년 이후, 사실이 아니다 : 모두를 통해 Assembly.LoadFrom이 () 및 대해서 typeof 다른 프로젝트에있는 리소스에 액세스 할 수 있습니다
— 마르셀 Scofano

1

다른 사람에게 도움이 될 경우 Assembly.GetExecutingAssembly()포함 된 리소스가있는 동일한 어셈블리에서 라인이 호출 되었는지 확인하십시오 .


다른 프로젝트에서 호출하는 경우를 제외하고이 경우에는 Assembly.LoadFrom () 또는 typeof를 사용 하여 다른 프로젝트에있는 리소스에 액세스 할 수 있습니다.
— Marcelo Scofano

1

간단하고 간소화 된 솔루션은 다음 기본 클래스를 사용하는 것입니다.

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. 폴더 이름이 변경되거나 프로젝트 설정의 기본 네임 스페이스가 변경된 경우 코드가 깨지지 않습니다.

0
    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>

0

솔루션을 언로드해야합니다. 그런 다음 프로젝트를 편집합니다 .Afterfind your folder and change like this :

<EmbeddedResource Include="yourpath" />

0

OP가 동일한 어셈블리의 리소스에서 NULL 을 반환하는 GetManifestResourceStream을 받았지만 일부 답변은 리소스가 다른 프로젝트 또는 어셈블리에있을 때 검색 할 수 없으며 GetManifestResourceStream이 NULL을 반환하는 정당한 원인이라고 제안했습니다.

적어도 2011 년 이후로는 사실이 아닙니다. 내가 다른 곳에서 일부 주석에서 지적했듯이 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에서 다음과 같이 지정합니다.

Namespace.Folder.Resource

그렇게 :

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

누군가에게 도움이되기를 바랍니다.


-2

GetManifestResourceStream매개 변수에 txt 파일의 경로를 지정해야 할 수도 있고 실행 파일과 동일한 디렉토리에 txt 파일을 고정 할 수도 있습니다. 도움이 되었기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.