ฉันต้องเขียนโค้ดที่มีประสิทธิภาพใน. NET เพื่อเปิดใช้งานบริการ windows (เซิร์ฟเวอร์ 2003) เพื่อรีสตาร์ทตัวเอง วิธีที่ดีที่สุดคืออะไร? มี. NET API ให้ทำบ้างไหม
ฉันต้องเขียนโค้ดที่มีประสิทธิภาพใน. NET เพื่อเปิดใช้งานบริการ windows (เซิร์ฟเวอร์ 2003) เพื่อรีสตาร์ทตัวเอง วิธีที่ดีที่สุดคืออะไร? มี. NET API ให้ทำบ้างไหม
คำตอบ:
ตั้งค่าบริการให้รีสตาร์ทหลังจากความล้มเหลว (ดับเบิลคลิกที่บริการในแผงควบคุมและดูรอบ ๆ แท็บเหล่านั้น - ฉันลืมชื่อของมัน) จากนั้นเมื่อใดก็ตามที่คุณต้องการให้บริการเริ่มต้นใหม่เพียงโทรEnvironment.Exit(1)
(หรือการส่งคืนที่ไม่ใช่ศูนย์) จากนั้นระบบปฏิบัติการจะรีสตาร์ทให้คุณ
Service.ExitCode = 1
และดำเนินการService.Stop()
พร้อมกับการเปิดใช้งานช่องทำเครื่องหมาย "เปิดใช้งานการดำเนินการเพื่อหยุดด้วยข้อผิดพลาด" บนหน้าจอการตั้งค่าการกู้คืนบริการ การทำเช่นนี้จะช่วยให้สามารถปิดเครื่องได้อย่างเหมาะสมและยังคงเริ่มการทำงาน
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()
คุณไม่สามารถแน่ใจได้ว่าบัญชีผู้ใช้ที่บริการของคุณกำลังทำงานอยู่แม้จะมีสิทธิ์หยุดและเริ่มบริการใหม่
คุณสามารถสร้างกระบวนการที่เป็นพรอมต์คำสั่ง DOS ที่รีสตาร์ทตัวเอง:
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);
ที่ไหน SERVICENAME
ชื่อบริการของคุณ (เครื่องหมายอัญประกาศคู่รวมอยู่ในช่องว่างในชื่อบริการสามารถละเว้นได้)
ทำความสะอาดไม่จำเป็นต้องกำหนดค่าการรีสตาร์ทอัตโนมัติ
ขึ้นอยู่กับว่าทำไมคุณถึงต้องการให้รีสตาร์ทตัวเอง
หากคุณกำลังมองหาวิธีที่จะให้บริการทำความสะอาดตัวเองเป็นระยะ ๆ คุณอาจมีตัวจับเวลาที่ทำงานในบริการซึ่งทำให้เกิดการล้างตามปกติเป็นระยะ ๆ
หากคุณกำลังมองหาวิธีเริ่มต้นใหม่เมื่อเกิดความล้มเหลว - โฮสต์บริการเองสามารถให้ความสามารถนั้นได้เมื่อมีการตั้งค่า
แล้วทำไมคุณต้องรีสตาร์ทเซิร์ฟเวอร์? คุณพยายามทำอะไรให้สำเร็จ?
ฉันไม่คิดว่าคุณจะสามารถใช้บริการในตัวได้ (เมื่อคุณเรียกรีสตาร์ทระบบจะหยุดบริการซึ่งจะขัดจังหวะคำสั่งรีสตาร์ทและจะไม่เริ่มต้นอีกเลย) หากคุณสามารถเพิ่ม. exe ตัวที่สอง (แอปคอนโซลที่ใช้คลาส ServiceManager) คุณสามารถเริ่มต้น. exe แบบสแตนด์อโลนและรีสตาร์ทบริการจากนั้นออก
ในความคิดที่สองคุณอาจให้บริการลงทะเบียนงานตามกำหนดเวลา (เช่นใช้คำสั่งบรรทัดคำสั่ง 'at') เพื่อเริ่มบริการจากนั้นให้หยุดทำงานเอง นั่นอาจจะใช้ได้
ปัญหาในการแบ่งออกเป็นแบตช์ไฟล์หรือ EXE คือบริการอาจมีหรือไม่มีสิทธิ์ที่จำเป็นในการเรียกใช้แอปภายนอก
วิธีที่สะอาดที่สุดที่ฉันพบคือใช้เมธอด OnStop () ซึ่งเป็นจุดเริ่มต้นสำหรับ Service Control Manager จากนั้นรหัสการล้างข้อมูลทั้งหมดของคุณจะทำงานและคุณจะไม่มีซ็อกเก็ตแขวนหรือกระบวนการอื่น ๆ โดยสมมติว่ารหัสหยุดของคุณทำงานได้ดี
ในการดำเนินการนี้คุณต้องตั้งค่าสถานะก่อนที่คุณจะยุติซึ่งจะบอกให้เมธอด OnStop ออกด้วยรหัสข้อผิดพลาด จากนั้น SCM จะรู้ว่าต้องเริ่มบริการใหม่ หากไม่มีการตั้งค่าสถานะนี้คุณจะไม่สามารถหยุดบริการด้วยตนเองจาก SCM ได้ นอกจากนี้ยังถือว่าคุณได้ตั้งค่าบริการเพื่อเริ่มต้นใหม่เมื่อเกิดข้อผิดพลาด
นี่คือรหัสหยุดของฉัน:
...
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);
}
หากบริการเกิดปัญหาและจำเป็นต้องรีสตาร์ทฉันจะเปิดเธรดที่หยุดบริการจาก SCM สิ่งนี้ช่วยให้บริการสามารถล้างข้อมูลได้เอง:
...
if(NeedToRestart)
{
ABORT = true;
new Thread(RestartThread).Start();
}
void RestartThread()
{
ServiceController sc = new ServiceController(ServiceName);
try
{
sc.Stop();
}
catch (Exception) { }
}
ฉันจะใช้ Windows Scheduler เพื่อกำหนดเวลาการเริ่มบริการของคุณใหม่ ปัญหาคือคุณไม่สามารถเริ่มต้นใหม่ได้ แต่คุณสามารถหยุดตัวเองได้ (โดยพื้นฐานแล้วคุณได้เลื่อยกิ่งไม้ที่คุณกำลังนั่งอยู่ ... ถ้าคุณได้รับการเปรียบเทียบของฉัน) คุณต้องมีกระบวนการแยกต่างหากเพื่อทำเพื่อคุณ Windows Scheduler เป็นเครื่องมือที่เหมาะสม กำหนดเวลางานครั้งเดียวเพื่อเริ่มบริการของคุณใหม่ (แม้จากภายในบริการเอง) เพื่อดำเนินการทันที
มิฉะนั้นคุณจะต้องสร้างกระบวนการ "ต้อน" ที่ทำเพื่อคุณ
คำตอบแรกสำหรับคำถามเป็นวิธีแก้ปัญหาที่ง่ายที่สุด: "Environment.Exit (1)" ฉันใช้สิ่งนี้บน Windows Server 2008 R2 และทำงานได้อย่างสมบูรณ์ บริการจะหยุดเอง O / S รอ 1 นาทีจากนั้นรีสตาร์ท
ฉันไม่คิดว่ามันจะทำได้ เมื่อบริการ "หยุด" บริการจะถูกยกเลิกการโหลดทั้งหมด
โอเคฉันคิดว่ามีวิธีเสมอ ตัวอย่างเช่นคุณสามารถสร้างกระบวนการแยกเพื่อหยุดบริการจากนั้นเริ่มต้นใหม่จากนั้นออก
แนวทางที่ดีกว่าคือการใช้ NT Service เป็นเครื่องห่อสำหรับแอปพลิเคชันของคุณ เมื่อเริ่มบริการ NT แอปพลิเคชันของคุณสามารถเริ่มต้นในโหมด "ไม่ได้ใช้งาน" เพื่อรอให้คำสั่งเริ่มทำงาน (หรือได้รับการกำหนดค่าให้เริ่มโดยอัตโนมัติ)
ลองนึกถึงรถยนต์เมื่อสตาร์ทแล้วมันเริ่มอยู่ในสถานะว่างรอให้คำสั่งของคุณเดินหน้าหรือถอยหลัง นอกจากนี้ยังช่วยให้ได้รับประโยชน์อื่น ๆ เช่นการดูแลระบบระยะไกลที่ดีขึ้นเนื่องจากคุณสามารถเลือกวิธีเปิดเผยแอปพลิเคชันของคุณได้
เพิ่งผ่าน: และคิดว่าฉันจะเพิ่มข้อมูลพิเศษ ...
นอกจากนี้คุณยังสามารถทิ้งข้อยกเว้นซึ่งจะปิดบริการ windows โดยอัตโนมัติและตัวเลือกการเริ่มต้นใหม่อัตโนมัติก็เริ่มต้นขึ้นปัญหาเดียวของสิ่งนี้คือหากคุณมีสภาพแวดล้อมการพัฒนาบนพีซีของคุณ JIT จะพยายามเตะเข้า และคุณจะได้รับข้อความแจ้งว่า debug Y / N บอกว่าไม่แล้วมันจะปิดแล้วเริ่มใหม่อย่างถูกต้อง (บนพีซีที่ไม่มี JIT มันใช้งานได้ทั้งหมด) เหตุผลที่ฉันหลอกคือ JIT นี้เป็นของใหม่สำหรับ Win 7 (เคยทำงานได้ดีกับ XP ฯลฯ ) และฉันกำลังพยายามหาวิธีปิดการใช้งาน JIT ... ฉันอาจลองใช้ Environment วิธีการออกที่กล่าวถึงที่นี่ดูว่า ที่ได้ผลเช่นกัน
Kristian: Bristol, สหราชอาณาจักร
สร้างไฟล์ restart.bat แบบนี้
@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%
จากนั้นลบงาน% taskname% เมื่อ% service% ของคุณเริ่มทำงาน
สร้าง appdomain แยกต่างหากเพื่อโฮสต์รหัสแอปพลิเคชัน เมื่อต้องรีสตาร์ทเราสามารถยกเลิกการโหลดและโหลด appdomain ใหม่แทนกระบวนการ (บริการ windows) นี่คือวิธีการทำงานของพูลแอพ IIS พวกเขาไม่ได้เรียกใช้แอพ asp.net โดยตรงพวกเขาใช้ appdmain แยกต่างหาก
วิธีที่ง่ายที่สุดคือการมีไฟล์แบตช์ที่มี:
เริ่มต้นสุทธิหยุดสุทธิ
และเพิ่มไฟล์ลงในตัวกำหนดตารางเวลาด้วยช่วงเวลาที่คุณต้องการ
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();
}
}