ฉันจะได้รับเส้นทางของการชุมนุมรหัสอยู่ใน?


781

มีวิธีที่จะได้รับเส้นทางสำหรับการชุมนุมที่รหัสปัจจุบันอยู่หรือไม่? ฉันไม่ต้องการเส้นทางของชุดการโทรเพียงอันเดียวที่มีรหัส

โดยทั่วไปการทดสอบหน่วยของฉันต้องอ่านไฟล์ทดสอบ xml บางไฟล์ซึ่งตั้งอยู่สัมพันธ์กับ dll ฉันต้องการเส้นทางที่จะแก้ไขอย่างถูกต้องเสมอโดยไม่คำนึงถึงว่า dll การทดสอบรันจาก TestDriven.NET, MbUnit GUI หรืออย่างอื่น

แก้ไข : ผู้คนดูเหมือนจะเข้าใจผิดในสิ่งที่ฉันขอ

ห้องสมุดทดสอบของฉันตั้งอยู่ในคำพูด

C: \ โครงการ \ MyApplication \ daotests \ bin \ Debug \ daotests.dll

และฉันต้องการเส้นทางนี้:

C: \ โครงการ \ MyApplication \ daotests \ bin \ Debug \

ข้อเสนอแนะสามข้อที่ทำให้ฉันล้มเหลวเมื่อฉันเรียกใช้จาก MbUnit Gui:

  • Environment.CurrentDirectory ให้c: \ Program Files \ MbUnit

  • System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location ให้C: \ Documents และ Settings \ george \ Local Settings \ Temp \ .... \ DaoTests.dll

  • System.Reflection.Assembly.GetExecutingAssembly().Location ให้เหมือนกับก่อนหน้านี้


102
นี่คือวิธีการแก้ปัญหาของคุณ: var dir = AppDomain.CurrentDomain.BaseDirectory;
Jalal El-Shaer

7
นี่ควรเป็นทางออกที่ยอมรับได้ AppDomain.CurrentDomain.BaseDirectory เป็นวิธีการที่ถูกต้อง
aBetterGamer

ดูข้อมูลที่เกี่ยวข้อง: การค้นหา - my-main-executables- path-using-assembly-vs-appdomain
nawfal

2
ฉันมาที่นี่เพื่อค้นหาโซลูชันสำหรับแพ็คเกจ nuget เพื่ออ่านไฟล์ JSON จากไดเรกทอรี pacakge ดูเหมือนว่าเมื่อมีการดำเนินการแพคเกจ nuget "AppDomain.CurrentDomain.BaseDirectory" ชี้ไปที่ไดเรกทอรีโครงการที่กำลังทำงานอยู่และไม่ใช่ไดเรกทอรีแพคเกจ nuget ดูเหมือนว่าจะไม่มีการกำหนดเป้าหมายไปยังไดเรกทอรีแพ็คเกจ nuget อย่างถูกต้อง
ลูคัส

@Lucas ไม่ได้เพราะนั่นไม่ใช่สิ่งที่คำถามนี้เกี่ยวกับ (ในความเป็นจริงเมื่อมีการถาม nuget ไม่มีอยู่) - อย่าลังเลที่จะเริ่มคำถามใหม่และ ping ฉันในที่นั่น แต่ฉันสามารถบอกคุณได้ทันทีว่า มันเป็นไปไม่ได้ในกรณีส่วนใหญ่ สำหรับโครงการส่วนใหญ่ไดเรกทอรี nuget อยู่packagesถัดจากไฟล์ sln แต่เมื่อคุณรวบรวมและแจกจ่ายสิ่งต่าง ๆ ไม่มีไฟล์ sln และไม่มีไดเรกทอรีแพ็คเกจ ระหว่างการรวบรวมสิ่งที่ต้องการ (แต่ไม่ใช่ทุกอย่าง) จะถูกคัดลอกไปยังไดเรกทอรี bin ทางออกที่ดีที่สุดของคุณคือใช้สคริปต์ postbuild เพื่อคัดลอกไฟล์ที่คุณต้องการ
George Mauer

คำตอบ:


1036

ฉันได้กำหนดคุณสมบัติต่อไปนี้เนื่องจากเราใช้สิ่งนี้บ่อยครั้งในการทดสอบหน่วย

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 (ที่ประกอบวิ่งออกจากโฟลเดอร์ชั่วคราว) ดังนั้นฉันชอบที่จะใช้CodeBaseซึ่งจะช่วยให้คุณเส้นทางในรูปแบบ URI แล้วUriBuild.UnescapeDataStringเอาFile://ที่จุดเริ่มต้นและGetDirectoryNameการเปลี่ยนแปลงเป็นรูปแบบที่หน้าต่างปกติ .


29
นี่เป็นปัญหาหนึ่งที่ฉันเจอถ้าชื่อไดเรกทอรีของคุณคือ: c: \ My% 20Directory Uri.UnescapeDataString จะกลับมา: c: \ My Directory นี่หมายความว่า File.Exists ("c: \ My Directory \ MyFile.txt ") จะคืนค่าเท็จเนื่องจากเส้นทางที่ถูกต้องเป็นจริง" c: \ My% 20Directory \ MyFile.txt "ฉันเจอสิ่งนี้เนื่องจากเส้นทาง SVN ของเรามีช่องว่างอยู่และเมื่อเราตรวจสอบมันเข้ารหัสช่องว่าง
row1

5
ระวังเมื่อคุณใช้สิ่งนี้เพื่อตรวจสอบ File.Exist () เนื่องจากวิธีนี้จะคืนค่าเท็จบนเส้นทาง UNC ใช้คำตอบของ @ Keith แทน
อาริโซน่า

3
ไม่ทราบว่าคุณสามารถทำให้คงที่ก่อนที่สาธารณะ ดีใจที่ได้ทราบและฉันคิดว่าฉันชอบการอ่าน
Valamas

5
หมายเหตุ: สิ่งนี้ไม่สามารถใช้ได้กับตำแหน่งเครือข่าย (เช่น \\ REMOT_EPC \ Folder)
Muxa

5
นอกจากนี้สิ่งนี้จะไม่ทำงานหากไดเรกทอรีมีเครื่องหมายหมายเลข '#' อยู่ในนั้น อนุญาตให้ใช้เครื่องหมายตัวเลขในไดเรกทอรีและชื่อไฟล์ใน Windows
Huemac

321

สิ่งนี้ช่วยได้ไหม?

//get the full location of the assembly with DaoTests in it
string fullPath = System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location;

//get the folder that's in
string theDirectory = Path.GetDirectoryName( fullPath );

ดูการแก้ไขของฉันไม่ใช่สิ่งนี้แปลกเกี่ยวกับวิธีที่ MbUnit ทำสิ่งต่างๆหรือไม่
George Mauer

3
ตั้งค่าไฟล์ xml ให้เป็นเนื้อหาคัดลอกด้วย dll หรือทรัพยากรอ่านจาก dll
Keith

22
หรือเพียงแค่typeof(DaoTests).Assembly
slaks

4
@SLaks @JohnySkovdal @Keith: Hey guys Assembly.GetExecutingAssembly()ใช้ มัน"ได้รับการชุมนุมที่มีรหัสที่กำลังดำเนินการ" (จากคำอธิบายวิธีการ) ฉันใช้สิ่งนี้ใน AddIn ของฉัน " EntitiesToDTOs " ดูAssemblyHelper.csสำหรับตัวอย่างจริง
kzfabi

4
มีปัญหากับการโพสต์โดย @John Silby เนื่องจากดูเหมือนว่าจะทำงานกับเส้นทาง UNC ... เช่น \\ Server \ Folder \ File.ext อันนี้ทำอุบาย +1
บลูเบอร์รี่

312

มันง่ายอย่างนี้:

var dir = AppDomain.CurrentDomain.BaseDirectory;

11
นี่ควรเป็นทางออกที่ยอมรับได้ AppDomain.CurrentDomain.BaseDirectory เป็นวิธีการที่ถูกต้อง
aBetterGamer

5
ขอบคุณที่นำความสนใจของฉันกลับมาที่นี่ - ไม่แน่ใจว่ามีให้ในเวลาที่ฉันถามคำถาม แต่ตอนนี้
George Mauer

120
ไม่ผิด สิ่งนี้จะคืนค่าพา ธ ของจุดเริ่มต้นดั้งเดิมไม่ใช่รหัสที่กำลังดำเนินการในปัจจุบัน หากคุณโหลดแอสเซมบลีด้วยตนเองจากพา ธ ที่แตกต่างกันหรือถ้าแอสเซมบลีที่ถูกโหลดจาก GAC มันจะส่งคืนผลลัพธ์ที่ผิด คำตอบนี้เป็นที่ถูกต้อง: stackoverflow.com/a/283917/243557Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)เร็วยังคงเป็น
nathanchere

9
จริง ๆ แล้วสิ่งนี้จะไม่ทำงานในเว็บแอปพลิเคชั่น แต่เท่าที่ฉันได้พบการเสริมต่อไปนี้ควรใช้กับแอปพลิเคชันทุกประเภท:AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory
Ilya Chernomordik

4
สิ่งนี้ยอดเยี่ยมสำหรับการทดสอบหน่วยหากคุณต้องการได้รับเส้นทาง bin ดั้งเดิมของชุดทดสอบของคุณ (เช่นเพื่อเข้าถึงไฟล์ข้อมูลเสริมในโฟลเดอร์ย่อย) ชุดทดสอบเป็นจุดเริ่มต้นของรหัสของคุณ
MarioDS

68

เช่นเดียวกับคำตอบของ John แต่วิธีการขยาย verbose น้อยกว่าเล็กน้อย

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

6
คุณไม่ได้มีความหมายassemblyแทนAssembly.GetExecutingAssembly()?
Dude Pascalou

3
เมื่อ Dude ชี้ให้เห็นคุณผ่านการโต้แย้งและไม่สามารถใช้มันได้
Chris Moschini

4
คำตอบนี้เป็นเพียงผิดธรรมดาสำหรับคำถามที่อยู่ในมือ รุ่นที่แก้ไขของคำตอบนี้จะให้เส้นทางของแอสเซมบลีที่กำหนด อย่างไรก็ตามที่นี่เรากำลังมองหาชุดประกอบที่เรียกใช้งานโดยเฉพาะดังนั้นการส่งผ่านชุดประกอบจึงไม่สมเหตุสมผล วิธีการขยายเป็นเครื่องมือที่ผิดสำหรับงาน
Edward Brey

46

ทางออกเดียวที่ทำงานสำหรับฉันเมื่อใช้ CodeBase และเครือข่าย UNC ร่วมกันคือ:

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

นอกจากนี้ยังทำงานร่วมกับ URI ปกติเช่นกัน


5
นี่ควรเป็นคำตอบที่ยอมรับได้ มันน่ารำคาญจริง ๆ ที่ codebase เริ่มต้นไม่จัดการ UNC ที่ถูกต้อง
Daniel Gilbert

สิ่งนี้จะพังลงเมื่อโฟลเดอร์นั้นมีช่องว่างและพระเจ้าทรงรู้ว่าตัวละครอื่น ๆ ...
MarioDS

1
ฉันใช้มันมากและพบว่ามีสถานการณ์หนึ่งที่มันล้มเหลว: หากโค้ดของตัวเองเป็นส่วนหนึ่งของแพ็คเกจ NuGet ซึ่งแอพพลิเคชั่นจะใช้งาน! เราสามารถรองรับสถานการณ์ที่มากเกินไปโดยการแทนที่โดยGetExecutingAssembly() GetCallingAssembly()
Timo

@Timo: คุณตรวจสอบแล้วว่าการเปลี่ยนแปลงนี้มีผลข้างเคียงหรือไม่? ถ้าเป็นเช่นนั้นโปรดแก้ไขคำตอบเพื่อรวมการแก้ไข
Ignacio Soler Garcia

@IgnacioSolerGarcia น่าเศร้าฉันต้องรายงานว่ามันใช้งานได้เพียงชั้นเดียวลึก ๆ นั่นคือมันล้มเหลวถ้าแพ็คเกจ NuGet ถูกเรียกโดยแพ็คเกจอื่นของ NuGet! ตอนนี้ฉันกำลังใช้นี้ (จากความคิดเห็นในหน้านี้โดย AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectoryChernomordik): ส่วนแรกสำหรับเว็บแอปพลิเคชันและส่วนที่สองสำหรับแอปพลิเคชันอื่น
Timo

32

สิ่งนี้จะได้ผลเว้นแต่ว่าการชุมนุมจะถูกคัดลอกเงา :

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


11

ฉันสงสัยว่าปัญหาจริงที่นี่คือนักทดสอบของคุณกำลังคัดลอกชุดของคุณไปยังตำแหน่งอื่น ไม่มีวิธีรันไทม์ที่จะบอกว่าชุดประกอบถูกคัดลอกมาจากที่ใด แต่คุณสามารถพลิกสวิตช์เพื่อบอกให้ผู้ทดสอบทดสอบเรียกใช้ชุดประกอบจากตำแหน่งที่อยู่และไม่คัดลอกไปยังไดเรกทอรีเงา

แน่นอนว่าสวิตช์แต่ละตัวมีความแตกต่างกันไปตามแต่ละหลักสูตร

คุณถือว่าการฝังข้อมูล XML ของคุณเป็นทรัพยากรภายในชุดทดสอบของคุณหรือไม่


+1 สำหรับการชี้ให้เห็นปัญหาด้วยการคัดลอกเงา Assembly.CodeBaseแต่ก็เป็นไปได้แน่นอนในการกำหนดสถานที่เดิมจาก
tm1

11
AppDomain.CurrentDomain.BaseDirectory

ทำงานร่วมกับ MbUnit GUI


สิ่งนี้ใช้งานได้ดีเยี่ยมสำหรับการเขียนไฟล์ที่เกี่ยวข้องกับไดเรกทอรีรูทในแอปพลิเคชันเว็บ asp.net
Philip Pittle

ฉันพบว่าสิ่งนี้ใช้ได้ดีที่สุดโดยทั่วไป เลือกถ้าคุณไม่แน่ใจ
Erik Bergstedt

10

ฉันเชื่อว่าสิ่งนี้จะใช้ได้กับแอปพลิเคชันประเภทใดก็ได้:

AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory

1
การทดลองของฉันแสดงให้เห็นว่านี่เป็นคำตอบที่เข้าใจผิดได้มากที่สุดไม่เพียง แต่ครอบคลุมเว็บและแอปพลิเคชันคอนโซลเท่านั้น แต่ยังเรียกร้องจากการทดสอบหน่วยและแพ็คเกจ NuGet
Timo

8

เท่าที่ฉันสามารถบอกได้คำตอบอื่น ๆ ส่วนใหญ่มีปัญหาเล็กน้อย

วิธีที่ถูกต้องในการทำเช่นนี้สำหรับดิสก์ที่ใช้ (ซึ่งต่างจากเว็บ) แอสเซมบลีที่ไม่ใช่ GACedคือการใช้CodeBaseคุณสมบัติของแอสเซมบลีที่กำลังทำงานอยู่ในปัจจุบัน

ส่งคืน URL ( file://) แทนที่จะ messing รอบด้วยการจัดการสตริงหรือUnescapeDataStringนี้สามารถแปลงที่มีความยุ่งยากน้อยที่สุดโดยใช้ประโยชน์จากทรัพย์สินของLocalPathUri

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

1
ไม่ทำงานหากเส้นทางมี#( EscapedCodeBaseทำงานได้ แต่ EscapedCodeBase ไม่ทำงานหากเส้นทางมีเช่น%20คำต่อคำ (ซึ่งเป็นลำดับอักขระที่ได้รับอนุญาตในเส้นทาง Windows)
มาร์ตินบา

ถ้าเราต้องการที่จะมีรหัสนี้ในแพคเกจ NuGet เราสามารถแก้ไขสถานการณ์ที่โดยการแทนที่โดยGetExecutingAssembly() GetCallingAssembly()
Timo

8

แล้ว ...

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

จากนั้นก็ตัดสิ่งที่คุณไม่ต้องการออก



7

นี่คือพอร์ต VB.NET ของรหัสของ John Sibly Visual Basic ไม่คำนึงถึงตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก

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

6

ตลอดหลายปีที่ผ่านมาไม่มีใครพูดถึงเรื่องนี้ เคล็ดลับที่ฉันเรียนรู้จากโครงการ ApprovalTests ที่ยอดเยี่ยม เคล็ดลับคือคุณใช้ข้อมูลการดีบักในชุดประกอบเพื่อค้นหาไดเรกทอรีต้นฉบับ

สิ่งนี้จะไม่ทำงานในโหมด RELEASE หรือเปิดใช้งานการปรับให้เหมาะสมที่สุดหรือบนเครื่องที่แตกต่างจากที่รวบรวมไว้

แต่คุณจะได้รับพา ธ ที่สัมพันธ์กับตำแหน่งของไฟล์ซอร์สโค้ดที่คุณโทรหา

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

5

ไดเรกทอรีปัจจุบันที่คุณมีอยู่

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;

นี้จะเป็นปัญหาถ้าการชุมนุมได้รับเงาคัดลอก
ใช้จ่าย

1520! Environment.CurrentDirectoryทำงานได้ถ้าคุณใช้การสะท้อนในคลาสงาน MSBuild ซึ่งแอสเซมบลีการดำเนินการอยู่ใน GAC และรหัสของคุณอยู่ที่อื่น
Raven vulcan

4
โดยทั่วไป CurrentDirectory ไม่ได้บอกคุณว่าไฟล์เอ็กซิบิชั่นของคุณอยู่ที่ไหน นั่นไม่ใช่สิ่งที่มันใช้สำหรับ มันเกิดขึ้นบ่อยครั้งจะเป็นที่ตั้งเดียวกันกับที่โปรแกรมเรียกทำงานอยู่ดังนั้นโปรแกรมเมอร์จำนวนมากจึงไม่เข้าใจความแตกต่าง จากนั้นพวกเขาก็จบลงด้วยการสร้างปัญหาให้กับผู้ใช้บางรายที่คาดว่าแอปพลิเคชั่นจะเข้าใจการใช้ CurrentDirectory ที่เหมาะสม
Bent Tranberg

5

ฉันใช้ Assembly.CodeBase แทนตำแหน่ง:

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พูดว่า:

"CodeBase เป็น URL ไปยังตำแหน่งที่พบไฟล์ในขณะที่ Location คือพา ธ ที่โหลดจริงตัวอย่างเช่นหากแอสเซมบลีถูกดาวน์โหลดจากอินเทอร์เน็ต CodeBase อาจเริ่มต้นด้วย" http: // " แต่ตำแหน่งของมันอาจเริ่มต้นด้วย "C: \" หากไฟล์ถูกคัดลอกเงาตำแหน่งจะเป็นพา ธ ไปยังสำเนาของไฟล์ใน shadow copy dir นอกจากนี้ยังเป็นการดีที่จะทราบว่า CodeBase ไม่รับประกัน ที่จะตั้งค่าสำหรับแอสเซมบลีใน GAC ตำแหน่งจะถูกตั้งค่าสำหรับแอสเซมบลีที่โหลดจากดิสก์เสมอ "

คุณอาจต้องการใช้ CodeBase แทนตำแหน่ง


1
@Kiquenet: มีโค้ดมากสำหรับการแปลง URI ให้เป็นพา ธ แน่นอนว่าควรได้รับการปรับปรุง ดูคำตอบของ Mike Schall หรือ SoMoS คุณไม่ควรพยายามแปลง URIs ในระดับสตริง แต่ควรใช้วัตถุที่เหมาะสมแทน ตกลงมันยังงุ่มง่ามที่ Assembly.CodeBase ส่งคืนสตริงแทนวัตถุที่เหมาะสมกว่าเช่น URI หรือ FileInfo
เซเว่น


2

คำตอบที่เสนอทั้งหมดทำงานเมื่อนักพัฒนาสามารถเปลี่ยนรหัสเพื่อรวมข้อมูลโค้ดที่ต้องการ แต่ถ้าคุณต้องการทำเช่นนี้โดยไม่เปลี่ยนรหัสใด ๆ คุณสามารถใช้ Process Explorer ได้

มันจะแสดงรายการ dll ที่กำลังดำเนินการทั้งหมดบนระบบคุณอาจต้องกำหนดรหัสกระบวนการของแอปพลิเคชันที่ทำงานอยู่ของคุณ แต่โดยปกติจะไม่ยากเกินไป

ฉันได้เขียนคำอธิบายเต็มรูปแบบของวิธีการทำเช่นนี้สำหรับ dll ภายใน II - http://nodogmablog.bryanhogan.net/2016/09/locating-and-checking-an-executing-dll-on-a-running-web -Server /


โปรดทราบว่าก่อนอื่นรหัสในบทความนั้นค่อนข้างเป็นธรรม IIS และที่สองจะให้ (ผมเชื่อว่า) ที่กำลังโหลดทั้งหมดในขณะนี้ไม่ใช่สิ่งที่กำลังทำงานอยู่ในช่วงเวลาหนึ่ง
George Mauer

ตัวอย่างที่ให้มาเกี่ยวข้องกับ iis แต่มีขั้นตอนเดียวกันนี้หาก dll กำลังทำงานในกระบวนการที่อยู่นอก iis เป็นเพียงเรื่องของการระบุรหัสกระบวนการ ฉันจะอัปเดตบทความเพื่อทราบว่า ขอบคุณสำหรับคำแนะนำ
ไบรอัน

2

ในแอป windows form คุณสามารถใช้ Application.StartupPath

แต่สำหรับ DLLs และแอพคอนโซลนั้นจำได้ยากกว่า ...

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

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


1

คุณจะได้รับไดเรกทอรีที่ไม่ถูกต้องหากเส้นทางมีสัญลักษณ์ '#' ดังนั้นฉันใช้การแก้ไขคำตอบ John Sibly นั่นคือการรวมกัน UriBuilder.Path และ UriBuilder.Fragment:

public static string AssemblyDirectory
{
    get
    {
        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
        UriBuilder uri = new UriBuilder(codeBase);
        //modification of the John Sibly answer    
        string path = Uri.UnescapeDataString(uri.Path.Replace("/", "\\") + 
          uri.Fragment.Replace("/", "\\"));
        return Path.GetDirectoryName(path);
     }
}

0

นี่คือสิ่งที่ฉันมาด้วย ในระหว่างโครงการเว็บการทดสอบหน่วย (nunit และตัวทดสอบ resharper) ; ฉันพบว่ามันใช้งานได้สำหรับฉัน

ฉันได้มองหารหัสเพื่อตรวจสอบว่ามีการสร้างการกำหนดค่า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;
    }
}

กำลังรับโฟลเดอร์ bin : มีประโยชน์สำหรับการเรียกใช้งานชุดประกอบโดยใช้การสะท้อน หากไฟล์ถูกคัดลอกที่นั่นเนื่องจากคุณสมบัติการสร้าง

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

0

สิ่งนี้น่าจะใช้ได้:

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 พร้อมกับไฟล์การกำหนดค่าบางอย่าง (นี่คือการใช้ log4net จากภายในไฟล์ DLL)


สิ่งที่fileMapใช้สำหรับที่นี่
George Mauer

0

ฉันพบวิธีแก้ปัญหาที่เพียงพอสำหรับการดึงข้อมูลตำแหน่ง

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

นี่เป็นหนึ่งในคำตอบที่ได้รับความนิยมสูงสุดและถูกกล่าวถึงอย่างชัดเจนในคำถามว่าเป็นสิ่งที่ไม่สามารถใช้งานได้ในสถานการณ์นี้
George Mauer

ต้องขออภัยที่พลาด! เห็นได้ชัดว่าฉันไม่ได้อ่านอย่างละเอียด
Tez Wingfield

0

NUnitในอดีตฉันเคยมีพฤติกรรมแบบเดียวกัน โดยค่าเริ่มต้นNUnitคัดลอกแอสเซมบลีของคุณลงในไดเรกทอรีชั่วคราว คุณสามารถเปลี่ยนพฤติกรรมนี้ได้ในการNUnitตั้งค่า:

ป้อนคำอธิบายรูปภาพที่นี่

อาจTestDriven.NETและMbUnitGUI มีการตั้งค่าเดียวกัน


-3

ฉันใช้สิ่งนี้เพื่อรับเส้นทางไปยังไดเรกทอรีช่องเก็บ:

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

คุณได้รับผลลัพธ์นี้:

"c: \ users \ ricooley \ Documents \ visual studio 2010 \ Projects \ Windows_Test_Project \ Windows_Test_Project \ bin"


6
ฉันไม่เห็นเหตุผลที่จะหลีกเลี่ยง Path.getDirectoryName ที่นี่
Max Keller

@ MaxKeller หากคุณไม่เห็นเหตุผลก็ไม่ได้หมายความว่าถูกต้อง วิธีการอื่นของ Path.GetDirectoryName นี้เร็วกว่าสิบเท่า
Ruslan Veselov

-3

แอปพลิเคชั่นเว็บ?

Server.MapPath("~/MyDir/MyFile.ext")

2
@ Christiandev นี้เป็นคำตอบ แต่มันอาจจะเป็นคำตอบสำหรับคำถามที่ผิด จากคำถามมันค่อนข้างชัดเจนว่านี่ไม่ใช่เว็บแอปพลิเคชั่น แต่แอสเซมบลีที่ทำงานด้วย MbUnit ที่ถูกกล่าวว่าคำตอบยังไม่ถูกต้องเนื่องจากการคัดลอกเงา Asp.Net (แม้ว่าอาจเป็นสิ่งที่มีคนเชื่อมโยงไปถึงคำถามนี้กำลังมองหา)
George Mauer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.