Làm cách nào để có được tên của tệp thực thi hiện tại trong C #?


355

Tôi muốn lấy tên của chương trình hiện đang chạy, đó là tên thực thi của chương trình. Trong C / C ++, bạn nhận được nó từ args[0].


Có thể thực thi là tệp EXE (Windows Forms, ứng dụng WPF)? Một chương trình có thể là Ứng dụng máy tính để bàn (WinForms, WPF; và WinRT-Windows Phone?), Ứng dụng web, Ứng dụng dịch vụ Wcf, Addin Visual Studio, Addin Outlook-Word, Kiểm tra đơn vị trong VS (MSTest) hoặc Ứng dụng Silverlight.
Kiquenet

Câu trả lời:


405
System.AppDomain.CurrentDomain.FriendlyName

61
Coi chừng câu trả lời được chấp nhận. Chúng tôi đã gặp sự cố khi sử dụng System.AppDomain.CurrentDomain.FriendlyNametrong các ứng dụng được triển khai Nhấp chuột một lần. Đối với chúng tôi, đây là trả về " DefaultDomain ", và không phải tên exe ban đầu.
Gaspode

40
Chúng tôi đã sử dụng điều này cuối cùng:string file = object_of_type_in_application_assembly.GetType().Assembly.Location; string app = System.IO.Path.GetFileNameWithoutExtension( file );
Gaspode

4
FriendlyName có thể được đặt thành bất cứ điều gì. Ngoài ra nhận được vị trí lắp ráp có thể không đủ nếu bạn có một exe với một vài dll. Hơn nữa, nếu bạn sử dụng một số AppDomain, hội đồng.GetCallingAssugging () trả về null.
dùng276648

2
@Gaspode: sẽ dễ dàng hơn khi nói Path.GetFileNameWithoutExtension (GetType (). Association.Location) - bạn không cần chỉ định một đối tượng của loại trong cụm hiện tại. Bạn có thể sử dụng GetType của cái này, và thậm chí bạn không cần phải nói "cái này".
vbullinger

4
Điều này có thể hữu ích, nhưng nó không phải là câu trả lời được chấp nhận: Nó khác rất nhiều so với những gì được yêu cầu - nó sẽ ngẫu nhiên giống nhau trong một số tình huống, nhưng đây hoàn toàn là một điều khác. Nếu bạn không tự viết đơn, nó rất có thể trả về "Tôi thích khoai tây!" hoặc bất cứ điều gì khác đồng nghiệp hài hước của bạn đã viết vào tài sản này khi họ xây dựng ứng dụng!
AnorZaken

237

System.AppDomain.CurrentDomain.FriendlyName - Trả về tên tệp có phần mở rộng (ví dụ MyApp.exe).

System.Diagnostics.Process.GetCurrentProcess().ProcessName- Trả về tên tệp mà không cần mở rộng (ví dụ MyApp).

System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName- Trả về đường dẫn và tên tệp đầy đủ (ví dụ: C: \ example \ Processes \ MyApp.exe). Sau đó, bạn có thể chuyển nó vào System.IO.Path.GetFileName()hoặc System.IO.Path.GetFileNameWithoutExtension()để đạt được kết quả tương tự như trên.


3
AppDomain có thể là ứng dụng EXE, ứng dụng Web, ứng dụng kiểm tra đơn vị, Addin Visual Studio và "Ứng dụng Silverlight" (?). Có thể giải pháp đầy đủ thú vị cho tất cả các trường hợp. Ví dụ: đối với Bài kiểm tra đơn vị VS2012 - ProcessName: vstest.executengine.x86 MainModule.FileName: C: \ PROGRAM FILES (X86) \ MICROSOFT VISUAL STUDIO 11.0 \ COMMON7 \ IDE \ COMMONEXTENSION \ MICROSOFT MainModule.ModuleName: vstest.executengine.x86.exe FriendlyName: UnitTestAd CHƯƠNG: Chạy thử ApplicationName:
Kiquenet

"Chương trình" có thể là Ứng dụng dành cho Máy tính để bàn (WinForms, WPF; và WinRT-Windows Phone?), Ứng dụng web, Ứng dụng dịch vụ Wcf, Addin Visual Studio, Addin Outlook-Word, Kiểm tra đơn vị trong VS (MSTest) hoặc, Ứng dụng Silverlight . Ví dụ: làm thế nào để lắp ráp máy chủ dịch vụ cho Ứng dụng dịch vụ Wcf được lưu trữ trong IIS, không phải IISExpress hoặc WebDevServer?
Kiquenet

6
+1 Tôi sẽ đi theo câu trả lời này vì nó cung cấp cả ba biến thể mà bạn có thể cần một cách đơn giản và gọn gàng. Sử dụng tên chương trình trần không có đường dẫn hoặc phần mở rộng rất hữu ích cho văn bản trợ giúp trong chương trình ( /?chuyển đổi), bởi vì sử dụng phần mở rộng và đường dẫn chỉ làm lộn xộn nó một cách không cần thiết.
Synetech

2
Hãy nhớ loại bỏ kết quả củaGetCurrentProcess()
Mahmoud Al-Qudsi

Process.GetCurrentProcess().ProcessName()trả lại MyApp.vshost cho tôi.
Jonathan Wood

106

System.Diagnostics.Process.GetCurrentProcess()được quá trình hiện đang chạy. Bạn có thể sử dụng ProcessNametài sản để tìm ra tên. Dưới đây là một ứng dụng giao diện điều khiển mẫu.

using System;
using System.Diagnostics;

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Process.GetCurrentProcess().ProcessName);
        Console.ReadLine();
    }
}

36
Sử dụng tốt hơn Process.GetCienProcess (). MainModule.FileName
KindDragon

Process.GetCienProcess (). MainModule.FileName hoạt động hoàn hảo từ bên trong một Addin Excel (ExcelDNA)
Earcam 15/03/2016

10
Cách tiếp cận này sẽ thất bại khi được sử dụng trong thời gian chạy Mono; tên quy trình cho các ứng dụng chạy trên Mono sẽ luôn là một số biến thể của .../bin/mono* nixes hoặc .../mono.exetrên Windows.
cdhowie

1
Đây phải là câu trả lời được chấp nhận. Tên miền AppDomain hiện tại có thể không liên quan gì đến tên quy trình thực thi, đặc biệt là khi có nhiều tên miền ứng dụng
Ivan Krivyakov

Phương pháp này có thể chậm hơn đáng kể so với chơi với lớp hội.
Erwin Mayer

99

Điều này nên đủ:

Environment.GetCommandLineArgs()[0];

3
Hmm, điều này trả về (khi chạy từ vs.net và sử dụng điều lưu trữ gỡ lỗi), vị trí và tên của tên
tệp.vshost.exe

13
Đây là câu trả lời tốt nhất cho tôi vì Environment.GetCommandLineArgs()là tương tự C # chính xác argvtừ C / C ++.
Frederick The Fool

Đã đồng ý! câu trả lời tốt nhất. Tôi có nhu cầu lấy Môi trường.GetCommandLineArss () [1];
Jerry Liang

1
Để tránh đường dẫn đầy đủ:Path.GetFileNameWithoutExtension(Environment.GetCommandLineArgs()[0])
Nathan

1
Điều này hoạt động tốt khi cố gắng theo dõi các dịch vụ WCF. Tên quá trình trở lại với iothypress trong trường hợp của tôi. Nhưng lệnh này cho tôi tên lắp ráp dịch vụ WCF thực tế.
P.Brian.Mackey

19

Đây là mã làm việc cho tôi:

string fullName = Assembly.GetEntryAssembly().Location;
string myName = Path.GetFileNameWithoutExtension(fullName);

Tất cả các ví dụ trên đã cho tôi processName với vshost hoặc tên dll đang chạy.


4
Đối với những người không biết hoặc bỏ lỡ nó trong các câu trả lời khác, không gian tên cho hội là System.Reflection và không gian tên cho Path là System.IO.
hợp nhất

4
GetEntryAssugging sẽ trả về null nếu điểm nhập ứng dụng nằm trong mã gốc chứ không phải là một cụm.
Emdot

18

Thử cái này:

System.Reflection.Assembly.GetExecutingAssembly()

Điều này trả về cho bạn một System.Reflection.Assemblyví dụ có tất cả dữ liệu bạn có thể muốn biết về ứng dụng hiện tại. Tôi nghĩ rằng Locationtài sản có thể có được những gì bạn đang có sau khi cụ thể.


6
Có thể an toàn hơn khi sử dụng CodeBasethay vì Locationtrong trường hợp tính năng sao chép bóng của .NET đang hoạt động. Xem blogs.msdn.com/suzcook/archive/2003/06/26/...
Dirk Vollmar

18
Cảnh giác với GetExecutingAssugging (): nếu bạn gọi nó từ tập hợp thư viện, nó sẽ trả về tên của tập hợp thư viện, khác với tên của tập hợp mục nhập (tức là tập tin thực thi ban đầu). Nếu bạn sử dụng GetEntryAssugging (), nó sẽ trả về tên của tệp thực thi thực tế, nhưng nó sẽ ném ra một ngoại lệ nếu quá trình này đang chạy trong WCF (phải thừa nhận là một tình huống hiếm gặp). Để có mã mạnh nhất, hãy sử dụng Process.GetCienProcess (). ProcessName.
Contango

@Gravitas: Chắc chắn là không, bất kỳ tệp thực thi nào đang chạy "diễn giải", ví dụ với / usr / bin / mono sẽ có tên quy trình sai. Ngoài ra ProcessName sẽ không hoạt động với các dịch vụ windows. Nếu bạn sử dụng nó trong thư viện, hãy sử dụng GetCallingAssugging.
Stefan Steiger

1
Đã làm cho tôi. Tên thuộc tính của cuộc gọi hội đồng GetName () được trả về là những gì bạn cần và không bao gồm phần ".exe". Cũng đã thử nghiệm trên Mono / Linux với kết quả mong đợi.
Hội.GetName

1
Hmm, lưu ý rằng chuỗi trả về sẽ không thay đổi ngay cả khi bạn đổi tên tệp thực thi bằng tay bằng cách sử dụng trình thám hiểm tệp. Trong khi Môi trường.GetCommandLineArss () [0] thay đổi cùng với tên tệp thực thi thực tế (tất nhiên). Thật trùng hợp, phương pháp thứ hai mang lại kết quả tốt hơn cho tình huống cụ thể của tôi vì tôi muốn thư mục dữ liệu được đặt tên là tên tệp thực thi thực tế.
Hatoru Hansou

11
System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name;

sẽ cung cấp cho bạn Tên tệp của ứng dụng của bạn như thế nào; "MyApplication.exe"


11

Tại sao không ai đề nghị điều này, nó đơn giản.

Path.GetFileName(Application.ExecutablePath)

3
Không gian tên nào ứng dụng cư trú.
Jeetendra

6
Điều này hữu ích khi bên trong ứng dụng Windows Forms, nhưng không thì khác
Nine tweet

@NineBerry Bạn có thể quan tâm đến Application.ExecutablePath's mã nguồn .
Ma quái

@Nine BlackBerry Xem bài viết của tôi. Điều này hoạt động trong các ứng dụng Console nếu bạn thêm một tham chiếu đến System.Windows.Forms.
Giăng


9

Nếu bạn cần tên Chương trình để thiết lập quy tắc tường lửa, hãy sử dụng:

System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName

Điều này sẽ đảm bảo rằng tên là chính xác cả khi gỡ lỗi trong VisualStudio và khi chạy ứng dụng trực tiếp trong windows.


2
Đối với mục đích của tôi (tạo một tên tệp đăng nhập), đây là câu trả lời tốt nhất. Nếu chạy một quy trình được lưu trữ (giả sử, một dịch vụ hoặc ứng dụng web), System.AppDomain.CienDomain.FriendlyName có thể trả về một tên GUID-y xấu xí với các dấu gạch chéo được nhúng.
Curt

8

Khi không chắc chắn hoặc nghi ngờ, hãy chạy theo vòng tròn, la hét và hét lên.

class Ourself
{
    public static string OurFileName() {
        System.Reflection.Assembly _objParentAssembly;

        if (System.Reflection.Assembly.GetEntryAssembly() == null)
            _objParentAssembly = System.Reflection.Assembly.GetCallingAssembly();
        else
            _objParentAssembly = System.Reflection.Assembly.GetEntryAssembly();

        if (_objParentAssembly.CodeBase.StartsWith("http://"))
            throw new System.IO.IOException("Deployed from URL");

        if (System.IO.File.Exists(_objParentAssembly.Location))
            return _objParentAssembly.Location;
        if (System.IO.File.Exists(System.AppDomain.CurrentDomain.BaseDirectory + System.AppDomain.CurrentDomain.FriendlyName))
            return System.AppDomain.CurrentDomain.BaseDirectory + System.AppDomain.CurrentDomain.FriendlyName;
        if (System.IO.File.Exists(System.Reflection.Assembly.GetExecutingAssembly().Location))
            return System.Reflection.Assembly.GetExecutingAssembly().Location;

        throw new System.IO.IOException("Assembly not found");
    }
}

Tôi không thể tuyên bố đã thử nghiệm từng tùy chọn, nhưng nó không làm điều gì ngu ngốc như trả lại vhost trong các phiên gỡ lỗi.


2
+1 để giải trí. :-) Tôi hầu như không sử dụng mã này, trừ khi tôi đang viết một thư viện thực sự chung chung không biết gì về môi trường của nó (và sau đó có lẽ sẽ không phải là ý tưởng tốt để duy trì bất kỳ trạng thái toàn cầu nào bạn sẽ sử dụng tên cho).
Andrey Tarantsov 22/03/13

@Hoặc Ứng dụng Silverlight. Ví dụ: làm thế nào để lắp ráp máy chủ dịch vụ cho Ứng dụng dịch vụ Wcf được lưu trữ trong IIS, không phải IISExpress hoặc WebDevServer? Bất kỳ mã đầy đủ nào hợp lệ cho A WinForms, WPF, Ứng dụng web, Ứng dụng dịch vụ Wcf, Addin Visual Studio, Addin Outlook-Word, Kiểm tra đơn vị trong các ứng dụng VS (MSTest)?
Kiquenet

8
  • System.Reflection.Assembly.GetEntryAssembly().Location trả về vị trí của tên exe nếu lắp ráp không được tải từ bộ nhớ.
  • System.Reflection.Assembly.GetEntryAssembly().CodeBase trả về vị trí dưới dạng URL.

Đã thử nghiệm, điều này hoạt động 100%, ngay cả khi nó được gọi từ trong thư viện C #.
Contango

1
GetEntryAssugging () trả về null nếu bạn không ở trong AppDomain chính.
dùng276648

4

NẾU bạn đang tìm kiếm thông tin đường dẫn đầy đủ của tệp thực thi của mình, cách đáng tin cậy để làm điều đó là sử dụng như sau:

   var executable = System.Diagnostics.Process.GetCurrentProcess().MainModule
                       .FileName.Replace(".vshost", "");

Điều này giúp loại bỏ bất kỳ vấn đề với dlls trung gian, vshost, vv


Tôi đã thử cách đáng tin cậy của bạn trong Ubuntu Linux 15.10 C ++ bằng cách sử dụng realpath theo sau là chuỗi thay thế STL C ++ và nó đã khiến Point và Click bị lỗi. Điều đó có thể được gây ra bởi một lỗi trong mono khi giám đốc phần mềm của chúng tôi phỏng đoán ngày hôm nay? Cảm ơn.
Frank

Tôi không lập trình trên Mono, mặc dù có thể rất vui khi thử
TheMayer 17/2/2016

Gasponde đã viết ở trên rằng "Chúng tôi đã gặp vấn đề với việc sử dụng System.AppDomain.CienDomain.FriendlyName trong các ứng dụng được triển khai Nhấp chuột một lần." Bạn có thể đoán xem vấn đề có thể xảy ra với các ứng dụng được triển khai Click-Again trong .NET không? Cảm ơn.
Frank

Trả về C: \ Program Files \ dotnet \ dotnet.exe cho chương trình Mẫu của tôi trong VS2017.
jwdonahue

3

Bạn có thể sử dụng Environment.GetCommandLineArgs()để có được các đối số và Environment.CommandLineđể có được dòng lệnh thực tế như đã nhập.

Ngoài ra, bạn có thể sử dụng Assembly.GetEntryAssembly()hoặc Process.GetCurrentProcess().

Tuy nhiên, khi gỡ lỗi, bạn nên cẩn thận vì ví dụ cuối cùng này có thể đặt tên thực thi của trình gỡ lỗi của bạn (tùy thuộc vào cách bạn đính kèm trình gỡ lỗi) thay vì thực thi của bạn, như các ví dụ khác.


4
Cảnh giác với GetExecutingAssugging (): nếu bạn gọi nó từ tập hợp thư viện, nó sẽ trả về tên của tập hợp thư viện, khác với tên của tập hợp mục nhập (tức là tập tin thực thi ban đầu). Nếu bạn sử dụng GetEntryAssugging (), nó sẽ trả về tên của tệp thực thi thực tế, nhưng nó sẽ ném ra một ngoại lệ nếu quá trình này đang chạy trong WCF (phải thừa nhận là một tình huống hiếm gặp). Để có mã mạnh nhất, hãy sử dụng Process.GetCienProcess (). ProcessName.
Contango

@Gravitas: điểm tốt - wow, đã được một thời gian kể từ khi tôi viết bài này! : D Tôi sẽ chỉnh sửa tương ứng
Jeff Yates

Environment.CommandLineđưa ra đường dẫn tuyệt đối, không phải dòng lệnh đã nhập, ít nhất là trên Mono / Linux.
Ốc cơ khí

@M Mechanicalsnail: Âm thanh như Mono không hoàn toàn làm theo tài liệu. Hấp dẫn.
Jeff Yates

1

Đây có phải là những gì bạn muốn:

Assembly.GetExecutingAssembly ().Location

4
Cảnh giác với GetExecutingAssugging (): nếu bạn gọi nó từ tập hợp thư viện, nó sẽ trả về tên của tập hợp thư viện, khác với tên của tập hợp mục nhập (tức là tập tin thực thi ban đầu). Nếu bạn sử dụng GetEntryAssugging (), nó sẽ trả về tên của tệp thực thi thực tế, nhưng nó sẽ ném ra một ngoại lệ nếu quá trình này đang chạy trong WCF (phải thừa nhận là một tình huống hiếm gặp). Để có mã mạnh nhất, hãy sử dụng Process.GetCienProcess (). ProcessName.
Contango

Một câu trả lời không nên là một câu hỏi. Đó có phải là những gì OP muốn?
jwdonahue

1

Trên .Net Core (hoặc Mono), hầu hết các câu trả lời sẽ không được áp dụng khi nhị phân xác định quy trình là nhị phân thời gian chạy của Mono hoặc .Net Core (dotnet) chứ không phải ứng dụng thực tế của bạn mà bạn quan tâm. Trong trường hợp đó , dùng cái này:

var myName = Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly().Location);

1
GetEntryAssembly()có thể trả về null.
dùng2864740

1

Đối với các ứng dụng windows (biểu mẫu và bảng điều khiển) tôi sử dụng điều này:

Thêm một tham chiếu đến System.Windows.Forms trong VS rồi:

using System.Windows.Forms;
namespace whatever
{
    class Program
    {
        static string ApplicationName = Application.ProductName.ToString();
        static void Main(string[] args)
        {
            ........
        }
    }
}

Điều này hoạt động chính xác cho tôi cho dù tôi đang chạy chương trình thực thi hoặc gỡ lỗi thực tế trong VS.

Lưu ý rằng nó trả về tên ứng dụng mà không cần phần mở rộng.

John


1

Siêu dễ, ở đây:

Environment.CurrentDirectory + "\\" + Process.GetCurrentProcess().ProcessName

1
Đối với .NET Core Process.GetCienProcess (). ProcessName trả về "dotnet".
Evgeni Nabokov

1
Thư mục hiện tại là tạm thời và không thể dựa vào vị trí lắp ráp / thực thi.
jwdonahue

1

Điều này hoạt động nếu bạn chỉ cần tên ứng dụng mà không cần gia hạn:

Path.GetFileNameWithoutExtension(AppDomain.CurrentDomain.FriendlyName);

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.