Làm thế nào để bạn có được thư mục dự án hiện tại từ mã C # khi tạo một tác vụ MSBuild tùy chỉnh?


133

Thay vì chạy một chương trình bên ngoài với đường dẫn được mã hóa cứng, tôi muốn lấy Project Dir hiện tại. Tôi đang gọi một chương trình bên ngoài bằng cách sử dụng một quá trình trong tác vụ tùy chỉnh.

Làm thế nào tôi có thể làm điều đó? AppDomain.CienDomain.BaseDirectory chỉ cho tôi vị trí của VS 2008.

Câu trả lời:


112

Bạn có thể thử một trong hai phương pháp này.

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

string startupPath = Environment.CurrentDirectory;

Nói cho tôi biết, cái nào có vẻ tốt hơn với bạn


85
Hai mục trên đưa bạn đến thư mục bin, vì vậy, nếu bạn có một thư mục bin cho toàn bộ giải pháp của mình, nó sẽ chỉ bạn đến đó và KHÔNG đến thư mục dự án của bạn (hoặc hai cấp độ DƯỚI thư mục dự án của bạn)
matcheek

16
Cả hai giải pháp sẽ không hoạt động như mong đợi khi sử dụng Test Explorer.
Gucu112

264
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 cho Directory.GetParent () vì vậy chúng tôi không nhận được thư mục \ bin \ Debug :)
Eystein Bye

5
Điều gì xảy ra nếu chúng ta sử dụng CPU mục tiêu tùy chỉnh? Chẳng hạn, nếu tôi đặt bản dựng của mình thành đích x64, nó sẽ tạo một thư mục khác ở giữa chúng.
Samir Aguiar

3
Đây là câu trả lời chính xác. Câu trả lời được chấp nhận trả về đường dẫn đến thư mục bin, đây KHÔNG phải là thư mục dự án.
pookie

Câu trả lời của @ pookie là đệ quy sai cho trường hợp của tôi. Điều này mang lại cho tôi thư mục * / {project} / bin, vì vậy tôi cần nối một .parent.
Thuyền trưởng Prinny

1
Hoạt động tốt và đây phải là câu trả lời được chấp nhận
Ashok kumar Ganesan

41

Nếu một dự án đang chạy trên IIS Express, thì Environment.CurrentDirectorycó thể trỏ đến nơi IIS Express được đặt (đường dẫn mặc định sẽ là C: \ Program Files (x86) \ IIS Express ), chứ không phải nơi dự án của bạn nằm.


Đây có lẽ là đường dẫn thư mục phù hợp nhất cho các loại dự án.

AppDomain.CurrentDomain.BaseDirectory

Đây là định nghĩa MSDN.

Lấy thư mục cơ sở mà trình phân giải lắp ráp sử dụng để thăm dò các cụm.


20
9 năm sau và ai đó thực sự có câu trả lời thực sự.
Jeff Davis

Không có AppDomain trong .NET Core. Bạn sẽ phải làm một cái gì đó như thế này. System.R nb.Loader.AssuggingLoadContext.Default.Unloading + = bối cảnh => InvokeBatchProcessors ();
Độ trễ

Ngoài ra, bạn có thể sử dụng SDK Visual Studio và lấy vị trí từ bố trí cấu hình giải pháp bằng DTE2.
Độ trễ

2
@Latency có trong một dự án WPF lõi 3 .net
Alexander

Vâng, tôi đọc thông số kỹ thuật. Không có gì giống như 3.0 chắc chắn. Tôi đã sử dụng nó kể từ đó. Rất hài lòng. Tôi nghĩ rằng tôi đã đăng bài này trước 3.0 vì vậy cảm ơn đã làm rõ.
Độ trễ

18

Điều này cũng sẽ cung cấp cho bạn thư mục dự án bằng cách điều hướng hai cấp độ từ thư mục thực thi hiện tại (điều này sẽ không trả về thư mục dự án cho mỗi bản dựng, nhưng đây là phổ biến nhất).

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

Tất nhiên bạn sẽ muốn chứa cái này bên trong một số loại logic xử lý xác thực / xử lý lỗi.


IMO đây là phương pháp linh hoạt nhất. Tôi đang sử dụng điều này từ các bài kiểm tra đơn vị và kiểm tra tích hợp, đường dẫn nào thực sự sâu hơn của một thư mục.
Soleil - Mathieu Prévot

Điều này là cho tôi ổ đĩa gốc vì một số lý do.
Thuyền trưởng Prinny

10

Nếu bạn muốn ot biết thư mục chứa giải pháp của bạn là gì, bạn cần làm điều này:

 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*/}
            }

Nếu bạn chỉ cho phép với GetCurrrentDirectory()phương thức, bạn sẽ có được thư mục xây dựng bất kể bạn đang gỡ lỗi hay phát hành. Tôi hy vọng sự giúp đỡ này! Nếu bạn quên về xác nhận, nó sẽ như thế này:

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

5

Tôi đã tìm kiếm điều này quá. Tôi đã có một dự án chạy HWC và tôi muốn giữ trang web ra khỏi cây ứng dụng, nhưng tôi không muốn giữ nó trong thư mục gỡ lỗi (hoặc phát hành). FWIW, giải pháp được chấp nhận (và giải pháp này cũng vậy) chỉ xác định thư mục mà tệp thực thi đang chạy.

Để tìm thư mục đó, tôi đã sử dụng

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

5

Dựa trên câu trả lời của Gucu112 , nhưng đối với ứng dụng .NET Core Console / Window, thì nó phải là:

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

Tôi đang sử dụng điều này trong một dự án xUnit cho Ứng dụng .NET Core Window.


4

Một cách khác để làm điều này

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

Nếu bạn muốn lấy đường dẫn đến thư mục bin

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

Có lẽ có cách tốt hơn =)


4

Một giải pháp không hoàn hảo khác (nhưng có lẽ gần hoàn hảo hơn một số giải pháp khác):

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

Phiên bản này sẽ trả về thư mục của các dự án hiện tại ngay cả khi dự án hiện tại không phải Startup Projectlà giải pháp.

Lỗ hổng đầu tiên với điều này là tôi đã bỏ qua tất cả các kiểm tra lỗi. Điều đó có thể được sửa đủ dễ dàng nhưng chỉ là vấn đề nếu bạn lưu trữ dự án của bạn trong thư mục gốc cho ổ đĩa hoặc sử dụng một đường nối trong đường dẫn của bạn (và đường nối đó là hậu duệ của thư mục giải pháp) vì vậy kịch bản này khó xảy ra . Tôi không hoàn toàn chắc chắn rằng Visual Studio có thể xử lý một trong hai thiết lập này.

Một vấn đề khác (rất có thể) mà bạn có thể gặp phải là tên dự án phải khớp với tên thư mục của dự án để tìm thấy nó.

Một vấn đề khác bạn có thể có là dự án phải nằm trong thư mục giải pháp. Đây thường không phải là vấn đề nhưng nếu bạn đã sử dụng Add Existing Project to Solutiontùy chọn để thêm dự án vào giải pháp thì đây có thể không phải là cách tổ chức giải pháp của bạn.

Cuối cùng, nếu ứng dụng của bạn sẽ sửa đổi thư mục làm việc, bạn nên lưu trữ giá trị này trước khi bạn làm điều đó vì giá trị này được xác định liên quan đến thư mục làm việc hiện tại.

Tất nhiên, tất cả điều này cũng có nghĩa là bạn không được thay đổi các giá trị mặc định cho các tùy chọn ' Build-> Output pathhoặc Debug-> Working directorycủa dự án trong hộp thoại thuộc tính dự án.


4

Hãy thử nó, nó đơn giản

HttpContext.Current.Server.MapPath("~/FolderName/");

4

Giải pháp này hoạt động tốt với tôi, trên Develop và cả trên các máy chủ TEST và PROD với ASP.NET MVC5 qua C # :

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

Nếu bạn cần thư mục dự án trong tập tin cấu hình dự án, hãy sử dụng:

$(ProjectDir)

3

Sau khi tôi cuối cùng đã hoàn thành việc đánh bóng câu trả lời đầu tiên của mình về chuỗi công khai để đưa ra câu trả lời, tôi nhận ra rằng bạn có thể đọc giá trị từ sổ đăng ký để có kết quả mong muốn. Hóa ra, tuyến đường đó thậm chí còn ngắn hơn:

Trước tiên, bạn phải bao gồm không gian tên Microsoft.Win32 để bạn có thể làm việc với sổ đăng ký:

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

Đây là mã chính:

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

Một lưu ý về câu trả lời này:

Tôi đang sử dụng Visual Studio 2008 Professional Edition. Nếu bạn đang sử dụng một phiên bản khác, (ví dụ 2003, 2005, 2010; v.v.), thì bạn không thể sửa đổi phần 'phiên bản' của chuỗi SubKey (ví dụ 8.0, 7.0; v.v.).

Nếu bạn sử dụng một trong những câu trả lời của tôi và nếu nó không quá nhiều để hỏi, thì tôi muốn biết phương pháp nào tôi đã sử dụng và tại sao. Chúc may mắn.

  • dm

3

Tôi đã có một tình huống tương tự, và sau khi Google không có kết quả, tôi đã khai báo một chuỗi công khai, điều chỉnh giá trị chuỗi của đường dẫn gỡ lỗi / phát hành để có được đường dẫn dự án. Lợi ích của việc sử dụng phương thức này là vì nó sử dụng thư mục của dự án hiện tại, nên vấn đề không phải là nếu bạn đang làm việc từ thư mục gỡ lỗi hoặc thư mục phát hành:

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

Sau đó, bạn có thể gọi nó bất cứ khi nào bạn muốn, chỉ sử dụng một dòng:

string MyProjectDir = DirProject();

Điều này sẽ làm việc trong hầu hết các trường hợp.


3

Sử dụng cái này để lấy thư mục Project (làm việc cho tôi):

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

Tôi đã sử dụng giải pháp sau đây để hoàn thành công việc:

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

2

Thử:

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

Đây là giải pháp khác với các giải pháp khác cũng có tính đến việc xây dựng x86 hoặc x64 có thể.


Giải pháp này gần như đã có cho các tệp csproj mới, nơi TargetFramework được bao gồm trong đường dẫn.
Glenn Watson

1
Đối với định dạng kiểu .netcore mới, tôi đã có Regex mới (@ "\\ bin (\\ x86 | \\ x64)? \ (Gỡ lỗi | Phát hành) (\ [a-zA-Z0-9.] *)? $" , RegexOptions.Compiled)
Glenn Watson

1

Giải pháp tốt nhất

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

Giải pháp khác

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

Kiểm tra nó, AppDomain.C hiệnDomain.BaseDirectory đã làm việc cho tôi trong dự án trước đây, bây giờ tôi nhận được thư mục gỡ lỗi .... câu trả lời TỐT được chọn chỉ KHÔNG LÀM VIỆC!.

//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

Nếu bạn thực sự muốn đảm bảo bạn có được thư mục dự án nguồn, bất kể đường dẫn đầu ra bin nào được đặt thành:

  1. Thêm một dòng lệnh sự kiện xây dựng trước (Visual Studio: Thuộc tính dự án -> Xây dựng sự kiện):

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

  2. Thêm ProjectDirectory.txttệp vào Tài nguyên.resx của dự án (Nếu chưa tồn tại, nhấp chuột phải vào dự án -> Thêm mục mới -> Tệp tài nguyên)

  3. Truy cập từ mã với Resources.ProjectDirectory.

-1

Điều này hoạt động trên các cấu hình VS2017 w / SDK Core MSBuild.

Bạn cần NuGet trong các gói EnvDTE / EnvDTE80.

Không sử dụng COM hoặc interop. bất cứ điều gì .... rác !!

 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.GetCienDirectory ()). Parent.Parent.Parent.Parent.FullName

Sẽ cung cấp cho bạn thư mục dự án.


77
có thật không? Tôi nghĩ rằng bạn đang thiếu Cha mẹ
sean
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.