मैं असेंबली को कैसे परिवर्तित कर सकता हूं। CodeBase को C#में एक फाइल सिस्टम पथ में बदल सकता है?




.net nunit (4)

मेरे पास एक प्रोजेक्ट है जो DLL और EXE के बगल में एक \Templates फ़ोल्डर में टेम्पलेट्स संग्रहीत करता है।

मैं इस फ़ाइल पथ को रनटाइम पर निर्धारित करना चाहता हूं, लेकिन एक तकनीक का उपयोग करना जो एक इकाई परीक्षण के साथ-साथ उत्पादन में भी काम करेगा (और मैं NUnit में छाया-प्रतिलिपि अक्षम नहीं करना चाहता!)

Assembly.Location अच्छा नहीं है क्योंकि यह NUnit के तहत चलने पर छाया-प्रतिक्षित असेंबली का पथ लौटाता है।

Environment.CommandLine भी सीमित उपयोग की है क्योंकि NUnit et al में यह NUnit का रास्ता लौटाता है, मेरे प्रोजेक्ट के लिए नहीं।

Assembly.CodeBase ।कोडबेस आशाजनक लग रहा है, लेकिन यह एक यूएनसी मार्ग है:

file:///D:/projects/MyApp/MyApp/bin/debug/MyApp.exe

अब मैं इसे स्ट्रिंग में हेरफेर का उपयोग करके एक स्थानीय फाइल सिस्टम पथ में बदल सकता हूं, लेकिन मुझे संदेह है कि इसे नेट कंप्रेसर में कहीं दफन करने का एक क्लीनर तरीका है। किसी को भी ऐसा करने का एक अनुशंसित तरीका पता है?

(यदि UNC पथ file:/// नहीं है, तो एक अपवाद को फेंकना file:/// URL इस संदर्भ में बिल्कुल ठीक है)


असेंबली ।कोडबेस आशाजनक लग रहा है, लेकिन यह एक यूएनसी मार्ग है:

ध्यान दें कि यह एक यूआरआई पथ नहीं , बल्कि एक फ़ाइल यूरी का अनुमान लगा रहा है।

आप इसे हाथ से स्ट्रिंग हेरफेर करके हल करते हैं। गंभीरता से।

निम्नलिखित निर्देशिका (शब्दशः) के साथ SO पर मिलने वाले अन्य सभी तरीकों को आज़माएँ:

C:\Test\Space( )(h#)(p%20){[a&],[email protected],p%,+}.,\Release

यह एक मान्य है, अगर कुछ असामान्य, विंडोज पथ। (कुछ लोगों के पास इन रास्तों में से कोई एक वर्ण होगा, और आप चाहते हैं कि आप उन सभी के लिए काम करने की विधि सही है?)

उपलब्ध कोड आधार ( हम Location नहीं चाहते हैं, ठीक है? ) गुण तब हैं (.NET 4 के साथ मेरे Win7 पर):

assembly.CodeBase -> file:///C:/Test/Space( )(h#)(p%20){[a&],[email protected],p%,+}.,/Release

assembly.EscapedCodeBase -> file:///C:/Test/Space(%20)(h%23)(p%20)%7B%5Ba%26%5D,[email protected],p%,+%7D.,/Release

आप ध्यान देंगे:

  • CodeBase बिल्कुल भी नहीं बचा है, यह सिर्फ नियमित रूप से स्थानीय file:/// साथ उपसर्ग है file:/// और बैकस्लैश की जगह। जैसे, यह System.Uri को यह खिलाने के लिए काम नहीं करता है
  • EscapedCodeBase पूरी तरह से बच नहीं है (मुझे नहीं पता कि यह बग है या यदि यह यूआरआई योजना की कमी है):
    • ध्यान दें कि स्पेस कैरेक्टर ( ) का अनुवाद %20
    • लेकिन %20 अनुक्रम भी %20 अनुवाद करता है! (प्रतिशत % बच नहीं रहा है)
    • कोई भी इस मंगली रूप से मूल का पुनर्निर्माण नहीं कर सकता है!

स्थानीय फ़ाइलों के लिए (और यह वास्तव में सभी मैं CodeBase सामान के बारे में परवाह करूंगा, क्योंकि अगर फ़ाइल स्थानीय नहीं है, तो आप उपयोग करना चाहते हैं .Location वैसे भी, मेरे लिए निम्न कार्य करता है (ध्यान दें कि यह सबसे छोटा नहीं है) या तो:

    public static string GetAssemblyFullPath(Assembly assembly)
    {
        string codeBasePseudoUrl = assembly.CodeBase; // "pseudo" because it is not properly escaped
        if (codeBasePseudoUrl != null) {
            const string filePrefix3 = @"file:///";
            if (codeBasePseudoUrl.StartsWith(filePrefix3)) {
                string sPath = codeBasePseudoUrl.Substring(filePrefix3.Length);
                string bsPath = sPath.Replace('/', '\\');
                Console.WriteLine("bsPath: " + bsPath);
                string fp = Path.GetFullPath(bsPath);
                Console.WriteLine("fp: " + fp);
                return fp;
            }
        }
        System.Diagnostics.Debug.Assert(false, "CodeBase evaluation failed! - Using Location as fallback.");
        return Path.GetFullPath(assembly.Location);
    }

मुझे यकीन है कि कोई व्यक्ति बेहतर समाधानों के साथ आ सकता है, शायद कोई ऐसा समाधान भी ला सकता है जो CodeBase संपत्ति का उचित URL एन-डिकोडिंग करता है यदि यह एक स्थानीय मार्ग है, लेकिन यह देखते हुए कि कोई भी file:/// बंद कर file:/// और इसके साथ किया जाता है, मैं कहूंगा कि यह समाधान पर्याप्त रूप से अच्छा है, अगर निश्चित रूप से बदसूरत है।


आपको System.Uri.LocalPath का उपयोग करने की आवश्यकता है:

string localPath = new Uri("file:///D:/projects/MyApp/MyApp/bin/debug/MyApp.exe").LocalPath;

इसलिए यदि आप वर्तमान में निष्पादित विधानसभा का मूल स्थान चाहते हैं:

string localPath = new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath;

जटिल पथों सहित एक और समाधान:

    public static string GetPath(this Assembly assembly)
    {
        return Path.GetDirectoryName(assembly.GetFileName());
    }

    public static string GetFileName(this Assembly assembly)
    {
        return assembly.CodeBase.GetPathFromUri();
    }

    public static string GetPathFromUri(this string uriString)
    {
        var uri = new Uri(Uri.EscapeUriString(uriString));
        return String.Format("{0}{1}", Uri.UnescapeDataString(uri.PathAndQuery), Uri.UnescapeDataString(uri.Fragment));
    }

और परीक्षण:

    [Test]
    public void GetPathFromUriTest()
    {
        Assert.AreEqual(@"C:/Test/Space( )(h#)(p%20){[a&],[email protected],p%,+}.,/Release", @"file:///C:/Test/Space( )(h#)(p%20){[a&],[email protected],p%,+}.,/Release".GetPathFromUri());
        Assert.AreEqual(@"C:/Test/Space( )(h#)(p%20){[a&],[email protected],p%,+}.,/Release",  @"file://C:/Test/Space( )(h#)(p%20){[a&],[email protected],p%,+}.,/Release".GetPathFromUri());
    }

    [Test]
    public void AssemblyPathTest()
    {
        var asm = Assembly.GetExecutingAssembly();

        var path = asm.GetPath();
        var file = asm.GetFileName();

        Assert.IsNotEmpty(path);
        Assert.IsNotEmpty(file);

        Assert.That(File     .Exists(file));
        Assert.That(Directory.Exists(path));
    }

यह काम करना चाहिए:

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
Assembly asm = Assembly.GetCallingAssembly();
String path = Path.GetDirectoryName(new Uri(asm.EscapedCodeBase).LocalPath);

string strLog4NetConfigPath = System.IO.Path.Combine(path, "log4net.config");

मैं एक स्टैंडअलोन log4net.config फ़ाइल का उपयोग करके dll पुस्तकालयों के भीतर से लॉग इन करने में सक्षम होने के लिए इसका उपयोग कर रहा हूं।





codebase