Cách kiểm tra xem dịch vụ windows đã được cài đặt trong C # chưa


79

Tôi đã viết một Dịch vụ Windows cho thấy một dịch vụ WCF với một GUI được cài đặt trên cùng một máy. Khi tôi chạy GUI, nếu tôi không thể kết nối với dịch vụ, tôi cần biết đó là do ứng dụng dịch vụ chưa được cài đặt hay là do dịch vụ không chạy. Nếu trước đây, tôi sẽ muốn cài đặt nó (như mô tả ở đây ); nếu sau này, tôi sẽ muốn khởi động nó.

Câu hỏi đặt ra là: làm thế nào để bạn phát hiện nếu dịch vụ đã được cài đặt, và sau đó phát hiện ra rằng nó đã được cài đặt, làm thế nào để bạn khởi động nó?

Câu trả lời:


147

Sử dụng:

// add a reference to System.ServiceProcess.dll
using System.ServiceProcess;

// ...
ServiceController ctl = ServiceController.GetServices()
    .FirstOrDefault(s => s.ServiceName == "myservice");
if(ctl==null)
    Console.WriteLine("Not installed");
else    
    Console.WriteLine(ctl.Status);

Cảm ơn bạn - chỉ là những gì tôi cần!
Shaul Behr

1
using (var sc = ServiceController.GetServices (). FirstOrDefault (s => s.ServiceName == "myservice")) - Tôi nghĩ đây là một cách tiếp cận tốt hơn.
Alexandru Dicu

4
@alexandrudicu: Đó là cách tiếp cận tốt hơn như thế nào? Nếu .GetServices()trả về 100 ServiceControllerđối tượng và bạn đã loại bỏ một trong số hàng trăm đối tượng trong khi bỏ qua phần còn lại, điều đó có thực sự tốt hơn đáng kể không? Tôi sẽ không nói như vậy bản thân mình.
Allon Guralnek

37

Bạn cũng có thể sử dụng những điều sau đây ..

using System.ServiceProcess; 
... 
var serviceExists = ServiceController.GetServices().Any(s => s.ServiceName == serviceName);

3
IMO, đây là cách tốt nhất để kiểm tra xem dịch vụ của bạn có tồn tại hay không. Chỉ một dòng mã, tận dụng sức mạnh của Linq. Và bằng cách này, Bất cứ () trả về một bool được chính xác những gì bạn muốn khi hỏi có / không có câu hỏi :-)
Alex X.

3
Nếu bạn cần phải kiểm tra các dịch vụ trên một máy từ xa, sử dụngGetServices(string)
ShooShoSha

7

Trên thực tế lặp lại như thế này:

foreach (ServiceController SC in ServiceController.GetServices())

có thể đưa ra ngoại lệ Access Denied nếu tài khoản mà ứng dụng của bạn đang chạy không có quyền xem thuộc tính dịch vụ. Mặt khác, bạn có thể thực hiện việc này một cách an toàn ngay cả khi không có dịch vụ nào có tên như vậy tồn tại:

ServiceController SC = new ServiceController("AnyServiceName");

Nhưng việc truy cập các thuộc tính của nó nếu dịch vụ không tồn tại sẽ dẫn đến Lỗi không hợp lệ. Vì vậy, đây là một cách an toàn để kiểm tra xem một dịch vụ đã được cài đặt hay chưa:

ServiceController SC = new ServiceController("MyServiceName");
bool ServiceIsInstalled = false;
try
{
    // actually we need to try access ANY of service properties
    // at least once to trigger an exception
    // not neccessarily its name
    string ServiceName = SC.DisplayName;
    ServiceIsInstalled = true;
}
catch (InvalidOperationException) { }
finally
{
    SC.Close();
}

cảm ơn! và bạn có muốn kết thúc bằng: last {SC.Close (); }
Cel

6
Tại sao không bọc toàn bộ thứ khi sử dụng? Điều đó sẽ loại bỏ nhu cầu cuối cùng cho {SC.Close ()} vì một câu lệnh using sẽ tự động loại bỏ. sử dụng (ServiceController SC = new ServiceController ("MyServiceName"))
lập hóa đơn vào

2

Đối với không phải linq, bạn chỉ có thể lặp lại qua mảng như sau:

using System.ServiceProcess;

bool serviceExists = false
foreach (ServiceController sc in ServiceController.GetServices())
{
    if (sc.ServiceName == "myServiceName")
    {
         //service is found
         serviceExists = true;
         break;
    }
}

1

Tôi nghĩ đây là câu trả lời tốt nhất cho câu hỏi này. Không cần thêm xử lý bổ sung để xác minh xem dịch vụ có tồn tại hay không, vì nó sẽ đưa ra một ngoại lệ nếu không. Bạn chỉ cần nắm bắt nó. Bạn cũng không cần đóng () kết nối nếu bạn sử dụng () toàn bộ phương thức.

using (ServiceController sc = new ServiceController(ServiceName))
{
 try
 {
  if (sc.Status != ServiceControllerStatus.Running)
  {
    sc.Start();
    sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 10));
    //service is now Started        
  }      
  else
    //Service was already started
 }
 catch (System.ServiceProcess.TimeoutException)
 {
  //Service was stopped but could not restart (10 second timeout)
 }
 catch (InvalidOperationException)
 {
   //This Service does not exist       
 }     
}

2
Không phải là một câu trả lời rất tốt ở tất cả. (1) Quản lý mã bằng các ngoại lệ là một thực tiễn rất tồi - không hiệu quả và chậm, và (2) câu trả lời được chấp nhận là gọn gàng, súc tích và đáp ứng các yêu cầu một cách hoàn hảo. Bạn đã xem xét nó trước khi đi sâu vào câu trả lời của riêng mình?
Shaul Behr

Rõ ràng là bạn không biết cách đọc như câu trả lời được chấp nhận, vì anh ấy cũng đã hỏi rõ ràng cách bắt đầu dịch vụ, điều này không có trong câu trả lời ban đầu.
hóa đơn

Rõ ràng là bạn không biết cách viết mã đúng cách. Như @Shaul Behr đã nêu, cách tiếp cận của bạn là một phương pháp không tốt vì nó không hiệu quả và chậm chạp. Nêu câu trả lời của riêng bạn có lẽ là tốt nhất, thậm chí còn tệ hơn: tự khen bản thân không bao giờ được coi là một hành vi tốt ở đây trên SO (và có thể là trên toàn thế giới).
Yoda

1
Rõ ràng là tôi không biết điều gì tồi tệ hơn ... Việc bạn không thể sử dụng ngữ pháp thích hợp để cố gắng trông giống như bạn biết mình đang nói gì, hoặc không thể nhận ra bạn vừa nhận xét về một chủ đề từ năm 2014 .... Lol.
hóa đơn

Đây là câu trả lời duy nhất mà chiếm những gì xảy ra nếu ai đó xóa các dịch vụ ở giữa kiểm tra cho sự tồn tại của nó và tương tác với nó
Mike Caron

1
 private bool ServiceExists(string serviceName)
    {
        ServiceController[] services = ServiceController.GetServices();
        var service = services.FirstOrDefault(s => string.Equals(s.ServiceName, serviceName, StringComparison.OrdinalIgnoreCase));
        return service != null;
    }
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.