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.