Tôi cần phải viết mã mạnh mẽ trong .NET để cho phép dịch vụ windows (máy chủ 2003) tự khởi động lại. Cách tốt nhất để làm điều này là gì? Có một số API .NET để làm điều đó?
Tôi cần phải viết mã mạnh mẽ trong .NET để cho phép dịch vụ windows (máy chủ 2003) tự khởi động lại. Cách tốt nhất để làm điều này là gì? Có một số API .NET để làm điều đó?
Câu trả lời:
Đặt dịch vụ để khởi động lại sau khi thất bại (nhấp đúp vào dịch vụ trong bảng điều khiển và xem qua các tab đó - tôi quên tên của nó). Sau đó, bất cứ khi nào bạn muốn dịch vụ khởi động lại, chỉ cần gọi Environment.Exit(1)
(hoặc bất kỳ trả lại khác không) và HĐH sẽ khởi động lại cho bạn.
Service.ExitCode = 1
và sau đó thực thi Service.Stop()
cùng với bật hộp kiểm 'Bật hành động cho các điểm dừng có lỗi' trên màn hình cài đặt khôi phục dịch vụ. Làm theo cách này cho phép tắt máy đúng cách và vẫn kích hoạt khởi động lại.
Dim proc As New Process()
Dim psi As New ProcessStartInfo()
psi.CreateNoWindow = True
psi.FileName = "cmd.exe"
psi.Arguments = "/C net stop YOURSERVICENAMEHERE && net start YOURSERVICENAMEHERE"
psi.LoadUserProfile = False
psi.UseShellExecute = False
psi.WindowStyle = ProcessWindowStyle.Hidden
proc.StartInfo = psi
proc.Start()
Bạn không thể chắc chắn rằng tài khoản người dùng mà dịch vụ của bạn đang chạy thậm chí có quyền dừng và khởi động lại dịch vụ.
Bạn có thể tạo một quy trình là một dấu nhắc lệnh DOS tự khởi động lại:
Process process = new Process();
process.StartInfo.FileName = "cmd";
process.StartInfo.Arguments = "/c net stop \"servicename\" & net start \"servicename\"";
process.Start();
const string strCmdText = "/C net stop \"SERVICENAME\"&net start \"SERVICENAME\"";
Process.Start("CMD.exe", strCmdText);
Ở đâu SERVICENAME
là tên của dịch vụ của bạn (bao gồm dấu ngoặc kép vào tài khoản cho các không gian trong tên dịch vụ, có thể bỏ qua bằng cách khác).
Sạch sẽ, không cần cấu hình tự động khởi động lại.
Nó sẽ phụ thuộc vào lý do tại sao bạn muốn nó tự khởi động lại.
Nếu bạn chỉ tìm cách để dịch vụ tự dọn dẹp định kỳ thì bạn có thể có một bộ đếm thời gian chạy trong dịch vụ định kỳ gây ra thói quen thanh lọc.
Nếu bạn đang tìm cách khởi động lại khi thất bại - chính máy chủ dịch vụ có thể cung cấp khả năng đó khi thiết lập.
Vậy tại sao bạn cần khởi động lại máy chủ? Bạn đang cố gắng để đạt được điều gì?
Tôi không nghĩ bạn có thể trong một dịch vụ độc lập (khi bạn gọi Khởi động lại, nó sẽ dừng dịch vụ, điều này sẽ làm gián đoạn lệnh Khởi động lại và nó sẽ không bao giờ bắt đầu lại). Nếu bạn có thể thêm .exe thứ hai (ứng dụng Console sử dụng lớp ServiceManager), thì bạn có thể khởi động .exe độc lập và khởi động lại dịch vụ sau đó thoát.
Về ý nghĩ thứ hai, có lẽ bạn có thể yêu cầu dịch vụ đăng ký Tác vụ theo lịch trình (ví dụ sử dụng lệnh 'at') để khởi động dịch vụ và sau đó tự dừng dịch vụ; điều đó có thể sẽ làm việc
Vấn đề với việc tách ra một tệp bó hoặc EXE là một dịch vụ có thể có hoặc không có quyền cần thiết để chạy ứng dụng bên ngoài.
Cách sạch nhất để làm điều này mà tôi đã tìm thấy là sử dụng phương thức OnStop (), đây là điểm vào của Trình quản lý điều khiển dịch vụ. Sau đó, tất cả mã dọn dẹp của bạn sẽ chạy và bạn sẽ không có bất kỳ ổ cắm treo hoặc các quy trình khác, giả sử mã dừng của bạn đang thực hiện công việc của mình.
Để làm điều này, bạn cần đặt cờ trước khi chấm dứt phương thức OnStop để thoát với mã lỗi; sau đó SCM biết rằng dịch vụ cần phải được khởi động lại. Nếu không có cờ này, bạn sẽ không thể dừng dịch vụ theo cách thủ công từ SCM. Điều này cũng cho rằng bạn đã thiết lập dịch vụ để khởi động lại khi có lỗi.
Đây là mã dừng của tôi:
...
bool ABORT;
protected override void OnStop()
{
Logger.log("Stopping service");
WorkThreadRun = false;
WorkThread.Join();
Logger.stop();
// if there was a problem, set an exit error code
// so the service manager will restart this
if(ABORT)Environment.Exit(1);
}
Nếu dịch vụ gặp sự cố và cần khởi động lại, tôi khởi chạy một luồng dừng dịch vụ từ SCM. Điều này cho phép dịch vụ tự dọn dẹp:
...
if(NeedToRestart)
{
ABORT = true;
new Thread(RestartThread).Start();
}
void RestartThread()
{
ServiceController sc = new ServiceController(ServiceName);
try
{
sc.Stop();
}
catch (Exception) { }
}
Tôi sẽ sử dụng Bộ lập lịch Windows để lên lịch khởi động lại dịch vụ của bạn. Vấn đề là bạn không thể tự khởi động lại, nhưng bạn có thể tự dừng lại. (Về cơ bản, bạn đã cưa nhánh cây mà bạn đang ngồi ... nếu bạn có sự tương tự của tôi) Bạn cần một quy trình riêng để làm điều đó cho bạn. Bộ lập lịch Windows là một cái thích hợp. Lên lịch tác vụ một lần để khởi động lại dịch vụ của bạn (thậm chí từ bên trong chính dịch vụ) để thực hiện ngay lập tức.
Nếu không, bạn sẽ phải tạo một quy trình "chăn cừu" phù hợp với bạn.
Câu trả lời đầu tiên cho câu hỏi là giải pháp đơn giản nhất: "Môi trường.Exit (1)" Tôi đang sử dụng điều này trên Windows Server 2008 R2 và nó hoạt động hoàn hảo. Dịch vụ tự dừng, O / S đợi 1 phút, sau đó khởi động lại.
Cách tiếp cận tốt hơn có thể là sử dụng Dịch vụ NT làm trình bao bọc cho ứng dụng của bạn. Khi Dịch vụ NT được khởi động, ứng dụng của bạn có thể bắt đầu ở chế độ "nhàn rỗi" chờ lệnh bắt đầu (hoặc được định cấu hình để bắt đầu tự động).
Hãy nghĩ về một chiếc xe, khi nó khởi động, nó bắt đầu ở trạng thái không hoạt động, chờ lệnh của bạn tiến lên hoặc lùi lại. Điều này cũng cho phép các lợi ích khác, chẳng hạn như quản trị từ xa tốt hơn khi bạn có thể chọn cách hiển thị ứng dụng của mình.
Chỉ cần vượt qua: và nghĩ rằng tôi sẽ thêm một số thông tin thêm ...
bạn cũng có thể đưa ra một ngoại lệ, điều này sẽ tự động đóng dịch vụ windows và các tùy chọn khởi động lại tự động chỉ cần khởi động. Vấn đề duy nhất là nếu bạn có môi trường dev trên máy tính thì JIT sẽ cố gắng khởi động, và bạn sẽ nhận được lời nhắc gỡ lỗi Y / N. nói không và sau đó nó sẽ đóng lại, và sau đó bắt đầu lại đúng cách. (trên PC không có JIT, nó chỉ hoạt động). Lý do tôi bị troll, là JIT này mới đối với Win 7 (nó được sử dụng để hoạt động tốt với XP, v.v.) và tôi đang cố gắng tìm cách vô hiệu hóa JIT .... tôi có thể thử phương pháp Môi trường. nó cũng hoạt động
Kristian: Bristol, Vương quốc Anh
Tạo một tập tin restart.bat như thế này
@echo on
set once="C:\Program Files\MyService\once.bat"
set taskname=Restart_MyService
set service=MyService
echo rem %time% >%once%
echo net stop %service% >>%once%
echo net start %service% >>%once%
echo del %once% >>%once%
schtasks /create /ru "System" /tn %taskname% /tr '%once%' /sc onstart /F /V1 /Z
schtasks /run /tn %taskname%
Sau đó xóa tác vụ% taskname% khi% dịch vụ% của bạn bắt đầu
Tạo một tên miền riêng để lưu trữ mã ứng dụng. Khi yêu cầu khởi động lại, chúng tôi có thể tải và tải lại tên miền appd thay vì quá trình (dịch vụ windows). Đây là cách nhóm ứng dụng IIS hoạt động, họ không chạy ứng dụng asp.net trực tiếp, họ sử dụng appdmain riêng biệt.
Cách dễ nhất là có một tệp bó với:
net dừng net bắt đầu
và thêm tệp vào bộ lập lịch với khoảng thời gian bạn muốn
private static void RestartService(string serviceName)
{
using (var controller = new ServiceController(serviceName))
{
controller.Stop();
int counter = 0;
while (controller.Status != ServiceControllerStatus.Stopped)
{
Thread.Sleep(100);
controller.Refresh();
counter++;
if (counter > 1000)
{
throw new System.TimeoutException(string.Format("Could not stop service: {0}", Constants.Series6Service.WindowsServiceName));
}
}
controller.Start();
}
}