ऐप की नज़र से Windows शटडाउन — निकास सूचना, रीस्टार्ट और बिजली कटौती से सही ढंग से बचना

· · Windows, शटडाउन, Windows विकास, Windows सेवाएँ, डिवाइस PC, डेटा अखंडता, लंबे समय चलने वाला काम, UPS

“Windows Update की रात वाली रीस्टार्ट के बाद डिवाइस PC पर माप ऐप लिखते-लिखते गिर गया, और सुबह माप फ़ाइल खराब थी।” “किसी ने साझा PC से साइन-आउट किया और शिकायत की कि न-सेव संपादन गायब हो गए।” — लंबे समय चलने वाले Windows ऐप के लिए ये दो परामर्श क्लासिक हैं।

दोनों साइटों में समान बात शटडाउन को “ऐसी असामान्य घटना जो नहीं होनी चाहिए” मानना है। वास्तविकता में, Windows Update स्वचालित रीस्टार्ट, उपयोगकर्ता साइन-आउट, और UPS-प्रेरित शटडाउन से लेकर बिना घोषणा बिजली कटौती तक, ऐप के बाहर से निष्पादन काटने वाली घटनाएँ आएँगी, देर-सबेर। उन्हें आने से रोक नहीं सकते। जो रोक सकते हैं वह है “जब आएँ तो डेटा खोना”।

सौभाग्य से Windows के पास शटडाउन से पहले ऐप को सूचित करने का तंत्र है — GUI ऐप, कंसोल ऐप और सेवा, तीनों के लिए। छोटे-मध्यम व्यवसायों के IT स्टाफ और Windows ऐप डेवलपरों (विशेषकर डिवाइस-PC और लंबे समय चलने वाले ऐप) के लिए, यह लेख उन सूचनाओं को कैसे लें, “कुछ सेकंड में खत्म” क्लीनअप कैसे डिज़ाइन करें, रीस्टार्ट के बाद स्वचालित पुनर्प्राप्ति, और बिना सूचना बिजली कटौती की तैयारी — सब अगस्त 2026 तक Microsoft Learn प्राथमिक स्रोतों पर आधारित — व्यवस्थित करता है।

1. निष्कर्ष पहले

  • शटडाउन को “सामान्य घटना जो देर-सबेर आएगी” मानकर डिज़ाइन करें। सूचना मिलने के बाद उपयोग योग्य समय सिद्धांततः लगभग 5 सेकंड ही है, इसलिए वहीं सब कुछ हड़बड़ी से सेव करने वाला डिज़ाइन टूट जाएगा। पूर्वापेक्षा बार-बार ऑटोसेव है ताकि “शटडाउन पर सेव करने वाला डेल्टा” छोटा रहे।1
  • Windows 8 से आगे के क्लाइंट OS पर, जब fast startup चालू हो (हाइबरनेशन समर्थित अधिकांश PC पर डिफ़ॉल्ट), “Shut down” hybrid shutdown है, और कर्नेल केवल हाइबरनेट हो रहा है। पूरी तरह रीसेट केवल “Restart” है। यही असली कारण है “मैंने शटडाउन किया, बेहतर नहीं हुआ, फिर रीस्टार्ट किया तो हुआ”।2
  • GUI ऐप को WM_QUERYENDSESSION पर तुरंत TRUE लौटाना चाहिए, और क्लीनअप WM_ENDSESSION में करना चाहिए। सिद्धांततः FALSE (अस्वीकार) नहीं लौटाना।1
  • केवल जब सचमुच ऐसा काम हो जो बीच में नहीं काटा जा सकता, ShutdownBlockReasonCreate से कारण दिखाएँ। तब भी उपयोगकर्ता और OS ज़बरदस्ती जारी रख सकते हैं, इसलिए “हम ब्लॉक कर सकते हैं” मानने वाला डिज़ाइन टिकता नहीं।34
  • कंसोल ऐप सूचना SetConsoleCtrlHandler से पाता है। छूट और छोटी है — कंसोल बंद पर डिफ़ॉल्ट 5 सेकंड। एक जाल भी है: जिस प्रक्रिया ने gdi32.dll या user32.dll लोड किया हो, इनमें से कुछ इवेंट नहीं आते।56
  • .NET के AppDomain.ProcessExit पर निर्भर क्लीनअप .NET 10 से उन पथों पर नहीं चलता जहाँ प्रक्रिया “बाहर से समाप्त” होती है। Main से लौटने जैसी सामान्य निकास पर वह पहले जैसा चलता है, पर क्योंकि रनटाइम कंसोल बंद और शटडाउन जैसे समाप्ति सिग्नलों का डिफ़ॉल्ट हैंडलिंग नहीं देता, उन पथों का क्लीनअप ऐप मॉडल से मेल खाने वाली सूचना पर जाना चाहिए।7
  • Windows सेवा SERVICE_ACCEPT_PRESHUTDOWN SERVICE_ACCEPT_SHUTDOWN (लगभग 20 सेकंड छूट) से पहले, और कॉन्फ़िगर करने योग्य छूट के साथ, पा सकती है। पर डिफ़ॉल्ट PRESHUTDOWN टाइमआउट Windows 10 Creators Update से 10 सेकंड कर दिया गया, इसलिए दोनों तरह छूट पर बहुत झुकने वाला डिज़ाइन नहीं चाहिए।89
  • रीस्टार्ट के बाद स्वचालित पुनर्प्राप्ति RegisterApplicationRestart को ARSO (स्वचालित साइन-ऑन) से जोड़कर हो सकती है। क्रैश, अनुत्तरदायी, और अपडेट-चालित रीस्टार्ट के लिए पथ हैं।1011
  • बिजली कटौती कोई सूचना नहीं लाती। मानक पैटर्न अस्थायी फ़ाइल में पूरा लिखना, फ्लश, और ReplaceFile से अदला-बदली है, पर क्योंकि बिजली कटने पर ReplaceFile भी परमाण्विकता गारंटी नहीं देता, बैकअप (.bak) प्लस लोड-समय जाँच पुनर्प्राप्ति पथ सेट का हिस्सा है। बाद का अलगाव इवेंट लॉग (1074/41/6008) से हो सकता है।121314

एक वाक्य में इस लेख का निष्कर्ष: “सूचना आने पर कुछ सेकंड में दुकान बंद कर सकने वाली अवस्था हमेशा रखें, और ऐसे लिखें जो बिना सूचना बिजली कटौती पर भी न टूटे”

2. शटडाउन पर क्या होता है — समाप्त होने के चार रास्ते

2.1. साइन-आउट, शटडाउन, रीस्टार्ट और बिजली कटौती

ऐप की नज़र से दो अक्ष मायने रखते हैं: “उपयोगकर्ता सत्र कैसे खत्म होता है” और “कर्नेल का क्या होता है”।

क्रिया उपयोगकर्ता सत्र कर्नेल और ड्राइवर ऐप को सूचना
साइन-आउट खत्म चलता रहता है WM_QUERYENDSESSION (ENDSESSION_LOGOFF) → WM_ENDSESSION
शटडाउन (fast startup चालू) खत्म हाइबरनेट (hiberfil.sys में सहेजा) WM_QUERYENDSESSION → WM_ENDSESSION, सेवाओं को (PRE)SHUTDOWN
रीस्टार्ट खत्म पूरी तरह खत्म; अगला बूट पूर्ण बूट ऊपर जैसा
बिजली कटौती तुरंत गायब तुरंत गायब कोई नहीं

ऐप की नज़र से साइन-आउट और शटडाउन लगभग एक ही इवेंट हैं। यदि WM_QUERYENDSESSION के lParam में ENDSESSION_LOGOFF बिट सेट हो तो साइन-आउट है; यदि 0 हो तो शटडाउन या रीस्टार्ट (दोनों अलग नहीं बता सकते)।1 यानी “केवल साइन-आउट है, चल जाएगा” वाली ढिलाई टिकती नहीं, और सही डिज़ाइन वही क्लीनअप कोड चलाना है

समाप्त होने के चार रास्ते, और ऐप को सूचनासाइन-आउट, शटडाउन और रीस्टार्ट WM_QUERYENDSESSION से WM_ENDSESSION सूचना देते हैं, और क्लीनअप कुछ सेकंड में खत्म होता है। केवल बिजली कटौती पर कोई सूचना नहीं, इसलिए अध्याय 8 के लेखन डिज़ाइन और UPS से तैयारी करेंसाइन-आउटQUERY → ENDSESSIONशटडाउनरीस्टार्टबिजली कटौतीसूचना नहीं: लेखन + UPSसेकंडों में क्लीनअप

चित्र 1: साइन-आउट, शटडाउन और रीस्टार्ट WM_QUERYENDSESSION से WM_ENDSESSION सूचना देते हैं, और क्लीनअप कुछ सेकंड में खत्म होता है। केवल बिजली कटौती पर कोई सूचना नहीं, इसलिए अध्याय 8 के लेखन डिज़ाइन और UPS से तैयारी करें।

2.2. “मैंने शटडाउन किया फिर भी बेहतर नहीं हुआ” का असली कारण — hybrid shutdown

तालिका की आसानी से छूटने वाली पंक्ति दूसरी है। Windows 8 से आगे के क्लाइंट OS पर fast startup (hybrid shutdown) हाइबरनेशन समर्थित PC पर डिफ़ॉल्ट से चालू है, और “Shut down” का व्यवहार बदल गया। उपयोगकर्ता सत्र का साइन-आउट पहले जैसा होता है, पर कर्नेल सत्र बंद नहीं होता; वह डिवाइस ड्राइवर समेत हाइबरनेशन फ़ाइल (hiberfil.sys) में सहेजा जाता है और अगले बूट पर ज्यों-का-त्यों लौटता है। इससे स्टार्टअप तेज़ होता है, पर कर्नेल और ड्राइवर अवस्था बिजली काटने पर भी बचती है।2 यह, पर, सशर्त व्यवहार है। जहाँ हाइबरनेशन स्वयं बंद हो (powercfg /hibernate off), जहाँ नीति या Power Options ने fast startup बंद किया हो, और Windows Server पर, शटडाउन पारंपरिक पूर्ण शटडाउन है। दिया PC किस रास्ते पर है, Power Options के “Turn on fast startup” चेक बॉक्स से, या powercfg /a (उपलब्ध स्लीप अवस्थाएँ) “Fast Startup” सूचीबद्ध करता है या नहीं, उससे पता चलता है।

Shut down क्रिया पर कर्नेल का क्या होता हैShut down क्रिया fast startup चालू होने पर पूर्ण शटडाउन या कर्नेल हाइबरनेशन में बँटती है, और Restart हमेशा पूर्ण बूट करता हैFast startup चालूहाइबरनेट बंद / ServerShut downRestartसत्र खत्म + कर्नेल हाइबरनेटपूर्ण शटडाउनअगला: कर्नेल पुनर्स्थापितअगला: पूर्ण बूट

चित्र 2: Shut down क्रिया fast startup चालू होने पर पूर्ण शटडाउन या कर्नेल हाइबरनेशन में बँटती है, और Restart हमेशा पूर्ण बूट करता है।

इसके विपरीत “Restart” हमेशा पूरा बूट चक्र चलाता है। ड्राइवर अपडेट के बाद, उदाहरण के लिए, पूरी तरह नई अवस्था चाहिए।2 उससे मैदान में सुनी कई घटनाएँ जगह बैठती हैं।

  • “मैंने शटडाउन कर फिर चालू किया, पर डिवाइस समस्या नहीं गई” — कर्नेल और ड्राइवर केवल हाइबरनेशन से लौटे; रीसेट नहीं हुए
  • “रीस्टार्ट के बाद बेहतर हुआ” — क्योंकि पूर्ण बूट ने उन्हें आरंभ किया
  • डिवाइस-PC घटना प्रक्रिया को कहना चाहिए “Restart”, “बंद करके चालू करें” नहीं

कमांड लाइन से पूर्ण शटडाउन स्पष्ट करना हो तो shutdown /s (Shutdown.exe का डिफ़ॉल्ट पूर्ण शटडाउन है); डिफ़ॉल्ट हाइब्रिड व्यवहार चाहिए तो shutdown /s /hybrid2 fast startup बंद करना अनुशंसित नहीं। ऐप पक्ष को मानना चाहिए “शटडाउन पर कर्नेल केवल हाइबरनेट हो सकता है” — उदाहरण के लिए OS बूट समय से “संचयी अपटाइम” न आँकें — और डिज़ाइन करें कि किसी भी रास्ते न टूटे (fast startup चालू या बंद वातावरण से भिन्न होता है)।

3. GUI ऐप को कैसा व्यवहार करना चाहिए — WM_QUERYENDSESSION और WM_ENDSESSION

3.1. दो संदेश काम कैसे बाँटते हैं

जिस ऐप के पास विंडो और संदेश कतार हो उसे सत्र समाप्ति दो चरणों में सूचित होती है।1

  1. WM_QUERYENDSESSION — प्रश्न: “खत्म करना ठीक है?” ऐप को तुरंत TRUE लौटाना चाहिए; DefWindowProc का डिफ़ॉल्ट उत्तर भी TRUE है। यहाँ क्लीनअप शुरू न करें।
  2. WM_ENDSESSION (wParam=TRUE) — निश्चित सूचना: “सत्र सचमुच खत्म हो रहा है”। क्लीनअप यहाँ होता है।

WM_QUERYENDSESSION पर FALSE लौटाना शटडाउन रोक सकता है, पर दस्तावेज़ स्पष्ट है कि “आपको TRUE लौटाकर उपयोगकर्ता के इरादे का सम्मान करना चाहिए”, और FALSE लौटाने वाला ऐप फिर भी पूर्ण-स्क्रीन UI में “शटडाउन रोकने वाला ऐप” दिखता है। कंसोल ऐप और बिना दिखाई विंडो वाले ऐप शटडाउन रोक ही नहीं सकते, और 5 सेकंड में उत्तर न दें तो स्वचालित समाप्त हो जाते हैं।14

दो-चरण सत्र-समाप्ति सूचना का प्रवाहWM_QUERYENDSESSION प्रश्न पर TRUE लौटाने से WM_ENDSESSION निश्चित होता है और क्लीनअप चलता है। FALSE से अस्वीकार ऐप को शटडाउन रोकने वाला दिखाता है, और लगभग 5 सेकंड बिना उत्तर ज़बरदस्ती जारी रख सकता हैTRUE(नियम)FALSE(अस्वीकार)कोई उत्तर नहीं ~5 सेकंडज़बरदस्ती जारीरद्दWM_QUERYENDSESSIONWM_ENDSESSION(निश्चित)शटडाउन रोकने वाला दिखायाहैंग मानाक्लीनअप यहाँप्रक्रिया निकासशटडाउन निरस्त

चित्र 3: WM_QUERYENDSESSION प्रश्न पर TRUE लौटाने से WM_ENDSESSION निश्चित होता है और क्लीनअप चलता है। FALSE से अस्वीकार ऐप को शटडाउन रोकने वाला दिखाता है, और लगभग 5 सेकंड बिना उत्तर ज़बरदस्ती जारी रख सकता है।

3.2. उत्तर न दें तो क्या होता है — 5-सेकंड की दीवार

WM_QUERYENDSESSION और WM_ENDSESSION दोनों पर उत्तर लगभग 5 सेकंड विलंबित कर सकते हैं। उससे आगे सिस्टम “यह ऐप शटडाउन रोक रहा है” स्क्रीन दिखाता है, और उपयोगकर्ता ज़बरदस्ती जारी (= ऐप को ज़बरदस्ती समाप्त) चुन सकता है।4 ज़बरदस्ती समाप्त प्रक्रिया को सेव खत्म करने का दूसरा मौका नहीं मिलता।

डिज़ाइन बिंदु इसलिए ये दो हैं।

  • क्लीनअप उस मात्रा तक रखें जो 5 सेकंड में खत्म हो। Microsoft स्वयं सामान्य काम में डेटा बार-बार सेव करने की सलाह देता है ताकि शटडाउन पर कम सेव करना पड़े, और न-सेव डेटा अस्थायी स्थान पर सेव कर अगले लॉन्च पर पुनर्स्थापित करें।1
  • शटडाउन के दौरान पुष्टि संवाद न दिखाएँ। जब आप “सेव करना चाहते हैं?” पर बैठे हों, 5 सेकंड बीत जाते हैं। चुपचाप सुरक्षित पक्ष पर जाएँ (ऑटोसेव)।

3.3. WinForms और WPF में कार्यान्वयन

.NET डेस्कटॉप ऐप में ये संदेश फ्रेमवर्क इवेंट बनते हैं। WinForms में FormClosing उठता है, और CloseReason बताता है कि शटडाउन कारण है या नहीं।

// WinForms: FormClosing is also raised on shutdown / sign-out
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
    if (e.CloseReason == CloseReason.WindowsShutDown)
    {
        // Do only an idempotent snapshot save. Do not show a dialog.
        // Do not set e.Cancel = true (refuse) either.
        SaveWorkingStateToTempFile();
        return;
    }

    // For ordinary closes such as the user clicking the × button, you may confirm here
}

WPF में Application.SessionEnding इवेंट (XAML SessionEnding विशेषता, या OnSessionEnding ओवरराइड) मेल खाता है।

WinForms/WPF इवेंट संदेशों से कैसे मैप होते हैंWM_QUERYENDSESSION का क्वेरी चरण WinForms FormClosing और WPF SessionEnding से मैप होता है, और वहाँ अधिकतम idempotent स्नैपशॉट सेव करें। निश्चित WM_ENDSESSION का संगत इवेंट नहीं, इसलिए WndProc या हुक में लें और केवल निश्चित होने के बाद चल सकने वाला क्लीनअप करेंWM_QUERYENDSESSIONWinForms: FormClosingWPF: SessionEndingकेवल idempotent स्नैपशॉटWM_ENDSESSIONकोई इवेंट नहीं: WndProc हुकनिश्चित होने के बाद क्लीनअप

चित्र 4: WM_QUERYENDSESSION का क्वेरी चरण WinForms FormClosing और WPF SessionEnding से मैप होता है, और वहाँ अधिकतम idempotent स्नैपशॉट सेव करें। निश्चित WM_ENDSESSION का संगत इवेंट नहीं, इसलिए WndProc या हुक में लें और केवल निश्चित होने के बाद चल सकने वाला क्लीनअप करें।

// WPF: App.xaml.cs
protected override void OnSessionEnding(SessionEndingCancelEventArgs e)
{
    base.OnSessionEnding(e);

    // You can distinguish ReasonSessionEnding.Logoff / Shutdown,
    // but the baseline is to run the same snapshot save in either case
    SaveWorkingStateToTempFile();

    // Do not set e.Cancel = true unless you have an exceptional reason
}

यहाँ एक चेतावनी है। FormClosing (CloseReason.WindowsShutDown) और WPF का SessionEnding दोनों क्वेरी चरण (WM_QUERYENDSESSION) से मेल खाते हैं। यदि कोई अन्य ऐप अस्वीकार करे, शटडाउन निरस्त होता है और आपका ऐप चलता रहता है। इसलिए इन इवेंट में जो कर सकते हैं वह है idempotent स्नैपशॉट सेव जो शटडाउन निरस्त होने पर नुकसान न करे और जितनी बार चले वही परिणाम दे। यदि “क्लीनअप जो केवल सचमुच खत्म होते समय करना हो” (डिस्कनेक्ट, संसाधन वापस, आदि) चाहिए, निश्चित WM_ENDSESSION (wParam=TRUE) को सीधे WndProc में हुक करें और वहाँ करें।

किसी भी पथ पर शरीर को साझा “स्नैपशॉट सेव” फ़ंक्शन में मोड़ें और सामान्य निकास, शटडाउन, और (यदि संभव हो) क्रैश के लिए पुनर्स्थापना डेटा एक ही प्रारूप में लिखें, ताकि अगले लॉन्च पर पुनर्स्थापना तर्क एक पथ हो। क्रैश पर भी जानकारी छोड़ने का डिज़ाइन “क्रैश पर लॉग और डंप छोड़ने वाले Windows ऐप डिज़ाइन करना” में है।

4. यदि सचमुच ब्लॉक करना हो — ShutdownBlockReasonCreate

जो काम बीच में कटने पर भौतिक रूप से टूटते हैं, जैसे CD या फ़र्मवेयर लिखना, अपवाद हैं। यहाँ सही अभ्यास है अबाधनीय काम शुरू होने पर ShutdownBlockReasonCreate से कारण स्ट्रिंग पंजीकृत करना, और खत्म होते ही ShutdownBlockReasonDestroy कॉल करना। शटडाउन अनुरोध पर वह कारण “यह ऐप शटडाउन रोक रहा है” स्क्रीन पर दिखता है, और उपयोगकर्ता जारी रखने या रद्द करने का निर्णय ले सकता है।3

ShutdownBlockReasonCreate से सुरक्षा का प्रवाहअबाधनीय काम शुरू होने पर कारण पंजीकृत करें; सुरक्षा के दौरान शटडाउन अनुरोध आए तो कारण पूर्ण स्क्रीन पर दिखता है और WM_QUERYENDSESSION FALSE से अस्वीकृत होता है। उपयोगकर्ता रद्द या ज़बरदस्ती जारी रख सकता है, और काम खत्म होने पर कारण साफ़ होता हैरद्दज़बरदस्ती जारीअबाधनीय काम शुरूShutdownBlockReasonCreateवर्कर थ्रेड पर चलाएँखत्म: Destroyइस दौरान शटडाउनकारण दिखाएँ + FALSEप्रक्रिया निकास

चित्र 5: अबाधनीय काम शुरू होने पर कारण पंजीकृत करें; सुरक्षा के दौरान शटडाउन अनुरोध आए तो कारण पूर्ण स्क्रीन पर दिखता है और WM_QUERYENDSESSION FALSE से अस्वीकृत होता है। उपयोगकर्ता रद्द या ज़बरदस्ती जारी रख सकता है, और काम खत्म होने पर कारण साफ़ होता है।

[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern bool ShutdownBlockReasonCreate(IntPtr hWnd, string pwszReason);

[DllImport("user32.dll", SetLastError = true)]
static extern bool ShutdownBlockReasonDestroy(IntPtr hWnd);

// Call from the thread that created the main window (it fails from other threads)
_criticalOperationInProgress = true;
ShutdownBlockReasonCreate(this.Handle, "Writing measurement data to a file");
try
{
    // Run the uninterruptible operation on a worker thread. If you run it
    // synchronously on the UI thread the message pump stops, and the process
    // is force-continued as "Not Responding" before the WM_QUERYENDSESSION
    // refusal code below can run
    await Task.Run(() => WriteMeasurementData());
}
finally
{
    ShutdownBlockReasonDestroy(this.Handle);
    _criticalOperationInProgress = false;
}

// Also, refuse WM_QUERYENDSESSION with FALSE only while protected
protected override void WndProc(ref Message m)
{
    const int WM_QUERYENDSESSION = 0x0011;
    if (m.Msg == WM_QUERYENDSESSION && _criticalOperationInProgress)
    {
        m.Result = IntPtr.Zero;   // Refuse. The registered reason string is shown in the full-screen UI
        return;
    }
    base.WndProc(ref m);
}

यहाँ आसानी से होने वाली गलतफहमी भूमिकाओं का विभाजन है। ShutdownBlockReasonCreate केवल कारण स्ट्रिंग पंजीकृत करता है; वह स्वयं शटडाउन नहीं रोकता। जो सचमुच शटडाउन रोकता है वह आपका अपना हैंडलिंग है जो सुरक्षा ध्वज सेट रहते WM_QUERYENDSESSION पर FALSE लौटाता है, जैसा ऊपर। दोनों को सेट की तरह उपयोग करें, और काम खत्म होते ही दोनों तुरंत साफ़ करें। साथ ही, सुरक्षित काम स्वयं वर्कर थ्रेड पर चलाएँ और UI थ्रेड संदेश संसाधित कर सके — अस्वीकार तंत्र तभी काम करता है जब संदेश आए (और तब भी उपयोगकर्ता और OS ज़बरदस्ती जारी रख सकते हैं, इसलिए “यदि नहीं रुका” तो न टूटने वाला लेखन डिज़ाइन — अध्याय 8 — अभी भी चाहिए)।

परिचालन की तीन चेतावनियाँ हैं।

  • कारण स्ट्रिंग छोटी और विशिष्ट रखें। उपयोगकर्ता जल्दी में है और कुछ सेकंड ही पढ़ेगा। दस्तावेज़ स्वयं “Burning a CD” उपयुक्त उदाहरण देता है।3
  • ऐप के पूरे जीवन पंजीकृत न छोड़ें। “केवल जब अबाधनीय काम चल रहा हो” वही API मानता है।
  • इस धारणा पर डिज़ाइन न करें कि ब्लॉक कर सकते हैं। उपयोगकर्ता ज़बरदस्ती जारी चुन सकता है, और ज़बरदस्ती शटडाउन (ENDSESSION_CRITICAL) पहले से प्रतीक्षा नहीं करेगा। दस्तावेज़ स्पष्ट है: “Applications should not depend on being able to block shutdown”।4

5. कंसोल ऐप और पृष्ठभूमि प्रक्रियाओं को कैसा व्यवहार करना चाहिए

5.1. SetConsoleCtrlHandler और छोटी छूट

कंसोल ऐप विंडो संदेश नहीं पा सकता, इसलिए नियंत्रण सिग्नल SetConsoleCtrlHandler से पंजीकृत हैंडलर फ़ंक्शन पर आते हैं। प्रति सिग्नल डिफ़ॉल्ट छूट इस प्रकार है।5

सिग्नल कब होता है डिफ़ॉल्ट छूट
CTRL_C_EVENT / CTRL_BREAK_EVENT Ctrl+C / Ctrl+Break कोई टाइमआउट नहीं
CTRL_CLOSE_EVENT कंसोल बंद करना, Task Manager “End task” (“Details” टैब से ज़बरदस्ती प्रक्रिया मारना बिना सूचना तुरंत निकास है, और इस तालिका से बाहर है) लगभग 5 सेकंड
CTRL_SHUTDOWN_EVENT सिस्टम शटडाउन (सेवा प्रक्रियाएँ) लगभग 20 सेकंड

देखने योग्य दो बिंदु हैं। पहला, मूलतः केवल सेवा के रूप में चल रही प्रक्रिया CTRL_LOGOFF_EVENT और CTRL_SHUTDOWN_EVENT पा सकती है। इंटरैक्टिव सत्र का ऐप साइन-आउट पर समाप्त होता है, इसलिए इन सिग्नलों की प्रतीक्षा करने वाला डिज़ाइन टिकता नहीं।5 दूसरा, जिस प्रक्रिया ने gdi32.dll या user32.dll लोड किया हो उसे कंसोल ऐप समझने पर भी Windows ऐप माना जाता है, और LOGOFF/SHUTDOWN हैंडलर नहीं बुलाए जाते। आधिकारिक समाधान छिपी विंडो बनाना और WM_QUERYENDSESSION/WM_ENDSESSION लेना है।6

प्रति कंसोल सिग्नल छूटCtrl+C और Ctrl+Break का स्पष्ट टाइमआउट नहीं; कंसोल बंद पर लगभग 5 सेकंड और सेवा प्रक्रिया को शटडाउन सिग्नल पर लगभग 20 सेकंड; पार करने पर प्रक्रिया ज़बरदस्ती समाप्तकोई टाइमआउट नहींलगभग 5 सेकंडलगभग 20 सेकंडCTRL_C / BREAKHandlerRoutine क्लीनअपCTRL_CLOSECTRL_SHUTDOWNछूट बाद ज़बरदस्ती मार

चित्र 6: Ctrl+C और Ctrl+Break का स्पष्ट टाइमआउट नहीं; कंसोल बंद पर लगभग 5 सेकंड और सेवा प्रक्रिया को शटडाउन सिग्नल पर लगभग 20 सेकंड; पार करने पर प्रक्रिया ज़बरदस्ती समाप्त।

// Console app: clean up on Ctrl+C and console close
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetConsoleCtrlHandler(HandlerRoutine handler, bool add);

delegate bool HandlerRoutine(int ctrlType);   // 2 = CTRL_CLOSE_EVENT

static readonly HandlerRoutine s_handler = OnCtrlEvent;  // Keep a reference so GC does not collect it

static bool OnCtrlEvent(int ctrlType)
{
    // Do only cleanup that finishes within 5 seconds
    FlushAndCloseDataFile();
    return false;   // Proceed to the default handler; the process exits
}

static void Main()
{
    SetConsoleCtrlHandler(s_handler, add: true);
    // ...
}

5.2. .NET का जाल — ProcessExit पर निर्भर न करें

.NET में लंबे समय से “AppDomain.ProcessExit में बस क्लीनअप कर दें” वाला स्टॉक पैटर्न रहा है, पर .NET 10 से रनटाइम डिफ़ॉल्ट समाप्ति-सिग्नल हैंडलर नहीं देता, और CTRL_CLOSE_EVENT/CTRL_SHUTDOWN_EVENT पर न ProcessExit न AssemblyLoadContext.Unloading चलता है। OS डिफ़ॉल्ट हैंडलर प्रक्रिया को तुरंत समाप्त कर देता है।7

.NET 10 में ProcessExit कैसे बदला.NET 9 तक रनटाइम का डिफ़ॉल्ट सिग्नल हैंडलर समाप्ति सिग्नल लेता, ProcessExit उठाता, फिर निकलता। .NET 10 से रनटाइम डिफ़ॉल्ट हैंडलर नहीं देता, OS डिफ़ॉल्ट हैंडलिंग प्रक्रिया तुरंत समाप्त करती है, और हैंडलर आप स्वयं पंजीकृत करते हैंCTRL_CLOSE / SHUTDOWN.NET 9 तक: ProcessExit.NET 10 से: तुरंत निकासहैंडलर स्वयं पंजीकृत करें

चित्र 7: .NET 9 तक रनटाइम का डिफ़ॉल्ट सिग्नल हैंडलर समाप्ति सिग्नल लेता, ProcessExit उठाता, फिर निकलता। .NET 10 से रनटाइम डिफ़ॉल्ट हैंडलर नहीं देता, OS डिफ़ॉल्ट हैंडलिंग प्रक्रिया तुरंत समाप्त करती है, और हैंडलर आप स्वयं पंजीकृत करते हैं।

इसके बजाय प्रत्येक ऐप मॉडल के मानक पथ पर जाएँ।

  • GUI ऐप: पिछले अध्याय के FormClosing / SessionEnding
  • Generic Host (Worker Service सहित): IHostApplicationLifetime और BackgroundService.StopAsync। HostOptions.ShutdownTimeout से रोक छूट स्पष्ट करें
  • सादा कंसोल ऐप: SetConsoleCtrlHandler (या PosixSignalRegistration से SIGINT/SIGTERM समकक्ष सब्सक्राइब करें)
प्रत्येक ऐप मॉडल निकास सूचना कहाँ पाता हैGUI ऐप FormClosing और SessionEnding प्लस निश्चित काम के लिए WM_ENDSESSION हुक उपयोग करता है; Generic Host IHostApplicationLifetime और StopAsync; सादा कंसोल ऐप SetConsoleCtrlHandler या PosixSignalRegistration। ProcessExit पर निर्भरता बाहरी-सिग्नल पथों पर नहीं चलतीGUIGUI नहींHostकंसोलकौन सा ऐप मॉडल?FormClosing / SessionEndingHost या कंसोल?ENDSESSION हुकLifetime + StopAsyncSetConsoleCtrlHandlerShutdownTimeout सेट करेंProcessExit पर निर्भर न करें

चित्र 8: GUI ऐप FormClosing और SessionEnding प्लस निश्चित काम के लिए WM_ENDSESSION हुक उपयोग करता है; Generic Host IHostApplicationLifetime और StopAsync; सादा कंसोल ऐप SetConsoleCtrlHandler या PosixSignalRegistration। ProcessExit पर निर्भरता बाहरी-सिग्नल पथों पर नहीं चलती।

छूट पथ से भिन्न है — GUI और कंसोल बंद पर लगभग 5 सेकंड, सेवा के लिए अध्याय 6 की SCM छूट (लगभग 20 सेकंड, या PRESHUTDOWN का कॉन्फ़िगर मान), और Ctrl+C पर कोई स्पष्ट टाइमआउट नहीं। हर पथ पर, पर, छूट सीमित है और भरोसा नहीं किया जा सकता, इसलिए डिज़ाइन अक्ष यह है कि सामान्य मामला “प्रत्येक प्रसंस्करण चौकी पर पहले से सेव” है, “निकास इवेंट में कड़ी मेहनत” नहीं

6. Windows सेवा को कैसा व्यवहार करना चाहिए — SHUTDOWN और PRESHUTDOWN

6.1. शटडाउन सूचना की दो तरह

सेवा साइन-आउट से प्रभावित नहीं होती, पर शटडाउन और रीस्टार्ट पर रुकती है। सूचना Service Control Manager (SCM) से नियंत्रण कोड के रूप में आती है, और पाने के लिए स्वीकृति ध्वज घोषित करना पड़ता है।8

घोषणा आने वाली सूचना समय और छूट
SERVICE_ACCEPT_SHUTDOWN SERVICE_CONTROL_SHUTDOWN शटडाउन प्रसंस्करण के दौरान सूचित। डिफ़ॉल्ट लगभग 20 सेकंड, ऊपरी सीमा WaitToKillServiceTimeout
SERVICE_ACCEPT_PRESHUTDOWN SERVICE_CONTROL_PRESHUTDOWN SHUTDOWN से पहले सूचित। SCM सेवा रुकने या टाइमआउट तक प्रतीक्षा करता है
सेवा को शटडाउन सूचनाओं का क्रमशटडाउन शुरू होने पर PRESHUTDOWN घोषित सेवाएँ पहले कॉन्फ़िगर छूट के साथ सूचित होती हैं, फिर SHUTDOWN सूचना लगभग 20 सेकंड डिफ़ॉल्ट के साथ भेजी जाती है, और छूट खत्म होने पर प्रक्रिया समाप्तशटडाउन शुरूPRESHUTDOWN(यदि घोषित)SHUTDOWN(लगभग 20 सेकंड)छूट खत्म → निकास

चित्र 9: शटडाउन शुरू होने पर PRESHUTDOWN घोषित सेवाएँ पहले कॉन्फ़िगर छूट के साथ सूचित होती हैं, फिर SHUTDOWN सूचना लगभग 20 सेकंड डिफ़ॉल्ट के साथ भेजी जाती है, और छूट खत्म होने पर प्रक्रिया समाप्त।

PRESHUTDOWN टाइमआउट ChangeServiceConfig2 (SERVICE_CONFIG_PRESHUTDOWN_INFO) से कॉन्फ़िगर हो सकता है; डिफ़ॉल्ट Windows 10 Creators Update (build 15063) से 10 सेकंड, उससे पहले 3 मिनट है।9 यदि अभी भी पुराने ज्ञान से काम कर रहे हैं कि “PRESHUTDOWN 3 मिनट देता है”, वर्तमान OS पर अपेक्षित छूट का केवल 1/18 है। साथ ही, PRESHUTDOWN उस अंतराल पूरे सिस्टम का शटडाउन रोकता है, इसलिए दस्तावेज़ भी कहता है कि इसे “केवल विशेष परिस्थितियों में उपयोग करना चाहिए”।8

हैंडलर-पक्ष अभ्यास भी मायने रखता है। नियंत्रण हैंडलर को 30 सेकंड में लौटना चाहिए; समय लेने वाला रोक-काम दूसरे थ्रेड पर छोड़ें, SERVICE_STOP_PENDING रिपोर्ट करें, और तुरंत लौटें।8

// Win32 service: accept PRESHUTDOWN and leave stop work to a worker
g_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PRESHUTDOWN;

DWORD WINAPI ServiceHandlerEx(DWORD control, DWORD, LPVOID, LPVOID)
{
    switch (control)
    {
    case SERVICE_CONTROL_PRESHUTDOWN:
    case SERVICE_CONTROL_STOP:
        ReportStatus(SERVICE_STOP_PENDING, /*waitHintMs*/ 3000);
        SetEvent(g_stopEvent);   // Tell the worker to stop and return immediately
        return NO_ERROR;
    }
    return ERROR_CALL_NOT_IMPLEMENTED;
}

// Worker side: if cleanup runs longer than waitHint, keep reporting
// SERVICE_STOP_PENDING periodically while incrementing dwCheckPoint.
// The SCM judges "still alive and making progress" from waitHint and
// checkpoint advance. If reporting stops it can be treated as hung and
// shutdown can proceed. Always report SERVICE_STOPPED when finished

6.2. छूट पर निर्भर न करने वाला डिज़ाइन

छूट की छत WaitToKillServiceTimeout को सेवा पक्ष से लिखकर बढ़ाना स्पष्ट रूप से अनुशंसित नहीं। दस्तावेज़ उलटा माँगता है — सेवा को क्लीनअप जितना जल्दी हो खत्म करना चाहिए ताकि UPS-संचालित मशीन बैटरी खत्म होने से पहले शटडाउन पूरा कर सके। मार्गदर्शन सामान्य काम में बार-बार सेव करना है ताकि न-सेव डेटा न्यूनतम रहे, शटडाउन पर मेमोरी मुक्त करने में समय न गँवाना, और नेटवर्क साथी को सूचित करते बहुत लंबी प्रतीक्षा न करना। साथ ही, SCM शटडाउन पर डिफ़ॉल्ट से निर्भरता नहीं देखता, इसलिए रोक प्रसंस्करण “भले जिस सेवा पर निर्भर हों वह पहले गिर चुकी हो” तब भी काम करना चाहिए।8

छूट पर निर्भर न करने वाला रोक प्रसंस्करण डिज़ाइनयदि प्रत्येक प्रसंस्करण चौकी पर सेव करें ताकि न-सेव डेटा हमेशा न्यूनतम रहे, रोक सूचना आने पर क्लीनअप कुछ सेकंड में खत्म होता है। निकास पर सब सेव करने वाला डिज़ाइन छूट में नहीं समाएगा, और ज़बरदस्ती समाप्ति डेटा खो देती हैप्रत्येक चौकी पर सेवरोक → छोटा सेव → पूरानिकास पर सब सेवरोक → सेव छूट चूकताज़बरदस्ती मार → डेटा हानि

चित्र 10: यदि प्रत्येक प्रसंस्करण चौकी पर सेव करें ताकि न-सेव डेटा हमेशा न्यूनतम रहे, रोक सूचना आने पर क्लीनअप कुछ सेकंड में खत्म होता है। निकास पर सब सेव करने वाला डिज़ाइन छूट में नहीं समाएगा, और ज़बरदस्ती समाप्ति डेटा खो देती है।

.NET Worker Service (UseWindowsService) में SERVICE_CONTROL_STOP और SHUTDOWN होस्ट रोक में अनुवाद होते हैं, और BackgroundService.StopAsync बुलाया जाता है। इस लेखन के समय स्टॉक कार्यान्वयन STOP/SHUTDOWN परिवार स्वीकार करता है; PRESHUTDOWN भी चाहिए तो विस्तारित हैंडलर चाहिए। दोनों तरह HostOptions.ShutdownTimeout स्पष्ट करें और StopAsync कुछ सेकंड में खत्म करें। सेवा बनाने के सामान्य विषय के लिए “Windows सेवाएँ कैसे बनाएँ और चलाएँ” देखें।

7. रीस्टार्ट के बाद स्वचालित पुनर्प्राप्ति

डिवाइस PC या बिना-उपस्थिति PC पर डिज़ाइन दायरा केवल “शटडाउन से बचना” नहीं, “रीस्टार्ट के बाद स्वयं लौटना” भी है।

7.1. RegisterApplicationRestart और पुनर्प्राप्ति कॉलबैक

यदि RegisterApplicationRestart कॉल किया हो, ऐप क्रैश (अनहैंडल्ड अपवाद), अनुत्तरदायी, अपडेट-चालित ऐप रीस्टार्ट, और अपडेट-चालित OS रीस्टार्ट के लिए रीस्टार्ट उम्मीदवार पंजीकृत होता है। रीस्टार्ट के लिए कमांड-लाइन तर्क पंजीकृत कर सकते हैं, इसलिए यदि “कौन सी फ़ाइल खुली थी” और “कौन सा पुनर्स्थापना बिंदु” शामिल करें, रीस्टार्ट के बाद जहाँ छोड़ा था वहाँ से जारी रख सकते हैं।10

अपनाए जाने वाले विनिर्देश इस प्रकार हैं।10

  • पंजीकरण समस्या आने से पहले खत्म होना चाहिए (अपडेट परिदृश्य में WM_QUERYENDSESSION हैंडलिंग अंतिम मौका है)
  • रीस्टार्ट लूप रोकने के लिए 60 सेकंड से कम चली प्रक्रिया रीस्टार्ट नहीं होती
  • उन्नत चल रही प्रक्रिया स्वचालित रीस्टार्ट की उम्मीदवार नहीं (उन्नयन सहमति बिना प्रक्रिया दोबारा नहीं बन सकती)। उन्नयन चाहिए ऐप की स्वचालित पुनर्प्राप्ति UI को मानक विशेषाधिकार पर रखकर और विशेषाधिकार काम सेवा में अलग कर, या Task Scheduler कार्य “उच्चतम विशेषाधिकार से चलाएँ” जैसे स्पष्ट लॉन्च पथ से डिज़ाइन होती है
  • क्रैश या हैंग के बाद रीस्टार्ट उपयोगकर्ता सहमति से जाता है; अपडेट के बाद रीस्टार्ट स्वचालित है
  • OS रीस्टार्ट पार कर पुनर्प्राप्त करने के लिए, रीस्टार्ट माँगने वाले पक्ष (इंस्टॉलर आदि) को EWX_RESTARTAPPS / SHUTDOWN_RESTARTAPPS ध्वज के साथ शटडाउन API कॉल करना चाहिए

यदि RegisterApplicationRecoveryCallback भी पंजीकृत करें, क्रैश पर WER (Windows Error Reporting) कॉलबैक बुलाता है और प्रगति पर डेटा सेव करने की छूट देता है। यदि सेव समय ले, पंजीकरण पर निर्दिष्ट पिंग अंतराल में ApplicationRecoveryInProgress बार-बार कॉल करना चाहिए वरना पुनर्प्राप्ति काम बीच में कट जाता है। सेव खत्म होने पर ApplicationRecoveryFinished से पूर्णता सूचित करें। ऐप-अपडेट समय “उपयोग में फ़ाइल बदलना और रीस्टार्ट” Restart Manager का क्षेत्र है, विस्तार से “उपयोग में exe या DLL कैसे बदलें” में।

7.2. ARSO — अपडेट रीस्टार्ट के बाद स्वचालित साइन-इन

Windows Update रीस्टार्ट के बाद, यदि कोई साइन-इन न करे, उपयोगकर्ता-सत्र ऐप नहीं लौटते। वह अंतर ARSO (Winlogon Automatic Restart Sign-On) भरता है। जब Windows Update रीस्टार्ट शुरू करता है, वह अंतिम इंटरैक्टिव उपयोगकर्ता की प्रमाण-पत्र सुरक्षित सहेजता है, Autologon कॉन्फ़िगर करता है, और रीस्टार्ट के बाद उस उपयोगकर्ता को स्वचालित साइन-इन कर फिर स्क्रीन लॉक करता है11 shutdown /g जैसा आदेश भी है जो रीस्टार्ट प्लस पंजीकृत ऐप फिर से शुरू माँगता है। कुछ वातावरण इसे संगठनात्मक नीति (DisableAutomaticRestartSignOn आदि) से बंद करते हैं, इसलिए बिना-उपस्थिति पुनर्प्राप्ति डिज़ाइन करते समय इस सेटिंग को सेट की तरह जाँचें। और यदि हमेशा चाहिए पृष्ठभूमि काम के लिए उपयोगकर्ता सत्र में स्वचालित लॉन्च पर निर्भर हैं, सही कदम शुरू से Windows सेवा बनाना है।

रीस्टार्ट के बाद ऐप स्वचालित कैसे लौटता हैसमस्या से पहले RegisterApplicationRestart पंजीकृत करें तो क्रैश या अनुत्तरदायी पर उपयोगकर्ता सहमति के बाद ऐप रीस्टार्ट होता है, और अपडेट-चालित रीस्टार्ट पर ARSO स्वचालित साइन-इन और स्क्रीन लॉक के बाद। 60 सेकंड से कम रनटाइम और उन्नत प्रक्रियाएँ दायरे से बाहरसहमतिRegisterApplicationRestartक्रैश या हैंगअपडेट रीस्टार्टऐप रीस्टार्टARSO साइन-इन + लॉकनहीं: 60 सेकंड से कम / उन्नत

चित्र 11: समस्या से पहले RegisterApplicationRestart पंजीकृत करें तो क्रैश या अनुत्तरदायी पर उपयोगकर्ता सहमति के बाद ऐप रीस्टार्ट होता है, और अपडेट-चालित रीस्टार्ट पर ARSO स्वचालित साइन-इन और स्क्रीन लॉक के बाद। 60 सेकंड से कम रनटाइम और उन्नत प्रक्रियाएँ दायरे से बाहर।

8. बिना सूचना बिजली कटौती से बचना — लेखन डिज़ाइन और UPS

8.1. ऐसा लेखन जो “जब भी कटे न टूटे” — अस्थायी फ़ाइल + ReplaceFile

ट्रिप हुआ ब्रेकर, फेल PSU, या खींचा प्लग न WM_ENDSESSION लाता है न PRESHUTDOWN। जब तक सेटिंग या माप परिणाम के लिए “मूल फ़ाइल को उसी जगह अधिलेखित” करते हैं, लिखते-लिखते बिजली कटने पर पुरानी-नई मिली टूटी फ़ाइल रह सकती है

मानक पैटर्न उसी वॉल्यूम पर अस्थायी फ़ाइल में पूरा लिखकर फिर अदला-बदली है। ReplaceFile “नई फ़ाइल में सेव → मूल अलग → नाम बदल → हटाएँ” क्रम को एक API में पैक करता है, और मूल फ़ाइल के निर्माण समय, ACL, और वैकल्पिक स्ट्रीम जैसे गुण भी ले जाता है (तीनों फ़ाइलें उसी वॉल्यूम पर होनी चाहिए)।12 .NET का File.Replace इसे ज्यों-का-त्यों कॉल करता है।

अस्थायी फ़ाइल और ReplaceFile से सेव और पुनर्प्राप्ति प्रवाहसेव पर अस्थायी फ़ाइल में पूरा लिखें, फ्लश करें, और ReplaceFile से अदला-बदली करें, पुरानी सामग्री .bak में छोड़ें। अगले लॉन्च पर प्राथमिक फ़ाइल जाँचें और टूटी हो तो .bak पर जाएँअगले लॉन्च परसेव परअक्षतटूटीकिसी भी चरण बिजली कटप्राथमिक जाँचेंज्यों का त्यों उपयोग.bak पर जाएँडिस्क पर फ्लशपूरी अस्थायी फ़ाइल लिखेंReplaceFile → .bak

चित्र 12: सेव पर अस्थायी फ़ाइल में पूरा लिखें, फ्लश करें, और ReplaceFile से अदला-बदली करें, पुरानी सामग्री .bak में छोड़ें। अगले लॉन्च पर प्राथमिक फ़ाइल जाँचें और टूटी हो तो .bak पर जाएँ।

// The standard pattern for settings and data: write completely to a temporary file, then swap, and keep the old contents
public static void SaveAtomically(string path, string content)
{
    string dir = Path.GetDirectoryName(path)!;
    string tmp = Path.Combine(dir, Path.GetRandomFileName());  // Create it on the same volume

    try
    {
        using (var fs = new FileStream(tmp, FileMode.CreateNew, FileAccess.Write))
        using (var writer = new StreamWriter(fs))
        {
            writer.Write(content);
            writer.Flush();
            fs.Flush(flushToDisk: true);   // FlushFileBuffers equivalent. Write the OS buffer
                                           // out to disk (device-side cache limits are in 8.2)
        }

        if (File.Exists(path))
            File.Replace(tmp, path, path + ".bak");  // Calls ReplaceFile. Keep the old contents as .bak
        else
            File.Move(tmp, path);
    }
    catch
    {
        // If we fail mid-way, do not leave the temporary file. Repeated failures
        // of a periodic save would fill the volume with complete copies
        try { File.Delete(tmp); } catch { /* Prefer the original exception if delete fails */ }
        throw;
    }
}

इससे सामान्य काम हमेशा या “पूरी पुरानी फ़ाइल” या “पूरी नई फ़ाइल” पढ़ने देता है। ReplaceFile, पर, बहु-चरण नेमस्पेस क्रिया है, और बिजली कटने पर परमाण्विकता विनिर्देश से गारंटी नहीं। इसीलिए ऊपर का उदाहरण बैकअप (.bak) रखता है — पढ़ने वाला पक्ष लॉन्च पर प्राथमिक फ़ाइल जाँचता है और टूटी हो तो बैकअप पर जाता है, सेट की तरह। इसे केवल-जोड़ लॉग या CSV पर उपयोग नहीं कर सकते, इसलिए वे ऐसा प्रारूप उपयोग करते हैं जो टूटन शामिल करे, जैसे “एक पंक्ति = एक रिकॉर्ड, और पढ़ते समय टूटी अंतिम पंक्ति फेंकें”।

8.2. WriteFile की सफलता डिस्क तक पहुँचना नहीं

दूसरी धारणा यह है कि WriteFile सफलता लौटाए तब भी डेटा केवल OS कैश में हो सकता है। Windows फ़ाइल पढ़ना-लिखना सिस्टम बफर पर रखता है और आलसी लेखन से समय-समय डिस्क पर प्रतिबिंबित करता है। डेटा निश्चित डिस्क तक ले जाने के लिए या FlushFileBuffers से स्पष्ट फ्लश करें, या CreateFile पर FILE_FLAG_WRITE_THROUGH निर्दिष्ट करें ताकि प्रत्येक लेखन कैश पार करे। फ़ाइल-सिस्टम मेटाडेटा हमेशा कैश होता है, इसलिए मेटाडेटा पुष्टि को भी फ्लश या write-through चाहिए।13

हर बार FlushFileBuffers कॉल करना अक्षम है, पर, और दस्तावेज़ भी बार-बार कॉल के बजाय FILE_FLAG_NO_BUFFERING+WRITE_THROUGH विचार करने को प्रोत्साहित करता है।13 व्यवहार में “केवल लेन-देन चौकी पर या फ़ाइल बंद करने से ठीक पहले फ्लश” यथार्थ समझौता है। इस परत की यांत्रिकी — कैश मैनेजर, आलसी लेखन, और यह तथ्य कि हार्डवेयर कैश के कारण “फ्लश किया फिर भी डिस्क तक नहीं पहुँचा हो सकता” — गहराई से “Cache Manager: आपका WriteFile वास्तव में डिस्क तक कब पहुँचता है?” में है।

8.3. UPS और बैटरी निगरानी — बिजली कटौती को शटडाउन बनाना

डिवाइस PC पर बिजली कटौती का असली उपाय UPS है। UPS की भूमिका “बिजली आउटेज रोकना” नहीं, “बिना सूचना बिजली कटौती” को “सूचना वाला नियोजित शटडाउन” बनाना मानें। डिज़ाइन दो-चरण सेटअप है।

  1. छूट डिज़ाइन करना: UPS बैटरी होल्ड समय > “बैटरी स्विच पकड़ें → ऐप और सेवा क्लीनअप → OS शटडाउन पूरा” का योग। यदि सेवा रोक प्रसंस्करण धीमा हो, यह समीकरण नहीं टिकता (खंड 6.2)
  2. पता लगाना: AC से बैटरी स्विच, और शेष क्षमता गिरना, PBT_APMPOWERSTATUSCHANGE इवेंट से सूचित होते हैं। विंडो वाले ऐप इसे WM_POWERBROADCAST के रूप में पाते हैं; बिना विंडो सेवा SERVICE_ACCEPT_POWEREVENT घोषित कर HandlerEx में SERVICE_CONTROL_POWEREVENT के रूप में पाती है (WM_POWERBROADCAST सेवा नियंत्रण हैंडलर तक नहीं आता)। प्राप्ति पर GetSystemPowerStatus कॉल करें, ACLineStatus (AC पर है या नहीं) और BatteryLifePercent जाँचें, और माप रोकना, सेव, और शटडाउन अनुरोध तक ले जाएँ15
UPS से बिजली कटौती को नियोजित शटडाउन बनाने का प्रवाहआउटेज UPS को बैटरी पर स्विच करे तो PBT_APMPOWERSTATUSCHANGE सूचित होता है, पावर स्थिति जाँची जाती है, और सेव प्लस शटडाउन अनुरोध बिना सूचना बिजली कटौती को सूचना वाले नियोजित शटडाउन में बदलते हैंआउटेजUPS बैटरी परPBT_APMPOWERSTATUSCHANGEGetSystemPowerStatusरोकें और सेव करेंशटडाउन अनुरोधसामान्य सूचना प्रवाह(3 से 6)

चित्र 13: आउटेज UPS को बैटरी पर स्विच करे तो PBT_APMPOWERSTATUSCHANGE सूचित होता है, पावर स्थिति जाँची जाती है, और सेव प्लस शटडाउन अनुरोध बिना सूचना बिजली कटौती को सूचना वाले नियोजित शटडाउन में बदलते हैं।

विशिष्ट USB-जुड़ा UPS Windows को बैटरी दिखता है, इसलिए इस मानक API से पकड़ सकते हैं। यदि विक्रेता प्रबंधन सॉफ़्टवेयर में “N% शेष पर OS शटडाउन” सुविधा हो, यह भी जाँचें कि सीमा ऐप के क्लीनअप समय से मेल खाती है। स्लीप या हाइबरनेशन से रिज़्यूम, और लंबे समय चलने वाले मुद्दे, अलग अक्ष हैं, “स्लीप, हाइबरनेशन, Modern Standby, और लंबे समय चलने वाले ऐप” में।

9. कैसे सत्यापित करें — शटडाउन सुरक्षित आज़माना

शटडाउन हैंडलिंग “लिख दिया पर उत्पादन-समान स्थितियों में कभी नहीं आज़माया” बन जाती है। इसे सुरक्षित सत्यापित करने की प्रक्रिया रखें।

  • परीक्षण मशीन या VM पर आज़माएँ: पहले उत्पादन डिवाइस PC पर न आज़माएँ। Hyper-V चेकपॉइंट (स्नैपशॉट) वाले परीक्षण वातावरण में शटडाउन, रीस्टार्ट, और ज़बरदस्ती बिजली कटौती (VM बंद करना) दोहराएँ। VM “पावर ऑफ”, पर, केवल “अतिथि OS बिना सूचना रुकना” पुनरुत्पादित करता है; भौतिक डिस्क के अस्थिर कैश या नियंत्रक-निर्भर टूटन नहीं। यदि डिवाइस PC के रूप में भेजें, अंतिम जाँच उत्पादन-समान हार्डवेयर पर वास्तविक बिजली-कट परीक्षण है
  • साइन-आउट से त्वरित जाँच: WM_QUERYENDSESSION → WM_ENDSESSION पथ साइन-आउट पर भी चलता है (अंतर केवल lParam में ENDSESSION_LOGOFF बिट), इसलिए विकास मशीन पर क्लीनअप-कोड व्यवहार आसानी से पुष्टि कर सकते हैं1
  • पूर्ण शटडाउन और हाइब्रिड अलग आज़माएँ: shutdown /s /t 0 (पूर्ण), shutdown /s /hybrid /t 0 (डिफ़ॉल्ट व्यवहार), और shutdown /r /t 0 (रीस्टार्ट) प्रत्येक आज़माएँ2
  • क्लीनअप कितना समय लेता है मापें: क्लीनअप फ़ंक्शन के आरंभ और अंत पर लॉग में टाइमस्टैंप लिखें, और मापें कि 5 सेकंड (या सेवा की कॉन्फ़िगर छूट) में समाता है या नहीं
सत्यापित करने योग्य क्रियाएँ और प्रत्येक क्या पुष्टि कर सकता हैसाइन-आउट सूचना पथ की सुविधाजनक जाँच है; शटडाउन-आदेश पूर्ण, हाइब्रिड और रीस्टार्ट उत्पादन सूचना पथ और छूट पुष्टि करते हैं; VM पावर-ऑफ अचानक-रुक लचीलापन जाँचता है; भौतिक बिजली-कट अंतिम जाँच है जिसमें भौतिक संग्रहण शामिलसाइन-आउटQUERY → ENDSESSION पथshutdown /s /hybrid /rउत्पादन पथ + छूटVM पावर-ऑफअतिथि अचानक रुकभौतिक बिजली-कटसंग्रहण सहित(अंतिम)

चित्र 14: साइन-आउट सूचना पथ की सुविधाजनक जाँच है; शटडाउन-आदेश पूर्ण, हाइब्रिड और रीस्टार्ट उत्पादन सूचना पथ और छूट पुष्टि करते हैं; VM पावर-ऑफ अचानक-रुक लचीलापन जाँचता है; भौतिक बिजली-कट अंतिम जाँच है जिसमें भौतिक संग्रहण शामिल।

बाद के अलगाव के लिए इवेंट लॉग (System) उपयोगी है। सामान्य शटडाउन या रीस्टार्ट पर इवेंट ID 1074 (किस प्रक्रिया ने शटडाउन शुरू किया, किसके लिए, और किस कारण) दर्ज होता है। अचानक बिजली कटौती या क्रैश पर 1074 नहीं होता, और अगले बूट पर इवेंट ID 41 (Kernel-Power) और 6008 (पिछला सिस्टम शटडाउन अप्रत्याशित था) दर्ज होते हैं।14 “रात में क्या हुआ” यहीं से शुरू होता है।

# Check the recent history of shutdown-related events
Get-WinEvent -FilterHashtable @{ LogName = 'System'; Id = 1074, 6008, 41 } -MaxEvents 20 |
    Select-Object TimeCreated, Id, ProviderName, Message |
    Format-List

यदि 1074 “Windows Update द्वारा रीस्टार्ट” दिखाए और ऐप का डेटा टूटा हो, समस्या क्लीनअप कोड है। 6008/41 केवल “अप्रत्याशित शटडाउन” दिखाते हैं; वे ब्लू-स्क्रीन (क्रैश) या ज़बरदस्ती रीसेट पर भी दर्ज होते हैं, केवल बिजली कटौती पर नहीं। यदि 41 का BugcheckCode शून्येतर हो तो क्रैश है; यदि 0 हो और मेमोरी डंप भी न हो, बिजली कटौती संभावित है — आसपास की जानकारी से कारण अलग करें, और जब पता चले बिजली कटौती थी, अध्याय 8 का लेखन डिज़ाइन और UPS अगला कदम हैं।

10. सारांश

  • शटडाउन “सामान्य घटना है जो देर-सबेर आएगी”। सूचना के बाद छूट सिद्धांततः लगभग 5 सेकंड ही है, इसलिए पूर्वापेक्षा बार-बार ऑटोसेव है ताकि “निकास पर जो करें” न्यूनतम रहे।
  • Windows 8 से आगे के क्लाइंट OS पर, यदि fast startup चालू हो, Shut down hybrid shutdown है और कर्नेल केवल हाइबरनेट हो रहा है। पूर्ण रीसेट केवल Restart है — घटना प्रक्रिया में Restart लिखें।
  • GUI ऐप WM_QUERYENDSESSION पर तुरंत TRUE लौटाता है, और निश्चित क्लीनअप WM_ENDSESSION में करता है। WinForms/WPF FormClosing और SessionEnding क्वेरी चरण से मेल खाते हैं, इसलिए वहाँ अधिकतम idempotent स्नैपशॉट सेव करें। शटडाउन के दौरान संवाद न दिखाएँ।
  • जो काम सचमुच बीच में नहीं काटा जा सकता, ShutdownBlockReasonCreate से कारण दिखाकर सुरक्षित होता है। पर कहीं गारंटी नहीं कि ब्लॉक कर सकते हैं।
  • कंसोल ऐप सूचना SetConsoleCtrlHandler से पाता है; सेवा SERVICE_ACCEPT_PRESHUTDOWN/SHUTDOWN से। वर्तमान OS पर डिफ़ॉल्ट PRESHUTDOWN छूट 10 सेकंड है। .NET में ProcessExit पर निर्भरता छोड़कर ऐप मॉडल के मानक पथ पर जाएँ।
  • रीस्टार्ट के बाद पुनर्प्राप्ति RegisterApplicationRestart (प्लस पुनर्प्राप्ति कॉलबैक) और ARSO से बिना-उपस्थिति हो सकती है।
  • बिजली कटौती कोई सूचना नहीं लाती। अस्थायी-फ़ाइल + ReplaceFile अदला-बदली (बैकअप + लोड-समय जाँच के सेट के साथ), चौकियों पर फ्लश, और UPS जो “बिजली कटौती को नियोजित शटडाउन बनाए” से तैयारी करें।
शटडाउन हैंडलिंग की समग्र तस्वीरसूचना वाले अंत के लिए कुछ सेकंड में दुकान बंद कर सकने वाला क्लीनअप और रीस्टार्ट के बाद स्वचालित पुनर्प्राप्ति; बिना सूचना बिजली कटौती के लिए जब भी कटे न टूटने वाला लेखन और UPS, भौतिक हार्डवेयर सहित सत्यापन। ये दो स्तंभ लेख का निष्कर्ष हैंसूचना के साथसूचना नहींकैसे खत्म होता हैकुछ-सेकंड क्लीनअप(3 से 6)सुरक्षित लेखन + UPS(8)रीस्टार्ट बाद स्वतः पुनर्प्राप्ति(7)हार्डवेयर पर सत्यापित(9)

चित्र 15: सूचना वाले अंत के लिए कुछ सेकंड में दुकान बंद कर सकने वाला क्लीनअप और रीस्टार्ट के बाद स्वचालित पुनर्प्राप्ति; बिना सूचना बिजली कटौती के लिए जब भी कटे न टूटने वाला लेखन और UPS, भौतिक हार्डवेयर सहित सत्यापन। ये दो स्तंभ लेख का निष्कर्ष हैं।

  • VM और साइन-आउट से सुरक्षित सत्यापित करें, और बाद में इवेंट ID 1074/41/6008 से अलग करें।

अगली बार ऐप में सुविधा जोड़ते स्वयं से एक बार पूछें: यदि इस काम के बीच WM_ENDSESSION आए, या बिजली खींच ली जाए, अगले लॉन्च पर क्या बचा है? उस उत्तर को डिज़ाइन में लिखना डिवाइस PC के सामने सुबह सिर पकड़कर खड़े न होने का सबसे छोटा पथ है।

संबंधित लेख

संबंधित परामर्श क्षेत्र

KomuraSoft LLC डिवाइस-PC और लंबे समय चलने वाले ऐप के लिए शटडाउन और बिजली-कटौती उपायों का डिज़ाइन व कार्यान्वयन, Windows Update रीस्टार्ट या साइन-आउट से शुरू डेटा भ्रष्टाचार और “सुबह तक रुक चुका था” घटनाओं की मूल-कारण जाँच, और Windows सेवा रोक प्रसंस्करण व स्वचालित पुनर्प्राप्ति की डिज़ाइन समीक्षा सँभालता है। “हर शटडाउन पर कुछ टूटता लगता है, और पता नहीं कहाँ से शुरू करें” चरण से शुरू करना ठीक है।

संदर्भ लिंक

  1. Microsoft Learn, WM_QUERYENDSESSION message. यह कि WM_QUERYENDSESSION सत्र समाप्ति पर भेजा जाता है और ऐप को TRUE लौटाकर उपयोगकर्ता के इरादे का सम्मान करना चाहिए (DefWindowProc का डिफ़ॉल्ट भी TRUE है); कि क्लीनअप WM_ENDSESSION तक टालना चाहिए; कि 5 सेकंड बाद सिस्टम शटडाउन रोकने वाले ऐप के लिए UI दिखाता है और उपयोगकर्ता ज़बरदस्ती समाप्त कर सकता है; lParam में ENDSESSION_LOGOFF/CLOSEAPP/CRITICAL बिट का अर्थ; कि शटडाउन और रीस्टार्ट अलग नहीं बताए जा सकते; और कि डेटा बार-बार सेव करना चाहिए ताकि निकास पर कम सेव करना पड़े।  2 3 4 5 6 7

  2. Microsoft Learn, Fast startup causes hibernation or shutdown to fail in Windows 10 or Windows 8.1. यह कि fast startup पर कर्नेल सत्र बंद नहीं होता और हाइबरनेशन माना जाता है, और कर्नेल व डिवाइस-ड्राइवर अवस्था hiberfil.sys में सहेजी जाती है; कि “Restart” हमेशा पूर्ण बूट करता है क्योंकि पूरी तरह नई Windows अवस्था चाहिए; कि fast startup डिफ़ॉल्ट चालू है और बंद करना अनुशंसित नहीं; और कि Shutdown.exe का डिफ़ॉल्ट पूर्ण शटडाउन है, /hybrid विकल्प हाइब्रिड व्यवहार देता है।  2 3 4 5

  3. Microsoft Learn, ShutdownBlockReasonCreate function (winuser.h). यह कि अबाधनीय काम शुरू होने पर कारण स्ट्रिंग पंजीकृत करने के लिए कॉल करें और खत्म होने पर ShutdownBlockReasonDestroy कॉल करें; कि इसे केवल उस थ्रेड से कॉल कर सकते हैं जिसने विंडो बनाई; और कि उपयोगकर्ता कारण कुछ सेकंड ही पढ़ेगा, इसलिए स्ट्रिंग छोटी और स्पष्ट हो।  2 3

  4. Microsoft Learn, Shutdown Changes for Windows Vista. यह कि WM_QUERYENDSESSION/WM_ENDSESSION का उत्तर प्रत्येक पर 5 सेकंड विलंबित हो सकता है और तब उपयोगकर्ता जारी या रद्द चुन सकता है; कि कंसोल ऐप या बिना दिखाई विंडो वाला ऐप शटडाउन निरस्त नहीं कर सकता और 5 सेकंड बिना उत्तर या FALSE उत्तर पर स्वचालित समाप्त होता है; कि ब्लॉक चाहिए तो ShutdownBlockReasonCreate से कारण पंजीकृत करना चाहिए; और कि ऐप को शटडाउन ब्लॉक कर सकने पर निर्भर नहीं रहना चाहिए।  2 3 4

  5. Microsoft Learn, HandlerRoutine callback function. SetConsoleCtrlHandler से पंजीकृत हैंडलर द्वारा प्राप्त CTRL_C/BREAK/CLOSE/LOGOFF/SHUTDOWN इवेंट; कि CTRL_CLOSE_EVENT का डिफ़ॉल्ट टाइमआउट लगभग 5000 मिलीसेकंड और सेवा प्रक्रिया पर CTRL_SHUTDOWN_EVENT लगभग 20000 मिलीसेकंड है; कि CTRL_LOGOFF/SHUTDOWN_EVENT मूलतः केवल सेवाएँ पाती हैं क्योंकि इंटरैक्टिव ऐप लॉगऑफ पर समाप्त होता है; और कि हैंडलर अलग थ्रेड पर चलता है।  2 3

  6. Microsoft Learn, SetConsoleCtrlHandler function. यह कि gdi32.dll या user32.dll लोड करने वाली प्रक्रिया Windows ऐप मानी जाती है और CTRL_LOGOFF_EVENT/CTRL_SHUTDOWN_EVENT हैंडलर नहीं बुलाए जाते; कि समाधान छिपी विंडो बनाकर WM_QUERYENDSESSION/WM_ENDSESSION सँभालना है; और कि सिग्नल हैंडलिंग के दौरान कंसोल फ़ंक्शन सही काम न करें।  2

  7. Microsoft Learn, .NET runtime no longer provides default termination signal handlers. यह कि .NET 10 से रनटाइम Windows CTRL_SHUTDOWN_EVENT/CTRL_CLOSE_EVENT (Unix SIGTERM/SIGHUP समकक्ष) का डिफ़ॉल्ट हैंडलर नहीं देता; कि OS डिफ़ॉल्ट हैंडलिंग ऐप तुरंत समाप्त करती है और AppDomain.ProcessExit व AssemblyLoadContext.Unloading नहीं चलते; और कि ऐप मॉडल के अनुकूल सिग्नल हैंडलिंग उच्च-स्तरीय लाइब्रेरी या ऐप कोड में पंजीकृत करनी चाहिए।  2

  8. Microsoft Learn, Service Control Handler Function. यह कि SERVICE_ACCEPT_PRESHUTDOWN घोषित सेवा पहले SERVICE_CONTROL_PRESHUTDOWN पाती है, फिर SERVICE_ACCEPT_SHUTDOWN सेवा SERVICE_CONTROL_SHUTDOWN; कि शटडाउन पर डिफ़ॉल्ट छूट लगभग 20 सेकंड और OS रीस्टार्ट पर छत WaitToKillServiceTimeout है; कि यह मान नहीं बढ़ाना चाहिए; कि नियंत्रण हैंडलर 30 सेकंड में लौटे, STOP_PENDING और wait hint रिपोर्ट करे, और लंबा काम दूसरे थ्रेड पर छोड़े; कि UPS संचालन ध्यान में रखकर क्लीनअप जितना जल्दी हो खत्म हो; और कि SCM शटडाउन पर डिफ़ॉल्ट से निर्भरता नहीं देखता।  2 3 4 5

  9. Microsoft Learn, SERVICE_PRESHUTDOWN_INFO structure (winsvc.h). यह कि PRESHUTDOWN सूचना के बाद SCM सेवा रुकने या टाइमआउट तक प्रतीक्षा करता है; कि डिफ़ॉल्ट टाइमआउट Windows 10 Creators Update (build 15063) से 10 सेकंड और उससे पहले 3 मिनट है; कि ChangeServiceConfig2 से कॉन्फ़िगर होता है; और कि SERVICE_STOP_PENDING के दौरान स्थिति अपडेट जारी रह सकती है।  2

  10. Microsoft Learn, RegisterApplicationRestart function (winbase.h). यह कि क्रैश, अनुत्तरदायी, अपडेट, और अपडेट के साथ कंप्यूटर रीस्टार्ट के लिए रीस्टार्ट पंजीकृत हो सकता है; कि रीस्टार्ट के कमांड-लाइन तर्क निर्दिष्ट हो सकते हैं; कि पंजीकरण समस्या से पहले होना चाहिए और अपडेट परिदृश्य में WM_QUERYENDSESSION हैंडलिंग अंतिम मौका है; कि 60 सेकंड से कम रनटाइम प्रक्रिया रीस्टार्ट नहीं होती; कि क्रैश या हैंग के बाद रीस्टार्ट उपयोगकर्ता सहमति से जाता है; और कि OS रीस्टार्ट पार करने के लिए EWX_RESTARTAPPS/SHUTDOWN_RESTARTAPPS वाला शटडाउन चाहिए।  2 3

  11. Microsoft Learn, Winlogon automatic restart sign-on (ARSO). यह कि Windows Update स्वचालित रीस्टार्ट शुरू करे तो अंतिम इंटरैक्टिव उपयोगकर्ता की प्रमाण-पत्र सहेजता है और Autologon कॉन्फ़िगर करता है; कि रीस्टार्ट के बाद उपयोगकर्ता को स्वचालित साइन-इन कर सत्र लॉक करता है; कि सफल साइन-इन के बाद सहेजे प्रमाण-पत्र हटते हैं; और कि Group Policy (DisableAutomaticRestartSignOn आदि) से कॉन्फ़िगर हो सकता है।  2

  12. Microsoft Learn, ReplaceFileW function (winbase.h). यह कि ReplaceFile “नई फ़ाइल में सेव, मूल का अस्थायी नाम, नई फ़ाइल का नाम, मूल हटाना” के समकक्ष बहु चरण एक फ़ंक्शन में पैक करता है; कि मूल फ़ाइल के निर्माण समय, DACL, एन्क्रिप्शन, संपीड़न और named streams जैसे गुण सुरक्षित रखता है; और कि बैकअप, बदली जा रही फ़ाइल, और प्रतिस्थापन फ़ाइल उसी वॉल्यूम पर होनी चाहिए।  2

  13. Microsoft Learn, File Caching. यह कि लेखन डिफ़ॉल्ट से सिस्टम कैश पर जाते हैं और आलसी लेखन से डिस्क पर प्रतिबिंबित होते हैं; कि FILE_FLAG_WRITE_THROUGH तुरंत डिस्क पर लिखता है; कि FlushFileBuffers स्पष्ट फ्लश कर सकता है; और कि फ़ाइल-सिस्टम मेटाडेटा हमेशा कैश होता है, इसलिए मेटाडेटा पुष्टि को फ्लश या write-through चाहिए।  2 3

  14. Microsoft Learn, Troubleshoot unexpected reboots using system event logs. यह कि सामान्य रीस्टार्ट इवेंट ID 1074 दर्ज करता है (किस प्रक्रिया ने शटडाउन शुरू किया, किसके लिए, किस कारण); कि अप्रत्याशित रीस्टार्ट इवेंट ID 41 (Kernel-Power) और 6008 दर्ज करता है; और कि ये ID रीस्टार्ट का प्रकार अलग कर सकते हैं।  2

  15. Microsoft Learn, PBT_APMPOWERSTATUSCHANGE event. यह कि यह इवेंट बैटरी और AC के बीच स्विच या शेष क्षमता गिरने पर WM_POWERBROADCAST से सूचित होता है; और कि प्राप्ति पर GetSystemPowerStatus कॉल कर ACLineStatus, BatteryFlag, और BatteryLifePercent जैसे SYSTEM_POWER_STATUS फ़ील्ड जाँचने चाहिए। 

निकटवर्ती विषयों में गहराई से जाने के लिए समान टैग वाले नवीनतम लेख।

Named Pipes व्यवहार में — डिज़ाइन से सुरक्षा तक, Windows की मानक IPC

Named pipes — Windows की मानक इंटर-प्रोसेस कम्युनिकेशन — की व्यावहारिक मार्गदर्शिका। यह लेख प्राथमिक स्रोतों से बाइट और मैसेज मोड का चुना...

स्लीप से रिज़्यूम पर टूटने वाले ऐप — Windows पावर इवेंट कैसे काम करते हैं और उनसे बचने वाले व्यावसायिक ऐप कैसे बनाएँ

लैपटॉप खोला और व्यावसायिक ऐप के कनेक्शन मर चुके थे — कारण वह डिज़ाइन है जिसने स्लीप का हिसाब ही नहीं रखा। यह लेख WM_POWERBROADCAST सूचना ...

DllMain और Loader Lock — DLL आरंभीकरण में "कुछ न करें" कहे जाने का वास्तविक कारण

DllMain से LoadLibrary क्यों न बुलाएँ या दूसरे थ्रेड से सिंक्रोनाइज़ न करें। प्राथमिक स्रोतों से यह लेख समझाता है कि लोडर लॉक हर DLL सूचन...

"Not Responding" वास्तव में क्या है — Windows ऐप के हैंग का निर्णय कैसे करता है, और न हैंग करने वाले ऐप कैसे डिज़ाइन करें

Windows का "Not Responding" वह तंत्र है जिसमें OS तय करता है कि विंडो ने 5 सेकंड संदेश नहीं लिया और उसे घोस्ट विंडो से बदल देता है। यह ले...

ये पृष्ठ विषय को सेवाओं और निर्णयों के व्यापक संदर्भ में रखते हैं।

यह लेख निम्नलिखित सेवाओं से सीधे जुड़ा है।

अक्सर पूछे जाने वाले प्रश्न

इस लेख के विषय पर परामर्श में अक्सर पूछे जाने वाले प्रश्न।

जो समस्या "Shut down" के बाद नहीं गई, "Restart" के बाद चली गई। क्यों?
Windows 8 से आगे के क्लाइंट OS पर, जब fast startup चालू हो (हाइबरनेशन समर्थित अधिकांश PC पर डिफ़ॉल्ट), "Shut down" hybrid shutdown नामक तंत्र इस्तेमाल करता है। उपयोगकर्ता साइन-आउट होता है, पर कर्नेल और ड्राइवर अवस्था हाइबरनेशन फ़ाइल में सहेजी जाती है और अगले बूट पर ज्यों-की-त्यों लौटती है। यानी OS का कोर रीसेट नहीं हुआ। इसके विपरीत "Restart" हमेशा पूर्ण बूट करता है, इसलिए ड्राइवर और सेवा की समस्या रीसेट होती है। अलगाव प्रक्रिया में "Restart" लिखें, "Shut down करके फिर चालू करें" नहीं। कमांड लाइन से पूर्ण शटडाउन चाहिए तो shutdown /s उपयोग कर सकते हैं।
क्या ऐप सेव खत्म करे तब तक शटडाउन रोक सकता हूँ?
अस्थायी प्रतीक्षा माँग सकते हैं, पर भरोसे से रोक नहीं सकते। यदि केवल उस समय ShutdownBlockReasonCreate से कारण स्ट्रिंग पंजीकृत करें जब अबाधनीय काम चल रहा हो, वह कारण "यह ऐप शटडाउन रोक रहा है" स्क्रीन पर दिखता है और उपयोगकर्ता जारी रखने या रद्द करने का निर्णय ले सकता है। फिर भी उपयोगकर्ता ज़बरदस्ती जारी रख सकता है, और ज़बरदस्ती शटडाउन या अपडेट-चालित रीस्टार्ट बिल्कुल प्रतीक्षा न करे। सही रास्ता इसलिए "ब्लॉक" नहीं, बल्कि बार-बार ऑटोसेव ताकि जोखिम में कम डेटा रहे, साथ निकास सूचना से कुछ सेकंड में खत्म होने वाला क्लीनअप है।
मेरी Windows सेवा रोकने में लंबा समय लगता है। क्या शटडाउन छूट बढ़ा सकता हूँ?
SERVICE_CONTROL_SHUTDOWN पाने वाली डिफ़ॉल्ट सेटिंग में छूट लगभग 20 सेकंड है और WaitToKillServiceTimeout रजिस्ट्री मान पर निर्भर करती है। उसे ऐप पक्ष से बढ़ाकर लिखना अनुशंसित नहीं। लंबी छूट चाहिए तो SERVICE_ACCEPT_PRESHUTDOWN घोषित कर SERVICE_CONTROL_PRESHUTDOWN पा सकते हैं; आप दूसरों से पहले सूचित होते हैं, और टाइमआउट ChangeServiceConfig2 से सेट हो सकता है (डिफ़ॉल्ट Windows 10 Creators Update से 10 सेकंड, उससे पहले 3 मिनट)। पर PRESHUTDOWN उस अंतराल पूरे शटडाउन को रोकता है, इसलिए केवल सचमुच ज़रूरी मामलों तक सीमित रखें, और मूल रूप से रोक-काम को कुछ सेकंड में खत्म डिज़ाइन करें।
.NET के AppDomain.ProcessExit में शटडाउन क्लीनअप सुरक्षित है?
इस पर निर्भर न करने की सलाह है। ऐतिहासिक रूप से रनटाइम डिफ़ॉल्ट सिग्नल हैंडलर पंजीकृत करता था, और CTRL_CLOSE_EVENT व CTRL_SHUTDOWN_EVENT पर ProcessExit चलता था, पर .NET 10 से रनटाइम डिफ़ॉल्ट समाप्ति-सिग्नल हैंडलर नहीं देता, और उन मामलों में ProcessExit नहीं चलता। क्लीनअप उस सूचना पथ पर लागू करें जो ऐप मॉडल से मेल खाए: GUI ऐप FormClosing या SessionEnding उपयोग करें (वे क्वेरी-चरण सूचना हैं, इसलिए उन्हें idempotent सेव तक सीमित रखें; जो क्लीनअप केवल सत्र निश्चित होने के बाद चल सकता है वह WM_ENDSESSION हुक में हो); Generic Host / Worker Service IHostApplicationLifetime और StopAsync उपयोग करें; कंसोल ऐप SetConsoleCtrlHandler या PosixSignalRegistration उपयोग करें।
अचानक बिजली कटने से फ़ाइलें खराब होने से कैसे बचाऊँ?
बिजली कटौती कोई सूचना नहीं लाती, इसलिए एकमात्र विकल्प ऐसे लिखना है जो बिजली जब भी कटे टूटे नहीं। आधार यह है कि मूल फ़ाइल को उसी जगह अधिलेखित न करें: उसी वॉल्यूम पर अस्थायी फ़ाइल में पूरा लिखें, फ्लश करें, और ReplaceFile (.NET में File.Replace) से अदला-बदली करें। सामान्य काम में इससे या पूरी पुरानी फ़ाइल या पूरी नई फ़ाइल पढ़ सकते हैं, पर बिजली कटने पर ReplaceFile की परमाण्विकता विनिर्देश से गारंटी नहीं, इसलिए बैकअप (तीसरा तर्क) रखें और लोड-समय पुनर्प्राप्ति लागू करें जो प्राथमिक फ़ाइल जाँचे और टूटी हो तो बैकअप पर जाए। साथ ही, WriteFile की सफलता का अर्थ डेटा डिस्क तक पहुँचना नहीं, इसलिए महत्वपूर्ण चौकियों पर FlushFileBuffers या FILE_FLAG_WRITE_THROUGH से लेखन पुष्टि करें। डिवाइस PC पर मानक सेटअप इसे UPS से जोड़ना, बैटरी स्विच पकड़ना, और सुरक्षित शटडाउन तक ले जाना है।

लेखक की प्रोफ़ाइल

लेख के लेखक का परिचय पृष्ठ।

Go Komura

KomuraSoft LLC के प्रतिनिधि

Windows सॉफ़्टवेयर विकास, तकनीकी परामर्श और बग जाँच में विशेषज्ञ, विशेष रूप से मौजूदा सिस्टम वाली परियोजनाओं और पुनरुत्पादन में कठिन बग में।

सार्वजनिक लिंक

ब्लॉग पर लौटें