GetManifestResourceStream, NULL döndürüyor


105

Bu bir C # .NET 4.0 uygulamasıdır:

Kaynak olarak bir metin dosyası yerleştiriyorum ve ardından bunu bir iletişim kutusunda görüntülemeye çalışıyorum:

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

Çözüm MyProjSolution ve yürütülebilir dosya MyProj.exe'dir. Help.txt gömülü bir kaynaktır. Ancak akış boştur. MyProjSolution.Help.txt ve MyProjSolution.MyProj.Help.txt denedim ama hiçbir şey işe yaramıyor gibi görünüyor.


1
Derleme bildirimindeki .mresource adlarına bakmak için ildasm.exe'yi kullanın. Bu sefalet çukuruna düşmekten kaçının, bunun yerine Proje + Özellikler, Kaynak sekmesini kullanın. Dolayısıyla, kaynak kodunuzda Properties.Resources.Help'i kullanabilirsiniz.
Hans Passant

Yanıtlar:


189

Kullanarak kaynakların doğru şekilde yerleştirilip yerleştirilmediğini kontrol edebilirsiniz.

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

hata ayıklama sırasında. Bu, kodunuzun yazıldığı derlemede gömülü olan tüm kaynakların (tam olarak nitelenmiş adlarını) listeleyecektir.

MSDN'de Assembly.GetManifestResourceNames () konusuna bakın .

Basitçe ilgili adı kopyalayın ve 'resourceName' değişkeninde tanımladığınız şey yerine bunu kullanın.

Notlar - kaynak adı büyük / küçük harfe duyarlıdır ve kaynak dosyasını yanlış yerleştirdiyseniz, GetManifestResourceNames () çağrısının döndürdüğü listede görünmeyecektir. Ayrıca - kaynağı doğru derlemeden okuduğunuzdan emin olun (birden çok derleme kullanılıyorsa), kaynakları başvurulan bir derlemeden ziyade şu anda yürütülen derlemeden almak çok kolaydır.

DÜZENLE - .NET Core .NET Core kullanılarak nasıl gömüleceğine ilişkin ayrıntılar için lütfen
bu SO gönderisine bakın .

Manifest bilgisinin alınması benzer görünüyor - sadece this.GetType().GetTypeInfo().Assembly.GetManifestResourceNames()kodun yürütüldüğü derlemeden bir bildirim almak için kullanın .

Assembly.GetExecutingAssembly()NET Core'da eşdeğerini nasıl yapacağımı henüz bulamadım ! bilen varsa - lütfen bana bildirin, bu yanıtı güncelleyeceğim.


5
İşe yaradı. ProjectName.Resources.Help.txt, katıştırılmış kaynak adıdır.
Ron

2
Yardımcı olduğuma sevindim! Bu gönderinin sorunuzu yanıtladığını düşünüyorsanız, lütfen bunu kabul edilen yanıt olarak işaretlemeyi unutmayın.
Jay

1
Evet, bu yüzden .Net Standardında [ProjeAdı]. [Ad Alanı]. [Kaynak] olmalıdır. Proje adını özlüyorum. Teşekkürler!
Billy Jake O'Connor

Sorunum GetEntryAssembly () yerine GetExecutingAssembly () kullanıyordu. İstediğim kaynak çalıştırılabilir durumdaydı, ancak aynı çözümde başka bir, başvurulan projede yaşayan kaynağı yükleme işlevi.
lettucemode

63

Önce dosyanın projenize dahil olup olmadığını kontrol ettim, ardından özelliklere gidin ve bu dosyanın derleme eylemini Gömülü Kaynak olarak ayarladım. bu benim için çalıştı.


Bu bana yardımcı oldu! Daha önce gömülü kaynağa varsayılan olarak eklenmiş bazı dosyalarım vardı, daha sonra eklediklerim "Yok" olarak ayarlandı. Visual Studio bazen çok can sıkıcıdır. Bunun en kötü yanı, kaynaklar için tüm XML dosyalarının derleme eylemi için NO ayarına sahip olmamasıdır. Derleme eyleminin orada ayarlanması gerekir.
John Suit

1
Varsayılan ad alanını ve kaynağa giden yolu kullanmayı unutmayın. ör DefatultNameSpace.Infrastructure.Help.txt. Proje özellikleri sayfanızdaki varsayılan ad alanı ve Infrastructuredosyanızın bulunduğu klasör olacaktır
jabu.hlong

İşte istediğim buydu Şerefe!
tekir

20

Gömülü dosyanın "Derleme Eylemi" özelliği , aşağıda verilen satırı düzgün bir şekilde çalıştırmak için "Gömülü Kaynak" olarak ayarlanmalıdır :

Stream stream = assembly.GetManifestResourceStream(resourceName)

Dosyayı sağ tıklayın, özelliği tıklayın ve ardından "Derleme Eylemi" özelliğini "Gömülü Kaynak" olarak ayarlayın:

görüntü açıklamasını buraya girin


Benim sorunum tam olarak neydi. Teşekkürler!
Riki

1
Bu benim sorunumdu. Resources.resx kullanarak ekledim ve işe yaramadı.
Hélder Lima

11

Boş değerimin nedeni burada.

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

GetManifestResourceStreamYöntem her zaman döner edecek NULLkaynağın 'inşa eylem niteliği gömülü kaynak' olarak ayarlanır değilse

Bu özelliği gerekli tüm dosyalarla ayarladıktan sonra assembly.GetManifestResourceStream, bunun yerine doğru akışı döndürmeye başlar NULL.


1
Tekrar teşekkürler. Bu, sorunumu bir veya iki ay önce düzeltti, sonra onu unuttum ve aynı sorunu yaşadım ve tekrar düzeltti.
Zengin

8

Sadece bir uyarı.

Bu Build Action özelliğine sahip olduğunu belirtmiş olsam da dosyama gömülü bir kaynak olarak erişemedim. Kafama vurarak çok zaman harcadım. Adına (xxx.cs.txt) .txt eklenmiş bir csharp kod dosyası ekledim. Bazı nedenlerden dolayı GetManifestResourceNames () ve GetManifestResourceStream () yöntemleri, adında .cs olan bir dosya görmez.

Sadece xxx.txt olarak yeniden adlandırdım ve her şey yolundaydı.

Tuhaf.


1
Bu bugün çok fazla zaman kaybetti! Kullanırsanız Resourceama kullanmazsanız Embedded Resourcegömecektir, bu da onu daha da tuhaf hale getirir ... İsimden çıkarmak .cs.işe yaramasını sağlar. Argh.
Matt

Sorun o .cs değil. dosyalardaki yol / segment C # dosyası olarak tanınır, bunun yerine bir CultureInfo olarak tanınır.
frontlinebg

2
Görünüşe göre çift uzantı ile hiç çalışmıyor.
Darion Badlydone

3

Aynı sorunu yaşadım, Jay sayesinde dizin adında kısa çizgi olduğunu buldum.

ProjectName.ResourceFolder.Sub-DirectoryProjectName.ResourceFolder.Sub_Directorykaynak akışına başvurduğunuzda olur .


2

Benim durumumda sorun, kaynağı arayan kodun, kaynağın kendisinden farklı bir projede olmasıydı.

Yalnızca kodla aynı projede bulunan kaynaklara erişebilirsiniz. Tüm kaynaklarımı web sayfası projesine koyabileceğimi düşündüm, ancak posta projesindeki resimlere de ihtiyacım var.

Umarım bu, benimle aynı durumda olan birine yardımcı olur.

Aramayı gerçekten yararlı buluyorum Assembly.GetExecutingAssembly().GetManifestResourceNames();.


Bu en azından 2011 yılından bu yana, doğru değildir: Her iki yoluyla Assembly.LoadFrom () ve typeof başka projede olan kaynaklara erişebilir
Marcelo Scofano

1

Başkasına yardımcı olması durumunda, Assembly.GetExecutingAssembly()satırın gömülü kaynakları olan aynı derlemeden çağrıldığından emin olun .


Başka bir projeden çağırmanız dışında ve bu durumda Assembly.LoadFrom () veya typeof kullanmanız gerekir, böylece başka bir projede bulunan kaynaklara erişebilirsiniz ...
Marcelo Scofano

1

Basit ve basit bir çözüm, bu temel sınıfa sahip olmaktır :

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

Ardından, bir kaynak eklediğinizde, aynı klasörde bir okuyucu C # sınıfı oluşturursunuz:

görüntü açıklamasını buraya girin

okuyucu sınıfı MyResource.cs burada çok basittir:

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

Böylece, her kaynak, onu doğru bir şekilde nasıl okuyacağını bilen bir "gölge" sınıfına sahip olacaktır.

Kodunuzdaki kaynağı şu şekilde okursunuz:

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

Diğer yanıtların önerildiği gibi, kaynak dosyasının Build Action özelliğinde "Gömülü Kaynak" ayarlamayı unutmayın.

Bu tek tip çözümün avantajı,

  1. özellikle iç içe klasörlere yerleştirildiğinde kaynağın tam adını bulmakta daha az güçlük çeker
  2. proje ayarlarında klasörün yeniden adlandırılması VEYA Varsayılan Ad Alanı'nın değiştirilmesi durumunda, kod KESİLMEZ

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

Çözümünüzü kaldırmanız gerekiyor, ardından projeyi düzenleyin, klasörünüzü bulun ve şu şekilde değiştirin:

<EmbeddedResource Include="yourpath" />

0

OP, GetManifestResourceStream'in aynı Derlemedeki kaynaklardan NULL döndürmesine rağmen , bazı Yanıtlar Kaynaklar başka bir Proje veya Derlemede olduğunda alınamayacaklarını ve GetManifestResourceStream'in NULL döndürmesinin adil bir nedeni olduğunu öne sürdü.

Bu, en azından 2011'den beri doğru değil; Başka bir yerde bazı yorumlarda belirttiğim gibi, Assembly.LoadFrom () veya typeof hile yapıyor ve sonuç olarak başka bir projedeki kaynaklara erişebilirsiniz.

Burada biraz karmaşık bir örneğim var; bu benim test kurulumum:

görüntü açıklamasını buraya girin

Başka bir projeye giden yol:

görüntü açıklamasını buraya girin

Burada yakalandı:

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

Ve WinFormFramework'dan Form1.cs ile belirtiyorum

Namespace.Folder.Resource

bunun gibi:

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

Ve metin kutusunda görüntülenen sonuç: görüntü açıklamasını buraya girin

Doğru yapmak için birkaç saat harcadım; bunun için Immediate Window'da çok fazla kullanmak zorunda kaldım:

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

Umarım birine yardımcı olur


-2

Muhtemelen txt dosyanızın yolunu GetManifestResourceStreamparametrede belirtmeniz gerekir veya txt dosyasını çalıştırılabilir dosyanızla aynı dizine yapıştırmayı deneyebilirsiniz. Umarım yardımcı olur!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.