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を使用するだけで済みます。
ハンスパッサント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は埋め込みリソース名でした。
Ron

2
手伝ってよかった!この投稿があなたの質問に答えたと思われる場合は、これを承認済みの回答としてマークすることを忘れないでください。
ジェイ

1
ええ、そうです。.NET標準では、[ProjectName]。[Namespace]。[Resource]になるはずです。プロジェクト名がありません。ありがとう!
ビリージェイクオコナー

私の問題は、GetEntryAssembly()ではなくGetExecutingAssembly()を使用していたことです。必要なリソースは実行可能ファイルにありましたが、リソースをロードする機能は、同じソリューションの別の参照プロジェクトにありました。
lettucemode 2018

63

最初に同様の問題チェックを行い、ファイルがプロジェクトに含まれていることを確認してから、プロパティに移動して、そのファイルのビルドアクションを埋め込みリソースに設定しました。これは私のために働いた。


これは私を助けました!以前に追加したいくつかのファイルをデフォルトで埋め込みリソースに設定し、次に追加したファイルを「なし」に設定しました。Visual Studioはときどき迷惑です。これの最悪の部分は、リソースのすべてのXMLファイルにビルドアクションの設定がないことです。ビルドアクションが設定されている必要があります。
ジョンスーツ

1
デフォルトの名前空間とリソースへのパスを使用することを忘れないでください。例えばDefatultNameSpace.Infrastructure.Help.txt。プロジェクトのプロパティページのデフォルトの名前空間で、Infrastructureファイルがあるフォルダーになります
jabu.hlong

これが私が欲しかったものです!
tabby

18

埋め込みファイルの「ビルドアクション」プロパティを「埋め込みリソース」として設定して、以下に示す行を適切に実行する必要があります。

Stream stream = assembly.GetManifestResourceStream(resourceName)

ファイルを右クリックしてプロパティをクリックし、「ビルドアクション」プロパティを「埋め込みリソース」として設定します。

ここに画像の説明を入力してください


正確に私の問題は何でしたか。ありがとう!
Riki

1
これが私の問題でした。Resources.resxを使用して追加しましたが、機能しませんでした。
エルダーリマ

11

これが私のnull値の原因です。

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

GetManifestResourceStreamこの方法は、常に返しますNULLリソース「建てアクション」プロパティ「が埋め込まれたリソース」に設定されていない場合

このプロパティに必要なすべてのファイルを設定するとassembly.GetManifestResourceStream、ではなく正しいストリームが返され始めますNULL


1
再度、感謝します。これで1か月か2か月前に問題が解決しましたが、それを忘れて同じ問題が発生したため、再び修正されました。
2017年

8

ただの警告です。

それを指定し、ビルドアクションプロパティがあったとしても、埋め込みリソースとしてファイルにアクセスできませんでした。私の頭を叩いて多くの時間を無駄にしました。名前に.txtが追加されたcsharpコードファイルを埋め込みました(xxx.cs.txt)。何らかの理由で、GetManifestResourceNames()メソッドとGetManifestResourceStream()メソッドは、名前に.csが含まれているファイルを表示しません。

私は単にxxx.txtという名前に変更しましたが、すべて問題ありませんでした。

変だ。


1
これにより、今日は時間を大幅に節約できました。を使用すると埋め込まれますResourceEmbedded Resource、使用しない場合はさらに不自然になります.cs.。名前から削除すると機能します。ああ。
Matt

問題はその.csではありません。ファイル内のパス/セグメントはC#ファイルとして認識されますが、CultureInfoとして認識されます。
frontlinebg

2
ダブルエクステンションでは全く動かないようです。
Darion Badlydone

3

同じ問題がありました。ジェイのおかげで、ディレクトリ名にハイフンが含まれていることがわかりました。

ProjectName.ResourceFolder.Sub-DirectoryProjectName.ResourceFolder.Sub_Directoryリソースストリームを参照するとなります。


2

私の場合の問題は、リソースを探すコードが、リソース自体とは別のプロジェクトにあるということでした。

コードと同じプロジェクトにあるリソースにのみアクセスできます。すべてのリソースをWebページプロジェクトに配置できると思いましたが、メールプロジェクトにも画像が必要です。

これが私と同じ状況の誰かを助けることを願っています。

本当に便利な通話だと思いますAssembly.GetExecutingAssembly().GetManifestResourceNames();


これは、少なくとも2011年以降は当てはまりません
。Assembly.LoadFrom

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

また、他の回答が示唆しているように、リソースファイルの[ビルドアクション]プロパティに「組み込みリソース」を設定することを忘れないでください。

この均一なソリューションの利点は、

  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

ソリューションをアンロードする必要があります。次にプロジェクトを編集します。フォルダーを見つけて次のように変更します。

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