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 एक एम्बेडेड संसाधन है। हालाँकि, धारा अशक्त है। मैंने MyProjSolution.Help.txt और MyProjSolution.MyProj.Help.txt की कोशिश की है, लेकिन कुछ भी काम नहीं कर रहा है।


1
विधानसभा मेनिफ़ेस्ट में .mresource नामों को देखने के लिए ildasm.exe का उपयोग करें। दुख के इस गड्ढे में गिरने से बचें, इसके बजाय प्रोजेक्ट + प्रॉपर्टीज़, रिसोर्स टैब का उपयोग करें। तो आप बस अपने स्रोत कोड में Properties.Resources.Help का उपयोग कर सकते हैं।
हंस पैसेंट

जवाबों:


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 पर असेंबली .GetManifestResourceNames () देखें ।

बस संबंधित नाम की प्रतिलिपि बनाएँ, और इसका उपयोग करें कि आपने जो भी परिवर्तन किया है उसके बजाय चर 'रिसोर्सनाम' में परिभाषित करें।

नोट्स - संसाधन का नाम केस संवेदी है, और यदि आपने संसाधन फ़ाइल को गलत तरीके से एम्बेड किया है, तो यह GetManifestResourceNames () को कॉल द्वारा वापस की गई सूची में दिखाई नहीं देगा। इसके अलावा - सुनिश्चित करें कि आप सही असेंबली से संसाधन पढ़ रहे हैं (यदि कई विधानसभाओं का उपयोग किया जाता है) - यह सभी को संदर्भित विधानसभा से वर्तमान में निष्पादित विधानसभा से संसाधन प्राप्त करना बहुत आसान है।

EDIT - .NET कोर
कृपया .NET कोर का उपयोग करके एम्बेड करने के तरीके के विवरण के लिए इस SO पोस्ट को देखें।

प्रकट जानकारी को पुनः प्राप्त करना समान दिखता है - केवल this.GetType().GetTypeInfo().Assembly.GetManifestResourceNames()उस विधानसभा से प्रकट होने के लिए उपयोग करें जहां कोड निष्पादित हो रहा है।

मुझे नहीं पता है कि Assembly.GetExecutingAssembly().NET कोर के बराबर कैसे करना है अभी तक! अगर किसी को पता है - कृपया मुझे बताएं और मैं इस उत्तर को अपडेट करूंगा।


5
वह काम किया। ProjectName.Resources.Help.txt एम्बेडेड संसाधन नाम था।
रॉन

2
मुझे मदद करने में खुशी हुई! यदि आपको लगता है कि इस पोस्ट ने आपके प्रश्न का उत्तर दिया है, तो कृपया इसे स्वीकृत उत्तर के रूप में चिह्नित करना न भूलें।
Jay

1
हाँ, इसलिए .Net मानक में यह [ProjectName] होना चाहिए। [Namespace]। [संसाधन]। मुझे प्रोजेक्ट का नाम याद नहीं है। धन्यवाद!
बिली जेक ओ'कॉनर

मेरा मुद्दा GetExntingAssembly () के बजाय GetExecutingAssembly () का उपयोग कर रहा था। मैं जो संसाधन चाहता था, वह निष्पादन योग्य था, लेकिन संसाधन को लोड करने का कार्य उसी समाधान में दूसरे, संदर्भित परियोजना में रहता था।
लेटस्यूसमोड

63

मेरे पास पहले एक समान मुद्दा था कि फ़ाइल आपके प्रोजेक्ट में शामिल है, फिर संपत्तियों पर जाएं और एंबेडेड संसाधन के लिए उस फ़ाइल की बिल्ड कार्रवाई सेट करें। यह मेरे लिए काम किया।


इससे मुझे मदद मिली! मेरे पास कुछ फाइलें पहले जोड़ी गई थीं जो एम्बेडेड संसाधन के लिए डिफ़ॉल्ट थीं, फिर जिन्हें मैंने बाद में जोड़ा, उन्हें "कोई नहीं" पर सेट किया गया था। विजुअल स्टूडियो कई बार इतना कष्टप्रद होता है। इसका सबसे बुरा हिस्सा यह है कि संसाधनों के लिए XML फ़ाइलों के सभी में बिल्ड एक्शन के लिए कोई सेटिंग नहीं है। वहां बिल्ड एक्शन सेट होना चाहिए।
जॉन सूट

1
डिफ़ॉल्ट नाम स्थान और संसाधन के लिए पथ का उपयोग करना याद रखें। उदा DefatultNameSpace.Infrastructure.Help.txt। अपनी परियोजना के गुण पृष्ठ में डिफ़ॉल्ट नाम स्थान और Infrastructureफ़ोल्डर आप फ़ाइल में है हो सकता है
jabu.hlong

यह वही है जो मैं चीयर्स चाहता था!
टैबी

19

एम्बेडेड फ़ाइल की "बिल्ड एक्शन" संपत्ति को लाइन चलाने के लिए "एंबेडेड रिसोर्स" के रूप में सेट किया जाना चाहिए , जो नीचे दी गई है, ठीक से:

Stream stream = assembly.GetManifestResourceStream(resourceName)

फ़ाइल पर राइट क्लिक करें, संपत्ति पर क्लिक करें और फिर "एंबेडेड संसाधन" के रूप में "बिल्ड एक्शन" संपत्ति सेट करें:

यहां छवि विवरण दर्ज करें


वास्तव में मेरा मुद्दा क्या था। धन्यवाद!
रिक्की

1
यह मेरी समस्या थी। मैंने इसे Resources.resx का उपयोग करके जोड़ा और यह काम नहीं किया।
हेरीमा लीमा

11

यहाँ मेरे शून्य मान का कारण है।

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

GetManifestResourceStreamविधि हमेशा रिटर्न होगा NULLसंसाधन 'बनाया कार्रवाई' संपत्ति 'एम्बेडेड संसाधन' के लिए सेट नहीं है

सभी आवश्यक फ़ाइलों के साथ इस गुण को सेट करने के बाद, assembly.GetManifestResourceStreamइसके बजाय सही स्ट्रीम वापस करना शुरू कर देता है NULL


1
एक बार फिर धन्यवाद। इसने एक या दो महीने पहले मेरे मुद्दे को ठीक कर दिया और फिर मैं इसके बारे में भूल गया और एक ही मुद्दा था और इसे फिर से तय किया।
रिच

8

बस एक चेतावनी।

मैं अपनी फ़ाइल को एक एम्बेडेड संसाधन के रूप में एक्सेस नहीं कर सका, भले ही मैंने निर्दिष्ट किया था कि यह था और भले ही इसमें बिल्ड एक्शन प्रॉपर्टी थी। मेरा सिर पीटने में बहुत समय बर्बाद हुआ। मैंने अपने नाम (xxx.cs.txt) से जुड़े .txt के साथ एक csharp कोड फ़ाइल एम्बेड की है। किसी कारण से GetManifestResourceNames () और GetManifestResourceStream () विधियाँ इसके नाम वाली .cs के साथ फाइल नहीं करेगी।

मैंने इसे केवल xxx.txt नाम दिया और सब कुछ ठीक था।

अजीब।


1
यह आज बहुत अधिक समय बचा है! यदि आप इसका उपयोग करेंगे , Resourceलेकिन इसे एम्बेड करेंगे Embedded Resource, जो इसे भी अजीब बनाता है ... .cs.नाम से हटाने से यह काम करता है। अरे।
मैट

समस्या यह नहीं है। पथ / खंडों को फ़ाइलों में C # फ़ाइल के रूप में पहचाना जाता है, लेकिन एक CultureInfo के रूप में।
फ्रंटलाइनबग

2
ऐसा लगता है कि दोहरे विस्तार के साथ यह बिल्कुल भी काम नहीं करता है।
डैरियन बैडलडोन

3

मुझे वही समस्या थी, जे के लिए धन्यवाद मैंने पाया कि यह निर्देशिका नाम में हाइफ़न था।

ProjectName.ResourceFolder.Sub-Directoryहो जाता है ProjectName.ResourceFolder.Sub_Directoryजब आप संसाधन धारा के संदर्भ हैं।


2

मेरे मामले में समस्या यह थी कि संसाधन की तलाश करने वाला कोड एक अलग परियोजना में था जो संसाधन ही था।

आप केवल उन्हीं संसाधनों तक पहुँच सकते हैं जो कोड में हैं। मुझे लगा कि मैं अपने सभी संसाधन वेब पेज प्रोजेक्ट में डाल सकता हूं, लेकिन मुझे मेल प्रोजेक्ट में भी चित्र चाहिए।

आशा है कि यह उसी स्थिति में किसी की मदद करता है जो मैं था।

मुझे वास्तव में उपयोगी कॉलिंग मिल गई है Assembly.GetExecutingAssembly().GetManifestResourceNames();


यह सच नहीं है, कम से कम 2011 के बाद से: दोनों विधानसभा के माध्यम से।
लॉडफ्रॉम

1

यदि यह किसी और की मदद करता है, तो सुनिश्चित करें कि Assembly.GetExecutingAssembly()लाइन को उसी असेंबली से बुलाया जाता है जिसमें एम्बेडेड संसाधन होते हैं।


सिवाय अगर आप इसे किसी अन्य परियोजना से बुलाते हैं, और इस मामले में आपको असेंबली का उपयोग करना चाहिए।
LadFrom

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

हालांकि ओपी को GetManifestResourceStream एक ही असेंबली में संसाधनों से NULL लौट रहा है , लेकिन कुछ उत्तर ने सुझाव दिया कि जब संसाधन किसी अन्य प्रोजेक्ट या असेंबली में हैं, तो उन्हें पुनर्प्राप्त नहीं किया जा सकता है, और GetManifestResourceStream NULL को वापस करने का एक उचित कारण है।

यह सच नहीं है, कम से कम 2011 के बाद से; जैसा कि मैंने कहीं और विधानसभा में कुछ टिप्पणियों में बताया। लॉडफ्रॉम () या टाइपोफ ट्रिक करते हैं और परिणामस्वरूप आप उन संसाधनों तक पहुंच सकते हैं जो किसी अन्य प्रोजेक्ट में हैं।

इसका वर्णन करने के लिए मेरे पास एक मामूली जटिल उदाहरण है; यह मेरा परीक्षण सेटअप है:

यहां छवि विवरण दर्ज करें

किसी अन्य प्रोजेक्ट का पथ:

यहां छवि विवरण दर्ज करें

यहां कैद:

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

और Win1ormFramework से 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 फ़ाइल को चिपकाने की कोशिश कर सकते हैं। उम्मीद है की वो मदद करदे!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.