कैसे एक Windows सेवा प्रोग्रामेटिक रूप से खुद को पुनरारंभ कर सकता है?


135

मुझे स्वयं को पुनः आरंभ करने के लिए विंडोज़ सेवा (सर्वर 2003) को सक्षम करने के लिए .NET में मजबूत कोड लिखने की आवश्यकता है। इसका सबसे अच्छा तरीका क्या है? क्या ऐसा करने के लिए कुछ .NET एपीआई है?


7
"रोबस्ट" एक वैसल शब्द है ( stackoverflow.fogbugz.com/default.asp?W13086 ) - आपको किन विशिष्ट लक्षणों की आवश्यकता है?
ऐदन रयान

जवाबों:


187

विफलता के बाद सेवा को पुनरारंभ करने के लिए सेट करें (नियंत्रण पैनल में सेवा पर डबल क्लिक करें और उन टैब पर चारों ओर एक नज़र डालें - मैं इसका नाम भूल जाता हूं)। फिर, कभी भी आप सेवा को पुनः आरंभ करना चाहते हैं, बस कॉल करें Environment.Exit(1)(या कोई गैर-शून्य रिटर्न) और OS आपके लिए इसे पुनः आरंभ करेगा।


7
Fyi स्थान सेवा पैनल में है, प्रश्न में सेवा पर राइट क्लिक करें और गुणों का चयन करें, फिर रिकवरी टैब चुनें।
जेम्स माइकल हरे

20
मैं देखता हूं कि यह वांछित व्यवहार को कैसे प्राप्त करता है लेकिन 1 का रिटर्नकोड सिस्टम को बताने के लिए है कि कोई त्रुटि थी। क्या यह बुरा व्यवहार नहीं है अगर वास्तव में कोई त्रुटि नहीं थी और आप सिर्फ अपनी सेवा को फिर से शुरू करना चाहते थे?
mgttlinger

4
इसे इंस्टाल करने के बाद सर्विस इंस्टॉलर द्वारा प्रोग्राममैटिकली किया जा सकता है, इसके लिए क्लिक करने की आवश्यकता नहीं है ... क्या होगा यदि आपकी सेवा रिमोट सर्वर पर है और आपको इसे दिन में कई बार स्थापित करने की आवश्यकता है, उदाहरण के लिए परीक्षण के दौरान?
डीन कूगा

5
@mgttlinger: मुझे लगता है कि हाँ, एक बुरा अभ्यास है जब आपकी सेवा स्वस्थ है, इसलिए इसे फिर से शुरू करने की आवश्यकता नहीं होगी। लेकिन कुछ सेवाओं की वास्तुकला हमारी पहुंच से बाहर है और अगर उन्हें फिर से शुरू करने की आवश्यकता है, तो यह एक लक्षण है कि यह ठीक नहीं है, इसलिए कुछ न्यूनतम पुनर्वितरणों को बंद करने और मुक्त करने के लिए कोई समस्या नहीं है (यदि संभव हो तो) और 'अपने पैरों को काटें', छोड़ने के बाद से अनुचित तरीके से चलने वाली सेवा बदतर (बेकार) हो सकती है।
लुसियानो

5
@JohnLeidegren यदि आप एक उचित शटडाउन चाहते हैं तो आप सेट कर सकते हैं Service.ExitCode = 1और फिर Service.Stop()चेकबॉक्स को सक्षम करने के साथ-साथ सर्विस रिकवरी सेटिंग स्क्रीन पर त्रुटियों के साथ स्टॉप के लिए कार्रवाई सक्षम करें ’। इस तरह से करना एक उचित शटडाउन की अनुमति देता है और फिर भी पुनरारंभ को चालू करता है।
क्रिस राइस

22
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()

3
यदि आप इसमें रिक्त स्थान रखते हैं, तो आप "" नाम से जुड़े हुए हैं।
एपीसी

4
यह केवल विशेषाधिकार प्राप्त खाते के तहत चलने वाली सेवाओं के लिए है, जो वैसे भी बुरा विचार है।
दिमित्री गुसरोव

17

आप यह सुनिश्चित नहीं कर सकते हैं कि आपकी सेवा जिस उपयोगकर्ता खाते के तहत चल रही है, उसके पास सेवा को रोकने और पुनः आरंभ करने की अनुमति भी है।


हालाँकि + 1-ed जैसा कि मैंने एक ही समस्या का सामना किया था, जब sc.exe को देखते हुए यह पता चलता है कि यह Open_Manager () को कॉल करते समय SERVICE_QUERY_CONFIG को dwDesiredAccess के रूप में उपयोग करता है और फिर OpenService () को Service_START के साथ कॉल करता है। किसी विशेष सेवा को खोलने के लिए SERVICE_STOP और यह ठीक काम करता है (पहुंच में कोई समस्या नहीं)। यह कैसे .NET में किया जा सकता है, इस बारे में निश्चित नहीं है।
n0p

अधिकांश Windows सेवाएँ सिस्टम के रूप में चलती हैं, इसलिए यह समस्या नहीं होनी चाहिए।
स्विच करें

@Switch में ऐसी बहुत सारी सेवाएँ हैं, जो NETWORK SERVICE के तहत चलाई जाती हैं, जो डिफ़ॉल्ट रूप से अपने निष्पादन योग्य को खोलने का अधिकार भी नहीं रखती हैं।
AgentFire

@AgentFire, सही, लेकिन डिफ़ॉल्ट स्थानीय प्रणाली है, नेटवर्क सेवा नहीं। स्थानीय प्रणाली में ऑपरेटिंग सिस्टम के लिए विशेष रूप से उच्चतम स्तर के विशेषाधिकार हैं - जो स्थानीय प्रशासक समूह के सदस्यों को सौंपा गया है।
स्विच करें

@Switch लेकिन सबसे अधिक उपलब्ध विशेषाधिकारों का उपयोग PoL-Principle का उल्लंघन कर रहा है ।
AgentFire

12

आप एक प्रक्रिया बना सकते हैं जो एक डॉस कमांड प्रॉम्प्ट है जो खुद को पुनरारंभ करता है:

 Process process = new Process();
 process.StartInfo.FileName = "cmd";
 process.StartInfo.Arguments = "/c net stop \"servicename\" & net start \"servicename\"";
 process.Start();

यह, और कुछ किए बिना, कॉलिंग थ्रेड के सुरक्षा संदर्भ को विरासत में मिलेगा ... और जब तक यह एक संदर्भ है जिसमें पुनरारंभ करने के लिए पर्याप्त हॉर्स पावर है, तो आप अच्छे हैं।
क्ले

12
const string strCmdText = "/C net stop \"SERVICENAME\"&net start \"SERVICENAME\"";
Process.Start("CMD.exe", strCmdText);

कहाँ पे SERVICENAMEआपकी सेवा का नाम है (सेवा नाम में रिक्त स्थान के लिए शामिल किए गए दोहरे उद्धरण, अन्यथा अन्यथा छोड़े जा सकते हैं)।

स्वच्छ, कोई ऑटो-पुनरारंभ कॉन्फ़िगरेशन आवश्यक नहीं है।


9
& कमांड &&: [कमांड 1] और [कमांड 2] के बारे में कुछ नया सीखा है, दोनों क्रमों को क्रमिक रूप से निष्पादित करेगा, जबकि [कमांड 1] और& [कमांड 2] केवल कमांड 1 को सफलतापूर्वक चलाता है ( autoitscript.com/forum.topic/… )
जेफरी नाइट

5

यह इस बात पर निर्भर करेगा कि आप यह क्यों स्वयं को पुनः आरंभ करना चाहते हैं।

यदि आप समय-समय पर सेवा को स्वयं साफ करने का तरीका ढूंढ रहे हैं, तो आप सेवा में एक टाइमर चला सकते हैं जो समय-समय पर एक शुद्ध दिनचर्या का कारण बनता है।

यदि आप विफलता पर पुनः आरंभ करने का एक तरीका ढूंढ रहे हैं - सेवा होस्ट स्वयं सेटअप होने पर वह क्षमता प्रदान कर सकता है।

तो आपको सर्वर को पुनरारंभ करने की आवश्यकता क्यों है? आप क्या हासिल करने का प्रयास कर रहे हैं?


1
यदि आप बड़े ऑब्जेक्ट हीप और मेमोरी विखंडन से चिंतित हैं तो यह काम नहीं करेगा। माना जाता है कि .NET 4 / 4.5 और 64-बिट प्रक्रियाओं ने इसके साथ बहुत मदद की है।
डेविड कासा

3

मुझे नहीं लगता कि आप एक स्व-निहित सेवा में हो सकते हैं (जब आप रिस्टार्ट कहते हैं, तो यह सेवा को रोक देगा, जो रीस्टार्ट कमांड को बाधित करेगा, और यह फिर से शुरू नहीं होगा)। यदि आप एक दूसरा .exe (एक कंसोल ऐप जो ServiceManager वर्ग का उपयोग करता है) जोड़ सकते हैं, तो आप स्टैंडअलोन .exe को बंद कर सकते हैं और सेवा को पुनरारंभ कर सकते हैं और फिर बाहर निकल सकते हैं।

दूसरे विचार पर, शायद आप सेवा शुरू करने के लिए सेवा को एक अनुसूचित कार्य (कमांड-लाइन का उपयोग करके 'कमांड, उदाहरण के लिए) रजिस्टर कर सकते हैं और फिर इसे स्वयं रोक सकते हैं; वह शायद काम करेगा।


3

एक बैच फ़ाइल या EXE के लिए शेलिंग के साथ समस्या यह है कि किसी सेवा में बाहरी ऐप को चलाने के लिए आवश्यक अनुमतियाँ हो सकती हैं या नहीं भी हो सकती हैं।

ऐसा करने का सबसे साफ तरीका जो मुझे मिला है वह है ऑनस्टॉप () पद्धति का उपयोग करना, जो सेवा नियंत्रण प्रबंधक के लिए प्रवेश बिंदु है। फिर आपका सभी सफाई कोड चलेगा, और आपके पास कोई भी लटकाने वाला सॉकेट या अन्य प्रक्रिया नहीं होगी, यह मानते हुए कि आपका स्टॉप कोड अपना काम कर रहा है।

ऐसा करने के लिए आपको समाप्त करने से पहले एक ध्वज सेट करने की आवश्यकता होती है जो त्रुटि कोड के साथ बाहर निकलने के लिए 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) { }
}

2

मैं आपकी सेवा को पुनः आरंभ करने के लिए Windows समयबद्धक का उपयोग करूंगा। समस्या यह है कि आप स्वयं को पुनः आरंभ नहीं कर सकते, लेकिन आप स्वयं को रोक सकते हैं। (आप अनिवार्य रूप से उस शाखा को देख चुके हैं, जिस पर आप बैठे हैं ... यदि आपको मेरी उपमा मिल गई है) तो आपको इसे करने के लिए एक अलग प्रक्रिया की आवश्यकता है। विंडोज शेड्यूलर एक उपयुक्त है। तुरंत निष्पादित करने के लिए अपनी सेवा (यहां तक ​​कि स्वयं सेवा के भीतर से) को पुनरारंभ करने के लिए एक बार के कार्य को शेड्यूल करें।

अन्यथा, आपको एक "चरवाहा" प्रक्रिया बनानी होगी जो इसे आपके लिए करती है।


2

प्रश्न का पहला उत्तर सबसे सरल समाधान है: "पर्यावरण। एक्सिट (1)" मैं इसका उपयोग विंडोज सर्वर 2008 R2 पर कर रहा हूं और यह पूरी तरह से काम करता है। सेवा स्वयं बंद हो जाती है, ओ / एस 1 मिनट इंतजार करता है, फिर इसे पुनरारंभ करता है।


कितनी देर प्रतीक्षा करता है यह इस बात पर निर्भर करता है कि आपने इसे कितने समय तक प्रतीक्षा करने के लिए निर्धारित किया है। डिफ़ॉल्ट 1 मिनट हालांकि है, लेकिन अगर कोई नहीं चाहता है कि आपका जवाब गलत प्रभाव देगा।
एस्पेन

1

मुझे नहीं लगता कि यह हो सकता है। जब कोई सेवा "बंद" होती है, तो यह पूरी तरह से अनलोड हो जाता है।

ठीक है, ठीक है, हमेशा एक तरीका है जो मुझे लगता है। उदाहरण के लिए, आप सेवा को रोकने के लिए एक अलग प्रक्रिया बना सकते हैं, फिर उसे पुनरारंभ करें, फिर बाहर निकलें।


0

बेहतर तरीका यह हो सकता है कि आप एनटी सेवा का उपयोग अपने आवेदन के लिए एक आवरण के रूप में कर सकते हैं। जब NT सेवा शुरू की जाती है, तो आपका एप्लिकेशन एक "निष्क्रिय" मोड में शुरू हो सकता है जो कमांड के शुरू होने की प्रतीक्षा कर रहा है (या स्वचालित रूप से शुरू करने के लिए कॉन्फ़िगर किया जा सकता है)।

एक कार के बारे में सोचो, जब यह शुरू होता है तो यह एक निष्क्रिय स्थिति में शुरू होता है, आपके आदेश के आगे या रिवर्स होने की प्रतीक्षा करता है। यह अन्य लाभों के लिए भी अनुमति देता है, जैसे कि बेहतर दूरस्थ प्रशासन, जैसा कि आप चुन सकते हैं कि अपने आवेदन को कैसे उजागर किया जाए।


0

बस गुजर रहा है: और सोचा कि मैं कुछ अतिरिक्त जानकारी जोड़ूंगा ...

आप एक अपवाद भी फेंक सकते हैं, यह विंडोज़ सेवा को बंद कर देगा, और ऑटो री-स्टार्ट विकल्प सिर्फ किक करेंगे। इसके साथ एकमात्र मुद्दा यह है कि यदि आपके पीसी पर एक देव एनवायरमेंट है तो जेआईटी को किक करने की कोशिश करता है। और आपको डिबग Y / N कहने का संकेत मिलेगा। नहीं, और तब यह बंद हो जाएगा, और फिर ठीक से फिर से शुरू होगा। (बिना किसी JIT वाले पीसी पर यह सब काम करता है)। कारण im im trolling, क्या यह JIT विन 7 के लिए नया है (यह XP आदि के साथ ठीक काम करता था) और im JIT को अक्षम करने का एक तरीका खोजने की कोशिश कर रहा है .... मैं यहां पर्यावरण की कोशिश कर सकता हूं। इस विधि का उल्लेख यहां देखें वह भी काम करता है।

क्रिस्टियन: ब्रिस्टल, यूके


3
इन सभी अपवाद, निकास (1) समाधान सभी एक आवेदन के उचित सफाई से बचते हैं।
अनजाने में

0

इस तरह एक रिस्टार्ट।बैट फाइल बनाएं

@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% हटाएं


0

एप्लिकेशन कोड को होस्ट करने के लिए एक अलग एपडोमेन बनाएं। जब पुनरारंभ की आवश्यकता होती है, तो हम प्रक्रिया (विंडोज़ सेवा) के बजाय एपडोमेन को अनलोड और लोड कर सकते हैं। यह है कि IIS ऐप पूल कैसे काम करता है, वे सीधे asp.net ऐप नहीं चलाते हैं, वे अलग-अलग ऐपमैन का उपयोग करते हैं।


-2

सबसे आसान तरीका एक बैच फ़ाइल है:

नेट स्टॉप नेट स्टार्ट

और अपने इच्छित समय अंतराल के साथ अनुसूचक में फ़ाइल जोड़ें


यह काम नहीं कर रहा है क्योंकि दोनों कमांड के बीच बैच को रोक दिया गया है, क्योंकि यह सेवा की एक बाल प्रक्रिया है।
ओरबग

-3
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();
        }
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.