c# मैं कोड में असेंबली का मार्ग कैसे प्राप्त करूं?




.net reflection (21)

मुझे संदेह है कि असली मुद्दा यह है कि आपका परीक्षण धावक आपकी असेंबली को एक अलग स्थान पर कॉपी कर रहा है। रनटाइम पर कोई रास्ता नहीं है कि यह कहने के लिए कि असेंबली की प्रतिलिपि बनाई गई थी, लेकिन आप संभवतः एक असेंबली को चलाने के लिए परीक्षण धावक को यह कहने के लिए कह सकते हैं कि यह कहां है और इसे छाया निर्देशिका में कॉपी नहीं करना है।

निश्चित रूप से प्रत्येक परीक्षण धावक के लिए ऐसा स्विच अलग होने की संभावना है।

क्या आपने अपने एक्सएमएल डेटा को अपनी टेस्ट असेंबली के अंदर संसाधनों के रूप में एम्बेड करने पर विचार किया है?

क्या असेंबली के लिए रास्ता पाने का कोई तरीका है जिसमें वर्तमान कोड रहता है? मैं कॉलिंग असेंबली का मार्ग नहीं चाहता, केवल कोड वाला एक।

मूल रूप से मेरे यूनिट परीक्षण को कुछ एक्सएमएल परीक्षण फ़ाइलों को पढ़ने की आवश्यकता होती है जो डीएलएल के सापेक्ष स्थित होते हैं। मैं परीक्षण डीएल को TestDriven.NET, MbUnit GUI या कुछ और से चलाने के बावजूद सही ढंग से हल करने का मार्ग चाहता हूं।

संपादित करें : लोग जो मैं पूछ रहा हूं उसे गलत समझना प्रतीत होता है।

मेरी टेस्ट लाइब्रेरी कहने में स्थित है

C: \ परियोजनाओं \ myapplication \ daotests \ बिन \ डीबग \ daotests.dll

और मैं यह रास्ता प्राप्त करना चाहता हूं:

C: \ परियोजनाओं \ myapplication \ daotests \ बिन \ डीबग \

जब मैं एमबीयूनीट गुई से भागता हूं तो तीन सुझाव अब तक विफल हो जाते हैं:

  • Environment.CurrentDirectory डायरेक्टरी सी: \ प्रोग्राम फ़ाइलें \ MbUnit देता है

  • System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location सी: \ दस्तावेज़ और सेटिंग्स \ george \ स्थानीय सेटिंग्स \ Temp \ .... \ DaoTests.dll देता है

  • System.Reflection.Assembly.GetExecutingAssembly().Location पिछले जैसा ही देता है।


मुझे स्थान के पुनर्प्राप्ति के लिए मेरा समाधान पर्याप्त लगता है।

var executingAssembly = new FileInfo((Assembly.GetExecutingAssembly().Location)).Directory.FullName;

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

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

मैं कुछ विन्यास फाइल के साथ डीएलएल फ़ाइल पुस्तकालयों को तैनात करने के लिए इसका उपयोग कर रहा हूं (यह DLL फ़ाइल के भीतर से लॉग 4नेट का उपयोग करना है)।


जहां तक ​​मैं कह सकता हूं, अधिकांश अन्य उत्तरों में कुछ समस्याएं हैं।

डिस्क-आधारित (वेब-आधारित के विपरीत) के लिए ऐसा करने का सही तरीका , गैर-जीएसीड असेंबली वर्तमान में निष्पादित असेंबली की CodeBase संपत्ति का उपयोग करना है।

यह एक यूआरएल ( file:// ) देता है। स्ट्रिंग मैनिपुलेशन या UnescapeDataString साथ घूमने के बजाय, इसे UnescapeDataString संपत्ति का लाभ उठाकर न्यूनतम गड़बड़ी के साथ परिवर्तित किया जा सकता है।

var codeBaseUrl = Assembly.GetExecutingAssembly().CodeBase;
var filePathToCodeBase = new Uri(codeBaseUrl).LocalPath;
var directoryPath = Path.GetDirectoryName(filePathToCodeBase);

इस बारे में कैसा है ...

string ThisdllDirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

फिर बस उस चीज़ को हैक करें जिसे आपको आवश्यकता नहीं है


इन सभी वर्षों में, किसी ने वास्तव में इसका उल्लेख नहीं किया है। एक ट्रिक जिसे मैंने भयानक स्वीकृति परीक्षण परियोजना से सीखा। चाल यह है कि आप मूल निर्देशिका खोजने के लिए असेंबली में डीबगिंग जानकारी का उपयोग करते हैं।

यह रिलीज मोड में काम नहीं करेगा, न ही ऑप्टिमाइज़ेशन सक्षम के साथ, न ही मशीन पर संकलित एक से अलग मशीन पर।

लेकिन यह आपको पथ मिलेगा जो स्रोत कोड फ़ाइल के स्थान से संबंधित हैं जो आप इसे कहते हैं

public static class PathUtilities
{
    public static string GetAdjacentFile(string relativePath)
    {
        return GetDirectoryForCaller(1) + relativePath;
    }
    public static string GetDirectoryForCaller()
    {
        return GetDirectoryForCaller(1);
    }


    public static string GetDirectoryForCaller(int callerStackDepth)
    {
        var stackFrame = new StackTrace(true).GetFrame(callerStackDepth + 1);
        return GetDirectoryForStackFrame(stackFrame);
    }

    public static string GetDirectoryForStackFrame(StackFrame stackFrame)
    {
        return new FileInfo(stackFrame.GetFileName()).Directory.FullName + Path.DirectorySeparatorChar;
    }
}

जॉन के जवाब के समान, लेकिन थोड़ी कम वर्बोज़ एक्सटेंशन विधि।

public static string GetDirectoryPath(this Assembly assembly)
{
    string filePath = new Uri(assembly.CodeBase).LocalPath;
    return Path.GetDirectoryName(filePath);            
}

अब आप कर सकते हैं:

var localDir = Assembly.GetExecutingAssembly().GetDirectoryPath();

या यदि आप पसंद करते हैं:

var localDir = typeof(DaoTests).Assembly.GetDirectoryPath();

इस बारे में क्या:

System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

आप AppDomain.CurrentDomain.RelativeSearchPath द्वारा बिन पथ प्राप्त कर सकते हैं


मैंने निम्नलिखित संपत्ति को परिभाषित किया है क्योंकि हम इसे अक्सर यूनिट परीक्षण में उपयोग करते हैं।

public static string AssemblyDirectory
{
    get
    {
        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
        UriBuilder uri = new UriBuilder(codeBase);
        string path = Uri.UnescapeDataString(uri.Path);
        return Path.GetDirectoryName(path);
    }
}

Assembly.Location संपत्ति कभी-कभी आपको NUnit (जहां एक अस्थायी फ़ोल्डर से चलती असेंबली) का उपयोग करते समय आपको कुछ मजाकिया परिणाम देता है, इसलिए मैं UriBuild.UnescapeDataString का उपयोग करना पसंद करता हूं जो आपको यूआरआई प्रारूप में पथ देता है, फिर UriBuild.UnescapeDataString File:// को हटा देता है File:// पर शुरुआत, और GetDirectoryName इसे सामान्य विंडोज प्रारूप में बदल देता है।


मैंने ये ढूंढ निकाला। वेब परियोजनाओं के बीच, यूनिट परीक्षण (नूनिट और रिशेर्पर टेस्ट धावक) ; मैंने पाया यह मेरे लिए काम किया।

मैं यह पता लगाने के लिए कोड ढूंढ रहा हूं कि निर्माण में कौन सी कॉन्फ़िगरेशन है, Debug/Release/CustomName । हां, #if DEBUGतो अगर कोई इसे सुधार सकता है !

संपादित करने और सुधारने के लिए स्वतंत्र महसूस करें।

ऐप फ़ोल्डर प्राप्त करना वेब जड़ों के लिए उपयोगी, परीक्षण फ़ाइलों के फ़ोल्डर को पाने के लिए unittests।

public static string AppPath
{
    get
    {
        DirectoryInfo appPath = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);

        while (appPath.FullName.Contains(@"\bin\", StringComparison.CurrentCultureIgnoreCase)
                || appPath.FullName.EndsWith(@"\bin", StringComparison.CurrentCultureIgnoreCase))
        {
            appPath = appPath.Parent;
        }
        return appPath.FullName;
    }
}

बिन फ़ोल्डर प्राप्त करना : प्रतिबिंब का उपयोग करके असेंबली निष्पादित करने के लिए उपयोगी। यदि निर्माण गुणों के कारण फाइलों की प्रतिलिपि बनाई गई है।

public static string BinPath
{
    get
    {
        string binPath = AppDomain.CurrentDomain.BaseDirectory;

        if (!binPath.Contains(@"\bin\", StringComparison.CurrentCultureIgnoreCase)
            && !binPath.EndsWith(@"\bin", StringComparison.CurrentCultureIgnoreCase))
        {
            binPath = Path.Combine(binPath, "bin");
            //-- Please improve this if there is a better way
            //-- Also note that apps like webapps do not have a debug or release folder. So we would just return bin.
#if DEBUG
            if (Directory.Exists(Path.Combine(binPath, "Debug"))) 
                        binPath = Path.Combine(binPath, "Debug");
#else
            if (Directory.Exists(Path.Combine(binPath, "Release"))) 
                        binPath = Path.Combine(binPath, "Release");
#endif
        }
            return binPath;
    }
}

मैं स्थान के बजाय विधानसभा.कोडबेस का उपयोग कर रहा हूं:

Assembly a;
a = Assembly.GetAssembly(typeof(DaoTests));
string s = a.CodeBase.ToUpper(); // file:///c:/path/name.dll
Assert.AreEqual(true, s.StartsWith("FILE://"), "CodeBase is " + s);
s = s.Substring(7, s.LastIndexOf('/') - 7); // 7 = "file://"
while (s.StartsWith("/")) {
    s = s.Substring(1, s.Length - 1);
}
s = s.Replace("/", "\\");

यह काम कर रहा है, लेकिन मुझे यकीन नहीं है कि यह 100% सही है। http://blogs.msdn.com/suzcook/archive/2003/06/26/assembly-codebase-vs-assembly-location.aspx पर पृष्ठ कहता है:

"कोडबेस उस स्थान पर एक यूआरएल है जहां फ़ाइल मिली थी, जबकि स्थान वह पथ है जहां इसे वास्तव में लोड किया गया था। उदाहरण के लिए, यदि इंटरनेट से असेंबली डाउनलोड की गई थी, तो इसका कोडबेस" http: // "से शुरू हो सकता है। , लेकिन इसका स्थान "सी: \" से शुरू हो सकता है। अगर फ़ाइल छाया-प्रतिलिपि बनाई गई थी, तो स्थान छाया प्रतिलिपि में फ़ाइल की प्रतिलिपि का मार्ग होगा। यह जानना भी अच्छा है कि कोडबेस की गारंटी नहीं है जीएसी में असेंबली के लिए सेट किया जाएगा। स्थान हमेशा डिस्क से लोड असेंबली के लिए सेट किया जाएगा। "

आप स्थान के बजाय कोडबेस का उपयोग करना चाह सकते हैं।


अतीत में मुझे NUnit में वही व्यवहार मिला। डिफ़ॉल्ट रूप से NUnit आपकी असेंबली को temp निर्देशिका में कॉपी करता है। आप इस व्यवहार को NUnit सेटिंग्स में बदल सकते हैं:

शायद TestDriven.NET और MbUnit GUI में एक ही सेटिंग है।


कोडबेस और यूएनसी नेटवर्क शेयरों का उपयोग करते समय मेरे लिए काम करने वाला एकमात्र समाधान था:

System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath);

यह सामान्य यूआरआई के साथ भी काम करता है।


मैं इसका उपयोग बिन निर्देशिका का मार्ग पाने के लिए करता हूं:

var i = Environment.CurrentDirectory.LastIndexOf(@"\");
var path = Environment.CurrentDirectory.Substring(0,i); 

आपको यह परिणाम मिलता है:

"सी: \ उपयोगकर्ता \ ricooley \ दस्तावेज़ \ दृश्य स्टूडियो 2010 \ प्रोजेक्ट्स \ Windows_Test_Project \ Windows_Test_Project \ bin"


var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var assemblyPath = assembly.GetFiles()[0].Name;
var assemblyDir = System.IO.Path.GetDirectoryName(assemblyPath);

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

Public Shared ReadOnly Property AssemblyDirectory() As String
    Get
        Dim codeBase As String = Assembly.GetExecutingAssembly().CodeBase
        Dim uriBuilder As New UriBuilder(codeBase)
        Dim assemblyPath As String = Uri.UnescapeDataString(uriBuilder.Path)
        Return Path.GetDirectoryName(assemblyPath)
    End Get
End Property

string path = Path.GetDirectoryName(typeof(DaoTests).Module.FullyQualifiedName);

विंडोज़ फॉर्म ऐप में, आप बस Application.StartupPath स्टार्टअपपाथ का उपयोग कर सकते हैं

लेकिन डीएलएल और कंसोल ऐप्स के लिए कोड याद रखना बहुत कठिन है ...

string slash = Path.DirectorySeparatorChar.ToString();
string root = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

root += slash;
string settingsIni = root + "settings.ini"

वर्तमान निर्देशिका जहां आप मौजूद हैं।

Environment.CurrentDirectory;  // This is the current directory of your application

यदि आप निर्माण के साथ .xml फ़ाइल को कॉपी करते हैं तो आपको इसे ढूंढना चाहिए।

या

System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly(typeof(SomeObject));

// The location of the Assembly
assembly.Location;

यह काम करना चाहिए, जब तक असेंबली छाया प्रतिलिपि नहीं है :

string path = System.Reflection.Assembly.GetExecutingAssembly().Location






reflection