คุณจะได้รับไดเร็กทอรีโปรเจ็กต์ปัจจุบันจากรหัส C # เมื่อสร้างงาน MSBuild แบบกำหนดเองได้อย่างไร


134

แทนที่จะรันโปรแกรมภายนอกด้วยพา ธ ฮาร์ดโค้ดฉันต้องการรับ Project Dir ปัจจุบัน ฉันกำลังเรียกโปรแกรมภายนอกโดยใช้กระบวนการในงานที่กำหนดเอง

ฉันจะทำอย่างไร AppDomain.CurrentDomain.BaseDirectory ให้ตำแหน่งของ VS 2008 แก่ฉัน

คำตอบ:


112

คุณสามารถลองหนึ่งในสองวิธีนี้

string startupPath = System.IO.Directory.GetCurrentDirectory();

string startupPath = Environment.CurrentDirectory;

บอกฉันทีว่าอันไหนเหมาะกับคุณกว่ากัน


86
ทั้งสองข้างต้นชี้ให้คุณไปที่ไดเร็กทอรี bin ดังนั้นหากคุณมีตัวอย่างเช่นไดเร็กทอรี bin สำหรับโซลูชันทั้งหมดของคุณมันจะชี้คุณไปที่นั่นและไม่ใช่ไดเร็กทอรีโปรเจ็กต์ของคุณ (หรือสองระดับด้านล่างไดเร็กทอรีโปรเจ็กต์ของคุณ)
matcheek

16
โซลูชันทั้งสองจะไม่ทำงานตามที่คาดไว้เมื่อใช้ Test Explorer
Gucu112

265
using System;
using System.IO;

// This will get the current WORKING directory (i.e. \bin\Debug)
string workingDirectory = Environment.CurrentDirectory;
// or: Directory.GetCurrentDirectory() gives the same result

// This will get the current PROJECT directory
string projectDirectory = Directory.GetParent(workingDirectory).Parent.FullName;

25
+1 สำหรับ Directory.GetParent () ดังนั้นเราจึงไม่ได้รับไดเรกทอรี \ bin \ Debug :)
Eystein Bye

5
จะเกิดอะไรขึ้นถ้าเราใช้ CPU เป้าหมายที่กำหนดเอง? ตัวอย่างเช่นถ้าฉันตั้งค่า build ของฉันเป็นเป้าหมาย x64 มันจะสร้างโฟลเดอร์อื่นขึ้นมาระหว่างไฟล์.
Samir Aguiar

3
นี่คือคำตอบที่ถูกต้อง คำตอบที่ยอมรับจะส่งคืนพา ธ ไปยังไดเร็กทอรี bin ซึ่งไม่ใช่ไดเร็กทอรีโปรเจ็กต์
pookie

คำตอบของ @ pookie ผิดซ้ำซากสำหรับกรณีของฉัน กำลังให้โฟลเดอร์ * / {project} / bin กับฉันฉันจึงต้องต่อไฟล์ .parent
Captain Prinny

1
ทำงานได้ดีและนี่ควรเป็นคำตอบที่ยอมรับ
Ashok kumar Ganesan

42

หากโปรเจ็กต์กำลังรันบน IIS express Environment.CurrentDirectoryอาจชี้ไปที่ตำแหน่งของ IIS Express (พา ธ เริ่มต้นคือC: \ Program Files (x86) \ IIS Express ) ไม่ใช่ที่ที่โปรเจ็กต์ของคุณอยู่


นี่อาจเป็นเส้นทางไดเรกทอรีที่เหมาะสมที่สุดสำหรับโครงการประเภทต่างๆ

AppDomain.CurrentDomain.BaseDirectory

นี่คือคำจำกัดความของ MSDN

รับไดเร็กทอรีฐานที่ตัวแก้ไขแอสเซมบลีใช้เพื่อตรวจสอบสำหรับแอสเซมบลี


21
9 ปีต่อมาและใครบางคนมีคำตอบที่แท้จริง
Jeff Davis

ไม่มี AppDomain ใน. NET Core คุณจะต้องทำอะไรแบบนี้ System.Runtime.Loader.AssemblyLoadContext.Default.Unloading + = context => InvokeBatchProcessors ();
เวลาแฝง

นอกจากนั้นคุณสามารถใช้ Visual Studio SDK และรับตำแหน่งจากโครงร่างการกำหนดค่าโซลูชันโดยใช้ DTE2
เวลาแฝง

2
@Latency มีอยู่ในโครงการ WPF. net core 3
Alexander

ใช่ฉันอ่านรายละเอียดแล้ว ไม่มีอะไรเหมือนกับ 3,0 ที่แน่นอน ฉันใช้มันมาตั้งแต่ไหน แต่ไร ยินดีเป็นอย่างยิ่ง. ฉันคิดว่าฉันโพสต์ก่อน 3.0 นี้แล้วดังนั้นขอบคุณสำหรับคำชี้แจง
Latency

18

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

System.IO.Path.GetFullPath(@"..\..\")

แน่นอนคุณต้องการบรรจุสิ่งนี้ไว้ในตรรกะการตรวจสอบความถูกต้อง / การจัดการข้อผิดพลาดบางประเภท


IMO เป็นวิธีที่ยืดหยุ่นที่สุด ฉันใช้สิ่งนี้จากการทดสอบหน่วยและการทดสอบการรวมซึ่งเส้นทางนั้นลึกกว่าของโฟลเดอร์เดียว
Soleil - Mathieu Prévot

นี่เป็นการให้รูทไดรฟ์ด้วยเหตุผลบางประการ
Captain Prinny

10

หากคุณต้องการทราบว่าไดเร็กทอรีที่โซลูชันของคุณตั้งอยู่คืออะไรคุณต้องทำสิ่งนี้:

 var parent = Directory.GetParent(Directory.GetCurrentDirectory()).Parent;
            if (parent != null)
            {
                var directoryInfo = parent.Parent;
                string startDirectory = null;
                if (directoryInfo != null)
                {
                    startDirectory = directoryInfo.FullName;
                }
                if (startDirectory != null)
                { /*Do whatever you want "startDirectory" variable*/}
            }

หากคุณปล่อยด้วยGetCurrrentDirectory()วิธีการเท่านั้นคุณจะได้รับโฟลเดอร์ build ไม่ว่าคุณจะทำการดีบักหรือปล่อย ฉันหวังว่านี่จะช่วยได้! หากคุณลืมเกี่ยวกับการตรวจสอบความถูกต้องจะเป็นดังนี้:

var startDirectory = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.FullName;

5

ฉันกำลังมองหาสิ่งนี้เช่นกัน ฉันมีโปรเจ็กต์ที่เรียกใช้ HWC และฉันต้องการให้เว็บไซต์ไม่อยู่ในโครงสร้างแอพ แต่ฉันไม่ต้องการเก็บไว้ในไดเร็กทอรี debug (หรือ release) FWIW ซึ่งเป็นโซลูชันที่ยอมรับ (และโซลูชันนี้ด้วย) ระบุเฉพาะไดเร็กทอรีที่เรียกใช้งานได้

เพื่อค้นหาไดเร็กทอรีนั้นฉันใช้

string startupPath = System.IO.Path.GetFullPath(".\\").

5

จากคำตอบของ Gucu112แต่สำหรับแอปพลิเคชัน. NET Core Console / Window ควรเป็น:

string projectDir = 
    Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\.."));

ฉันใช้สิ่งนี้ในโครงการ xUnit สำหรับแอปพลิเคชัน. NET Core Window


4

อีกวิธีหนึ่งในการทำเช่นนี้

string startupPath = System.IO.Directory.GetParent(@"./").FullName;

หากคุณต้องการรับเส้นทางไปยังโฟลเดอร์ bin

string startupPath = System.IO.Directory.GetParent(@"../").FullName;

อาจจะมีวิธีที่ดีกว่านี้ =)


4

วิธีแก้ปัญหาที่ไม่สมบูรณ์อีกวิธีหนึ่ง (แต่อาจใกล้เคียงกับความสมบูรณ์แบบมากกว่าวิธีอื่นเล็กน้อย):

    protected static string GetSolutionFSPath() {
        return System.IO.Directory.GetParent(System.IO.Directory.GetCurrentDirectory()).Parent.Parent.FullName;
    }
    protected static string GetProjectFSPath() {
        return String.Format("{0}\\{1}", GetSolutionFSPath(), System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);
    }

เวอร์ชันนี้จะส่งคืนโฟลเดอร์ของโปรเจ็กต์ปัจจุบันแม้ว่าโปรเจ็กต์ปัจจุบันจะไม่ใช่Startup Projectสำหรับโซลูชันก็ตาม

ข้อบกพร่องประการแรกคือฉันได้ข้ามการตรวจสอบข้อผิดพลาดทั้งหมด ที่สามารถแก้ไขได้ง่ายพอ แต่ควรเป็นปัญหาเฉพาะเมื่อคุณจัดเก็บโปรเจ็กต์ของคุณในไดเร็กทอรีรูทสำหรับไดรฟ์หรือใช้ทางแยกในเส้นทางของคุณ (และทางแยกนั้นเป็นลูกหลานของโฟลเดอร์โซลูชัน) ดังนั้นสถานการณ์นี้จึงไม่น่าเป็นไปได้ . ฉันไม่แน่ใจว่า Visual Studio สามารถจัดการการตั้งค่าเหล่านี้ได้หรือไม่

อีกปัญหาหนึ่ง (เป็นไปได้มากกว่า) ที่คุณอาจพบคือชื่อโครงการต้องตรงกับชื่อโฟลเดอร์สำหรับโปรเจ็กต์

ปัญหาอื่นที่คุณอาจมีคือโครงการต้องอยู่ในโฟลเดอร์โซลูชัน โดยปกติจะไม่ใช่ปัญหา แต่ถ้าคุณใช้Add Existing Project to Solutionตัวเลือกเพื่อเพิ่มโปรเจ็กต์ลงในโซลูชันนี่อาจไม่ใช่วิธีการจัดระเบียบโซลูชันของคุณ

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

แน่นอนว่าทั้งหมดนี้หมายความว่าคุณต้องไม่แก้ไขค่าเริ่มต้นสำหรับตัวเลือก ' Build-> Output pathหรือDebug-> Working directoryโครงการของคุณในกล่องโต้ตอบคุณสมบัติโครงการ



4

โซลูชันนี้ใช้งานได้ดีสำหรับฉันในการพัฒนาและบนเซิร์ฟเวอร์ TEST และ PROD ด้วยASP.NET MVC5 ผ่าน C # :

var projectDir = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);

หากคุณต้องการไดเร็กทอรีโปรเจ็กต์ในไฟล์คอนฟิกูเรชันโปรเจ็กต์ให้ใช้:

$(ProjectDir)

3

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

ขั้นแรกคุณต้องรวมเนมสเปซ Microsoft.Win32 เพื่อให้คุณสามารถทำงานกับรีจิสทรีได้:

using Microsoft.Win32;    // required for reading and / or writing the registry

นี่คือรหัสหลัก:

RegistryKey Projects_Key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\VisualStudio\9.0", false);
string DirProject = (string)Projects_Key.GetValue(@"DefaultNewProjectLocation");

หมายเหตุเกี่ยวกับคำตอบนี้:

ฉันใช้ Visual Studio 2008 Professional Edition หากคุณกำลังใช้เวอร์ชันอื่น (เช่น 2003, 2005, 2010 เป็นต้น) คุณอาจต้องแก้ไขส่วน 'เวอร์ชัน' ของสตริง SubKey (เช่น 8.0, 7.0 เป็นต้น)

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

  • dm

3

ฉันมีสถานการณ์ที่คล้ายกันและหลังจาก Googles ที่ไร้ผลฉันได้ประกาศสตริงสาธารณะซึ่งดัดแปลงค่าสตริงของเส้นทางการดีบัก / รีลีสเพื่อรับเส้นทางโครงการ ข้อดีของการใช้วิธีนี้คือเนื่องจากใช้ไดเร็กทอรีของ currect project จึงไม่สำคัญหากคุณกำลังทำงานจากไดเร็กทอรี debug หรือไดเร็กทอรีรีลีส:

public string DirProject()
{
    string DirDebug = System.IO.Directory.GetCurrentDirectory();
    string DirProject = DirDebug;

    for (int counter_slash = 0; counter_slash < 4; counter_slash++)
    {
        DirProject = DirProject.Substring(0, DirProject.LastIndexOf(@"\"));
    }

    return DirProject;
}

จากนั้นคุณจะสามารถโทรหาได้ทุกเมื่อที่ต้องการโดยใช้เพียงบรรทัดเดียว:

string MyProjectDir = DirProject();

สิ่งนี้ควรได้ผลในกรณีส่วนใหญ่


3

ใช้สิ่งนี้เพื่อรับไดเร็กทอรี Project (ใช้ได้กับฉัน):

string projectPath = 
    Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;

3
using System;
using System.IO;

// Get the current directory and make it a DirectoryInfo object.
// Do not use Environment.CurrentDirectory, vistual studio 
// and visual studio code will return different result:
// Visual studio will return @"projectDir\bin\Release\netcoreapp2.0\", yet 
// vs code will return @"projectDir\"
var currentDirectory = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);

// On windows, the current directory is the compiled binary sits,
// so string like @"bin\Release\netcoreapp2.0\" will follow the project directory. 
// Hense, the project directory is the great grand-father of the current directory.
string projectDirectory = currentDirectory.Parent.Parent.Parent.FullName;

2

ฉันใช้วิธีแก้ปัญหาต่อไปนี้เพื่อให้งานสำเร็จ:

string projectDir =
    Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\.."));

2

ลอง:

var pathRegex = new Regex(@"\\bin(\\x86|\\x64)?\\(Debug|Release)$", RegexOptions.Compiled);
var directory = pathRegex.Replace(Directory.GetCurrentDirectory(), String.Empty);

นี่เป็นวิธีการแก้ปัญหาที่แตกต่างจากที่อื่น ๆ โดยคำนึงถึงการสร้าง x86 หรือ x64 ที่เป็นไปได้


โซลูชันนี้เกือบจะมีสำหรับไฟล์ csproj ใหม่ด้วยเช่นกันซึ่ง TargetFramework รวมอยู่ในพา ธ
Glenn Watson

1
สำหรับรูปแบบสไตล์. netcore ใหม่ฉันมี Regex (@ "\\ bin (\\ x86 | \\ x64)? \ (Debug | Release) (\ [a-zA-Z0-9.] *)? $" , RegexOptions.Compiled)
Glenn Watson

1

ทางออกที่ดีที่สุด

string PjFolder1 =
    Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory).
        Parent.Parent.FullName;

โซลูชันอื่น ๆ

string pjFolder2 = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(
                System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)));

ทดสอบมัน AppDomain.CurrentDomain.BaseDirectory ทำงานให้ฉันในโครงการที่ผ่านมาตอนนี้ฉันได้รับโฟลเดอร์ดีบัก .... คำตอบที่ดีที่เลือกก็ไม่ทำงาน!

//Project DEBUG folder, but STILL PROJECT FOLDER
string pjDebugFolder = AppDomain.CurrentDomain.BaseDirectory;

//Visual studio folder, NOT PROJECT FOLDER
//This solutions just not work
string vsFolder = Directory.GetCurrentDirectory();
string vsFolder2 = Environment.CurrentDirectory;
string vsFolder3 = Path.GetFullPath(".\\");   

//Current PROJECT FOLDER
string ProjectFolder = 
    //Get Debug Folder object from BaseDirectory ( the same with end slash)
    Directory.GetParent(pjDebugFolder).
    Parent.//Bin Folder object
    Parent. //Project Folder object
    FullName;//Project Folder complete path

0

ถ้าคุณต้องการให้แน่ใจว่าคุณได้รับไดเร็กทอรีโปรเจ็กต์ต้นทางไม่ว่าจะตั้งค่าพา ธ เอาต์พุต bin เป็น:

  1. เพิ่มบรรทัดคำสั่งเหตุการณ์ก่อนสร้าง (Visual Studio: คุณสมบัติโครงการ -> สร้างเหตุการณ์):

    echo $(MSBuildProjectDirectory) > $(MSBuildProjectDirectory)\Resources\ProjectDirectory.txt

  2. เพิ่มProjectDirectory.txtไฟล์ลงใน Resources.resx ของโปรเจ็กต์ (หากยังไม่มีให้คลิกขวาที่โปรเจ็กต์ -> เพิ่มรายการใหม่ -> ไฟล์รีซอร์ส)

  3. เข้าถึงจากรหัสด้วยResources.ProjectDirectory.

-1

สิ่งนี้ใช้ได้กับการกำหนดค่า VS2017 w / SDK Core MSBuild

คุณต้อง NuGet ในแพ็คเกจ EnvDTE / EnvDTE80

อย่าใช้ COM หรือ interop อะไรก็ได้ .... ขยะ !!

 internal class Program {
    private static readonly DTE2 _dte2;

    // Static Constructor
    static Program() {
      _dte2 = (DTE2)Marshal.GetActiveObject("VisualStudio.DTE.15.0");
    }


    private static void FindProjectsIn(ProjectItem item, List<Project> results) {
      if (item.Object is Project) {
        var proj = (Project) item.Object;
        if (new Guid(proj.Kind) != new Guid(Constants.vsProjectItemKindPhysicalFolder))
          results.Add((Project) item.Object);
        else
          foreach (ProjectItem innerItem in proj.ProjectItems)
            FindProjectsIn(innerItem, results);
      }

      if (item.ProjectItems != null)
        foreach (ProjectItem innerItem in item.ProjectItems)
          FindProjectsIn(innerItem, results);
    }


    private static void FindProjectsIn(UIHierarchyItem item, List<Project> results) {
      if (item.Object is Project) {
        var proj = (Project) item.Object;
        if (new Guid(proj.Kind) != new Guid(Constants.vsProjectItemKindPhysicalFolder))
          results.Add((Project) item.Object);
        else
          foreach (ProjectItem innerItem in proj.ProjectItems)
            FindProjectsIn(innerItem, results);
      }

      foreach (UIHierarchyItem innerItem in item.UIHierarchyItems)
        FindProjectsIn(innerItem, results);
    }


    private static IEnumerable<Project> GetEnvDTEProjectsInSolution() {
      var ret = new List<Project>();
      var hierarchy = _dte2.ToolWindows.SolutionExplorer;
      foreach (UIHierarchyItem innerItem in hierarchy.UIHierarchyItems)
        FindProjectsIn(innerItem, ret);
      return ret;
    }


    private static void Main() {
      var projects = GetEnvDTEProjectsInSolution();
      var solutiondir = Path.GetDirectoryName(_dte2.Solution.FullName);

      // TODO
      ...

      var project = projects.FirstOrDefault(p => p.Name == <current project>);
      Console.WriteLine(project.FullName);
    }
  }

-6

Directory.GetParent (Directory.GetCurrentDirectory ()). Parent.Parent.Parent.Parent.FullName

จะให้ไดเรกทอรีโครงการ


77
จริงๆ? ฉันคิดว่าคุณไม่มีพ่อแม่
ฌอน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.