2010-10-04 40 views
47

Nếu tôi chạy một quy trình với ShellExecute (hoặc trong .net với System.Diagnostics.Process.Start()), quá trình tên tệp để bắt đầu không cần phải là đường dẫn đầy đủ.Kiểm tra xem tệp thực thi có tồn tại trong đường dẫn Windows

Nếu tôi muốn bắt đầu notepad, tôi có thể sử dụng

Process.Start("notepad.exe"); 

thay vì

Process.Start(@"c:\windows\system32\notepad.exe"); 

vì direcotry c:\windows\system32 là một phần của các biến môi trường PATH.

làm cách nào để kiểm tra xem tệp có tồn tại trên PATH mà không thực thi quy trình và không phân tích cú pháp biến PATH không?

System.IO.File.Exists("notepad.exe"); // returns false 
(new System.IO.FileInfo("notepad.exe")).Exists; // returns false 

nhưng tôi cần một cái gì đó như thế này:

System.IO.File.ExistsOnPath("notepad.exe"); // should return true 

System.IO.File.GetFullPath("notepad.exe"); // (like unix which cmd) should return 
              // c:\windows\system32\notepad.exe 

Có một lớp học được xác định trước để làm nhiệm vụ này có sẵn trong BCL?

+0

Trong khi một lớp được xác định trước như vậy sẽ thuận tiện (hoặc là thuận tiện, nếu nó tồn tại) là không chỉ còn một dòng nữa để có được đường dẫn sau đó kiểm tra tồn tại()? Bạn có thể viết nó nhanh hơn so với đặt câu hỏi. Lý do/nhu cầu đặc biệt? Chỉ cần tự hỏi. – mickeyf

+2

Yepp, nên rất dễ dàng. Nhưng niềm tin của tôi là, nếu một công việc có thể được thực hiện với thư viện hiện tại của một ngôn ngữ thử nghiệm, tôi ủng hộ cách này qua việc tái phát minh các liên tục một lần nữa. Nếu không có smth có sẵn, tôi làm điều đó của riêng tôi. –

Trả lời

44

Tôi nghĩ rằng không có gì built-in là, nhưng bạn có thể làm điều gì đó như thế này với System.IO.File.Exists:

public static bool ExistsOnPath(string fileName) 
{ 
    return GetFullPath(fileName) != null; 
} 

public static string GetFullPath(string fileName) 
{ 
    if (File.Exists(fileName)) 
     return Path.GetFullPath(fileName); 

    var values = Environment.GetEnvironmentVariable("PATH"); 
    foreach (var path in values.Split(';')) 
    { 
     var fullPath = Path.Combine(path, fileName); 
     if (File.Exists(fullPath)) 
      return fullPath; 
    } 
    return null; 
} 
+3

Nếu bạn định làm điều này, tôi khuyên bạn nên chuyển chúng thành Phương thức mở rộng ... http: //msdn.microsoft.com/en-us/library/bb383977.aspx –

+5

@Aaron: Bạn có chắc chắn bạn sẽ thấy 'GetFullPath 'làm phương thức mở rộng cho' chuỗi'? Nghe có vẻ lạ lẫm với tôi ... Có lẽ có thể có ý nghĩa với 'FileInfo' ... – digEmAll

+0

Có thể sẽ rất lạ khi sử dụng một chuỗi. Tuy nhiên tôi nghĩ rằng nó sẽ làm cho tinh thần để bọc các chức năng trên từ cả hai phương pháp vào một phương pháp mở rộng duy nhất có tiêu đề ExistsOnPath mà treo tắt FileInfo như bạn đã đề cập. –

22

Đây là mạo hiểm, có rất nhiều hơn để nó hơn là chỉ tìm kiếm các thư mục trong PATH. Hãy thử điều này:

Process.Start("wordpad.exe"); 

Các thực thi được lưu trữ trong c: \ Program Files \ Windows NT \ Accessories trên máy tính của tôi, thư mục đó là không trên con đường.

Phím HKCR \ Ứng dụng và HKLM \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ App Đường dẫn cũng đóng vai trò trong việc tìm kiếm tệp thi hành. Tôi khá chắc chắn có thêm các mỏ đất như thế này xung quanh, ảo hóa thư mục trong các phiên bản 64-bit của Windows có thể đi bạn lên ví dụ.

Để làm cho điều này đáng tin cậy hơn, tôi nghĩ bạn cần phải ghim AssocQueryString(). Không chắc chắn, không bao giờ có nhu cầu. Cách tiếp cận tốt hơn chắc chắn là không phải đặt câu hỏi.

+0

ứng dụng mà tôi muốn truy vấn đăng ký chính nó vào đường dẫn (mysqldump.exe). Nếu không, hoặc nếu không được cài đặt, tôi muốn vô hiệu hóa tùy chọn sử dụng mysqlbackup từ một ứng dụng biểu mẫu windows. Tôi chỉ không muốn mã cứng đường dẫn đến tập tin. –

+0

Nó là * rất hiếm trong những ngày này để các trình cài đặt sửa đổi PATH. Đặc biệt đối với một tiện ích, hãy kiểm tra trước tiên. Tôi sẽ chỉ sử dụng một thiết lập với phạm vi Ứng dụng và mặc định là "" ở đây. –

+3

Đây là chủ đề của bài đăng Raymond Chen gần đây. Khó để đánh bại kỹ năng viết blog của anh ấy, khác với tôi trước tiên. Thưởng thức: http://blogs.msdn.com/b/oldnewthing/archive/2011/07/25/10189298.aspx –

2

Tôi đang theo cùng một điều và tôi nghĩ rằng tùy chọn tốt nhất mà tôi có ngay bây giờ là sử dụng gọi gốc để CreateProcess để tạo ra một quá trình bị đình chỉ và xem để thành công; chấm dứt quá trình ngay sau đó. Việc chấm dứt một quá trình bị đình chỉ sẽ không xảy ra bất kỳ sự cố chảy máu nào [cần dẫn nguồn]]

Tôi không thể tìm ra đường dẫn thực sự được sử dụng nhưng yêu cầu đơn giản như ExistsOnPath() nó phải làm - cho đến khi có giải pháp tốt hơn.

9

Ok, một cách tốt hơn tôi nghĩ ...

này sử dụng lệnh nơi, trong đó có sẵn ít nhất là trên Windows 7/Server 2003:

public static bool ExistsOnPath(string exeName) 
{ 
    try 
    { 
     Process p = new Process(); 
     p.StartInfo.UseShellExecute = false; 
     p.StartInfo.FileName = "where"; 
     p.StartInfo.Arguments = exeName; 
     p.Start(); 
     p.WaitForExit(); 
     return p.ExitCode == 0; 
    } 
    catch(Win32Exception) 
    { 
     throw new Exception("'where' command is not on path"); 
    } 
} 


public static string GetFullPath(string exeName) 
{ 
    try 
    { 
     Process p = new Process(); 
     p.StartInfo.UseShellExecute = false; 
     p.StartInfo.FileName = "where"; 
     p.StartInfo.Arguments = exeName; 
     p.StartInfo.RedirectStandardOutput = true; 
     p.Start(); 
     string output = p.StandardOutput.ReadToEnd(); 
     p.WaitForExit(); 

     if (p.ExitCode != 0) 
      return null; 

     // just return first match 
     return output.Substring(0, output.IndexOf(Environment.NewLine)); 
    } 
    catch(Win32Exception) 
    { 
     throw new Exception("'where' command is not on path"); 
    } 
} 
Các vấn đề liên quan