ऐप की नज़र से Windows shutdown — exit notification, restart और power loss से सही तरीके से बचें
· अद्यतन तिथि: · Go Komura · Windows, shutdown, Windows development, Windows services, device PC, data integrity, long-running work, UPS
संशोधन इतिहास (पहला संस्करण, 21 Aug 2026 को प्रकाशित)
- पहला प्रकाशन
इस लेख का हवाला दें(DOI: 10.5281/zenodo.22176533)
यह लेख Zenodo पर संग्रहीत है। नीचे वह DOI है जो हमेशा नवीनतम संस्करण की ओर ले जाता है, और वह DOI भी जो आपके पढ़े जा रहे संस्करण से बँधा है।
Go Komura (2026). ऐप की नज़र से Windows shutdown — exit notification, restart और power loss से सही तरीके से बचें. KomuraSoft LLC. https://doi.org/10.5281/zenodo.22176533 https://comcomponent.com/hi/blog/windows-shutdown-handling-for-apps/
- DOI (नवीनतम संस्करण)
- 10.5281/zenodo.22176533
- DOI (यह संस्करण)
- 10.5281/zenodo.22176534
“Windows Update की रात वाली restart के बाद device PC पर माप ऐप लिखते-लिखते गिर गया, और सुबह माप फ़ाइल खराब थी।” “किसी ने साझा PC से sign-out किया और शिकायत की कि न-save संपादन गायब हो गए।” — लंबे समय चलने वाले Windows ऐप के लिए ये दो consulting क्लासिक हैं।
दोनों साइटों में समान बात shutdown को “ऐसी असामान्य घटना जो नहीं होनी चाहिए” मानना है। वास्तविकता में, Windows Update automatic restart, user sign-out, और UPS-प्रेरित shutdown से लेकर बिना घोषणा power loss तक, ऐप के बाहर से execution काटने वाली घटनाएँ आएँगी, देर-सबेर। उन्हें आने से रोक नहीं सकते। जो रोक सकते हैं वह है “जब आएँ तो data खोना”।
सौभाग्य से Windows के पास shutdown से पहले ऐप को सूचित करने का mechanism है — GUI ऐप, console ऐप और service, तीनों के लिए। छोटे-मध्यम व्यवसायों के IT staff और Windows ऐप developers (खासकर device-PC और लंबे समय चलने वाले ऐप) के लिए, यह लेख उन notifications को कैसे लें, “कुछ सेकंड में खत्म” cleanup कैसे design करें, restart के बाद automatic recovery, और बिना notification power loss की तैयारी — सब अगस्त 2026 तक Microsoft Learn primary sources पर आधारित — व्यवस्थित करता है।
1. निष्कर्ष पहले
- Shutdown को “सामान्य घटना जो देर-सबेर आएगी” मानकर design करें। Notification मिलने के बाद उपयोग योग्य समय सिद्धांततः लगभग 5 सेकंड ही है, इसलिए वहीं सब कुछ हड़बड़ी से save करने वाला design टूट जाएगा। पूर्वापेक्षा बार-बार autosave है ताकि “shutdown पर save करने वाला delta” छोटा रहे।1
- Windows 8 से आगे के client OS पर, जब fast startup चालू हो (hibernation समर्थित अधिकांश PC पर default), “Shut down” hybrid shutdown है, और kernel केवल hibernate हो रहा है। पूरी तरह reset केवल “Restart” है। यही असली कारण है “मैंने shutdown किया, बेहतर नहीं हुआ, फिर restart किया तो हुआ”।2
- GUI ऐप को WM_QUERYENDSESSION पर तुरंत TRUE लौटाना चाहिए, और cleanup WM_ENDSESSION में करना चाहिए। सिद्धांततः FALSE (अस्वीकार) नहीं लौटाना।1
- केवल जब सचमुच ऐसा काम हो जो बीच में नहीं काटा जा सकता, ShutdownBlockReasonCreate से कारण दिखाएँ। तब भी user और OS ज़बरदस्ती जारी रख सकते हैं, इसलिए “हम block कर सकते हैं” मानने वाला design टिकता नहीं।34
- Console ऐप notification SetConsoleCtrlHandler से पाता है। Grace period और छोटी है — console बंद पर default 5 सेकंड। एक जाल भी है: जिस process ने gdi32.dll या user32.dll load किया हो, इनमें से कुछ events नहीं आते।56
- .NET के AppDomain.ProcessExit पर निर्भर cleanup .NET 10 से उन paths पर नहीं चलता जहाँ process “बाहर से terminate” होती है। Main से लौटने जैसी सामान्य exit पर वह पहले जैसा चलता है, पर क्योंकि runtime console बंद और shutdown जैसे termination signals का default handling नहीं देता, उन paths का cleanup ऐप model से मेल खाने वाली notification पर जाना चाहिए।7
- Windows service SERVICE_ACCEPT_PRESHUTDOWN SERVICE_ACCEPT_SHUTDOWN (लगभग 20 सेकंड grace period) से पहले, और configurable grace period के साथ, पा सकती है। पर default PRESHUTDOWN timeout Windows 10 Creators Update से 10 सेकंड कर दिया गया, इसलिए दोनों तरह grace period पर बहुत झुकने वाला design नहीं चाहिए।89
- Restart के बाद automatic recovery RegisterApplicationRestart को ARSO (automatic sign-on) से जोड़कर हो सकती है। Crash, unresponsive, और update-driven restart के लिए paths हैं।1011
- Power loss कोई notification नहीं लाती। मानक pattern temporary फ़ाइल में पूरा लिखना, flush, और ReplaceFile से अदला-बदली है, पर क्योंकि बिजली कटने पर ReplaceFile भी atomicity गारंटी नहीं देता, backup (.bak) प्लस load-समय जाँच recovery path सेट का हिस्सा है। बाद का isolation event log (1074/41/6008) से हो सकता है।121314
एक वाक्य में इस लेख का निष्कर्ष: “Notification आने पर कुछ सेकंड में दुकान बंद कर सकने वाली state हमेशा रखें, और ऐसे लिखें जो बिना notification power loss पर भी न टूटे”।
2. Shutdown पर क्या होता है — समाप्त होने के चार रास्ते
2.1. Sign-out, shutdown, restart और power loss
ऐप की नज़र से दो अक्ष मायने रखते हैं: “user session कैसे खत्म होता है” और “kernel का क्या होता है”।
| क्रिया | User session | Kernel और drivers | ऐप को notification |
|---|---|---|---|
| Sign-out | खत्म | चलता रहता है | WM_QUERYENDSESSION (ENDSESSION_LOGOFF) → WM_ENDSESSION |
| Shutdown (fast startup चालू) | खत्म | Hibernate (hiberfil.sys में सहेजा) | WM_QUERYENDSESSION → WM_ENDSESSION, services को (PRE)SHUTDOWN |
| Restart | खत्म | पूरी तरह खत्म; अगला boot पूर्ण boot | ऊपर जैसा |
| Power loss | तुरंत गायब | तुरंत गायब | कोई नहीं |
ऐप की नज़र से sign-out और shutdown लगभग एक ही event हैं। यदि WM_QUERYENDSESSION के lParam में ENDSESSION_LOGOFF bit set हो तो sign-out है; यदि 0 हो तो shutdown या restart (दोनों अलग नहीं बता सकते)।1 यानी “केवल sign-out है, चल जाएगा” वाली ढिलाई टिकती नहीं, और सही design वही cleanup code चलाना है।
flowchart TB
accTitle: समाप्त होने के चार रास्ते, और ऐप को notification
accDescr: Sign-out, shutdown और restart WM_QUERYENDSESSION से WM_ENDSESSION notification देते हैं, और cleanup कुछ सेकंड में खत्म होता है। केवल power loss पर कोई notification नहीं, इसलिए chapter 8 के लेखन design और UPS से तैयारी करें
signout["Sign-out"] --> notified["QUERY → ENDSESSION"]
shutdown["Shutdown"] --> notified
reboot["Restart"] --> notified
poweroff["Power loss"] --> none["Notification नहीं: लेखन + UPS"]
notified --> cleanup["सेकंडों में cleanup"]
चित्र 1: Sign-out, shutdown और restart WM_QUERYENDSESSION से WM_ENDSESSION notification देते हैं, और cleanup कुछ सेकंड में खत्म होता है। केवल power loss पर कोई notification नहीं, इसलिए chapter 8 के लेखन design और UPS से तैयारी करें।
2.2. “मैंने shutdown किया फिर भी बेहतर नहीं हुआ” का असली कारण — hybrid shutdown
तालिका की आसानी से छूटने वाली पंक्ति दूसरी है। Windows 8 से आगे के client OS पर fast startup (hybrid shutdown) hibernation समर्थित PC पर default से चालू है, और “Shut down” का व्यवहार बदल गया। User session का sign-out पहले जैसा होता है, पर kernel session बंद नहीं होता; वह device drivers समेत hibernation फ़ाइल (hiberfil.sys) में सहेजा जाता है और अगले boot पर ज्यों-का-त्यों लौटता है। इससे startup तेज़ होता है, पर kernel और driver state बिजली काटने पर भी बचती है।2 यह, पर, सशर्त व्यवहार है। जहाँ hibernation स्वयं बंद हो (powercfg /hibernate off), जहाँ policy या Power Options ने fast startup बंद किया हो, और Windows Server पर, shutdown पारंपरिक पूर्ण shutdown है। दिया PC किस रास्ते पर है, Power Options के “Turn on fast startup” check box से, या powercfg /a (उपलब्ध sleep states) “Fast Startup” सूचीबद्ध करता है या नहीं, उससे पता चलता है।
flowchart TB
accTitle: Shut down क्रिया पर kernel का क्या होता है
accDescr: Shut down क्रिया fast startup चालू होने पर पूर्ण shutdown या kernel hibernation में बँटती है, और Restart हमेशा पूर्ण boot करता है
op["Shut down"]
restart["Restart"]
op -->|"Fast startup चालू"| hybrid["Session खत्म + kernel hibernate"]
op -->|"Hibernate बंद / Server"| full["पूर्ण shutdown"]
hybrid --> resume["अगला: kernel restore"]
full --> boot["अगला: पूर्ण boot"]
restart --> boot
चित्र 2: Shut down क्रिया fast startup चालू होने पर पूर्ण shutdown या kernel hibernation में बँटती है, और Restart हमेशा पूर्ण boot करता है।
इसके विपरीत “Restart” हमेशा पूरा boot cycle चलाता है। Driver update के बाद, उदाहरण के लिए, पूरी तरह नई state चाहिए।2 उससे मैदान में सुनी कई घटनाएँ जगह बैठती हैं।
- “मैंने shutdown कर फिर चालू किया, पर device समस्या नहीं गई” — kernel और drivers केवल hibernation से लौटे; reset नहीं हुए
- “Restart के बाद बेहतर हुआ” — क्योंकि पूर्ण boot ने उन्हें initialize किया
- Device-PC घटना प्रक्रिया को कहना चाहिए “Restart”, “बंद करके चालू करें” नहीं
Command line से पूर्ण shutdown स्पष्ट करना हो तो shutdown /s (Shutdown.exe का default पूर्ण shutdown है); default hybrid व्यवहार चाहिए तो shutdown /s /hybrid।2 Fast startup बंद करना recommended नहीं। ऐप पक्ष को मानना चाहिए “shutdown पर kernel केवल hibernate हो सकता है” — उदाहरण के लिए OS boot समय से “संचयी uptime” न आँकें — और design करें कि किसी भी रास्ते न टूटे (fast startup चालू या बंद वातावरण से भिन्न होता है)।
3. GUI ऐप को कैसा व्यवहार करना चाहिए — WM_QUERYENDSESSION और WM_ENDSESSION
3.1. दो messages काम कैसे बाँटते हैं
जिस ऐप के पास window और message queue हो उसे session समाप्ति दो चरणों में सूचित होती है।1
- WM_QUERYENDSESSION — प्रश्न: “खत्म करना ठीक है?” ऐप को तुरंत TRUE लौटाना चाहिए; DefWindowProc का default उत्तर भी TRUE है। यहाँ cleanup शुरू न करें।
- WM_ENDSESSION (wParam=TRUE) — निश्चित notification: “session सचमुच खत्म हो रहा है”। Cleanup यहाँ होता है।
WM_QUERYENDSESSION पर FALSE लौटाना shutdown रोक सकता है, पर document स्पष्ट है कि “आपको TRUE लौटाकर user के इरादे का सम्मान करना चाहिए”, और FALSE लौटाने वाला ऐप फिर भी पूर्ण-screen UI में “shutdown रोकने वाला ऐप” दिखता है। Console ऐप और बिना दिखाई window वाले ऐप shutdown रोक ही नहीं सकते, और 5 सेकंड में उत्तर न दें तो स्वचालित terminate हो जाते हैं।14
flowchart TB
accTitle: दो-चरण session-समाप्ति notification का flow
accDescr: WM_QUERYENDSESSION प्रश्न पर TRUE लौटाने से WM_ENDSESSION निश्चित होता है और cleanup चलता है। FALSE से अस्वीकार ऐप को shutdown रोकने वाला दिखाता है, और लगभग 5 सेकंड बिना उत्तर ज़बरदस्ती जारी रख सकता है
q["WM_QUERYENDSESSION"]
q -->|"TRUE(नियम)"| e["WM_ENDSESSION(निश्चित)"]
q -->|"FALSE(अस्वीकार)"| blocked["Shutdown रोकने वाला दिखाया"]
q -->|"कोई उत्तर नहीं ~5 सेकंड"| hung["Hang माना"]
e --> cleanup["Cleanup यहाँ"]
cleanup --> term["Process exit"]
hung --> term
blocked -->|"ज़बरदस्ती जारी"| term
blocked -->|"Cancel"| cont["Shutdown निरस्त"]
चित्र 3: WM_QUERYENDSESSION प्रश्न पर TRUE लौटाने से WM_ENDSESSION निश्चित होता है और cleanup चलता है। FALSE से अस्वीकार ऐप को shutdown रोकने वाला दिखाता है, और लगभग 5 सेकंड बिना उत्तर ज़बरदस्ती जारी रख सकता है।
3.2. उत्तर न दें तो क्या होता है — 5-सेकंड की दीवार
WM_QUERYENDSESSION और WM_ENDSESSION दोनों पर उत्तर लगभग 5 सेकंड delayed कर सकते हैं। उससे आगे सिस्टम “यह ऐप shutdown रोक रहा है” screen दिखाता है, और user ज़बरदस्ती जारी (= ऐप को ज़बरदस्ती terminate) चुन सकता है।4 ज़बरदस्ती terminate process को save खत्म करने का दूसरा मौका नहीं मिलता।
Design बिंदु इसलिए ये दो हैं।
- Cleanup उस मात्रा तक रखें जो 5 सेकंड में खत्म हो। Microsoft स्वयं सामान्य काम में data बार-बार save करने की सलाह देता है ताकि shutdown पर कम save करना पड़े, और न-save data temporary स्थान पर save कर अगले launch पर restore करें।1
- Shutdown के दौरान confirmation dialog न दिखाएँ। जब आप “save करना चाहते हैं?” पर बैठे हों, 5 सेकंड बीत जाते हैं। चुपचाप सुरक्षित पक्ष पर जाएँ (autosave)।
3.3. WinForms और WPF में implementation
.NET desktop ऐप में ये messages framework events बनते हैं। WinForms में FormClosing उठता है, और CloseReason बताता है कि shutdown कारण है या नहीं।
// 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 event (XAML SessionEnding विशेषता, या OnSessionEnding override) मेल खाता है।
flowchart TB
accTitle: WinForms/WPF events messages से कैसे map होते हैं
accDescr: WM_QUERYENDSESSION का query चरण WinForms FormClosing और WPF SessionEnding से map होता है, और वहाँ अधिकतम idempotent snapshot save करें। निश्चित WM_ENDSESSION का matching event नहीं, इसलिए WndProc या hook में लें और केवल निश्चित होने के बाद चल सकने वाला cleanup करें
q["WM_QUERYENDSESSION"] --> fc["WinForms: FormClosing"]
q --> se["WPF: SessionEnding"]
fc -.-> idem["केवल idempotent snapshot"]
se -.-> idem
e["WM_ENDSESSION"] --> hook["कोई event नहीं: WndProc hook"]
hook -.-> final["निश्चित होने के बाद cleanup"]
चित्र 4: WM_QUERYENDSESSION का query चरण WinForms FormClosing और WPF SessionEnding से map होता है, और वहाँ अधिकतम idempotent snapshot save करें। निश्चित WM_ENDSESSION का matching event नहीं, इसलिए WndProc या hook में लें और केवल निश्चित होने के बाद चल सकने वाला cleanup करें।
// 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 दोनों query चरण (WM_QUERYENDSESSION) से मेल खाते हैं। यदि कोई अन्य ऐप अस्वीकार करे, shutdown निरस्त होता है और आपका ऐप चलता रहता है। इसलिए इन events में जो कर सकते हैं वह है idempotent snapshot save जो shutdown निरस्त होने पर नुकसान न करे और जितनी बार चले वही परिणाम दे। यदि “cleanup जो केवल सचमुच खत्म होते समय करना हो” (disconnect, संसाधन वापस, आदि) चाहिए, निश्चित WM_ENDSESSION (wParam=TRUE) को सीधे WndProc में hook करें और वहाँ करें।
किसी भी path पर शरीर को साझा “snapshot save” function में मोड़ें और सामान्य exit, shutdown, और (यदि संभव हो) crash के लिए restore data एक ही format में लिखें, ताकि अगले launch पर restore logic एक path हो। Crash पर भी जानकारी छोड़ने का design “Crash पर logs और dumps छोड़ने वाले Windows ऐप design करना” में है।
4. यदि सचमुच block करना हो — ShutdownBlockReasonCreate
जो काम बीच में कटने पर physically टूटते हैं, जैसे CD या firmware लिखना, अपवाद हैं। यहाँ सही अभ्यास है uninterruptible काम शुरू होने पर ShutdownBlockReasonCreate से कारण string register करना, और खत्म होते ही ShutdownBlockReasonDestroy call करना। Shutdown request पर वह कारण “यह ऐप shutdown रोक रहा है” screen पर दिखता है, और user जारी रखने या cancel करने का निर्णय ले सकता है।3
flowchart TB
accTitle: ShutdownBlockReasonCreate से सुरक्षा का flow
accDescr: Uninterruptible काम शुरू होने पर कारण register करें; सुरक्षा के दौरान shutdown request आए तो कारण पूर्ण screen पर दिखता है और WM_QUERYENDSESSION FALSE से अस्वीकृत होता है। User cancel या ज़बरदस्ती जारी रख सकता है, और काम खत्म होने पर कारण साफ़ होता है
begin["Uninterruptible काम शुरू"] --> reg["ShutdownBlockReasonCreate"]
reg --> work["Worker thread पर चलाएँ"]
work --> done["खत्म: Destroy"]
req["इस दौरान shutdown"] --> show["कारण दिखाएँ + FALSE"]
show -->|"Cancel"| work
show -->|"ज़बरदस्ती जारी"| kill["Process exit"]
चित्र 5: Uninterruptible काम शुरू होने पर कारण register करें; सुरक्षा के दौरान shutdown request आए तो कारण पूर्ण screen पर दिखता है और WM_QUERYENDSESSION FALSE से अस्वीकृत होता है। User cancel या ज़बरदस्ती जारी रख सकता है, और काम खत्म होने पर कारण साफ़ होता है।
[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 केवल कारण string register करता है; वह स्वयं shutdown नहीं रोकता। जो सचमुच shutdown रोकता है वह आपका अपना handling है जो सुरक्षा flag set रहते WM_QUERYENDSESSION पर FALSE लौटाता है, जैसा ऊपर। दोनों को सेट की तरह इस्तेमाल करें, और काम खत्म होते ही दोनों तुरंत साफ़ करें। साथ ही, सुरक्षित काम स्वयं worker thread पर चलाएँ और UI thread messages process कर सके — अस्वीकार mechanism तभी काम करता है जब message आए (और तब भी user और OS ज़बरदस्ती जारी रख सकते हैं, इसलिए “यदि नहीं रुका” तो न टूटने वाला लेखन design — chapter 8 — अभी भी चाहिए)।
परिचालन की तीन चेतावनियाँ हैं।
- कारण string छोटी और विशिष्ट रखें। User जल्दी में है और कुछ सेकंड ही पढ़ेगा। Document स्वयं “Burning a CD” उपयुक्त उदाहरण देता है।3
- ऐप के पूरे जीवन register न छोड़ें। “केवल जब uninterruptible काम चल रहा हो” वही API मानता है।
- इस धारणा पर design न करें कि block कर सकते हैं। User ज़बरदस्ती जारी चुन सकता है, और ज़बरदस्ती shutdown (ENDSESSION_CRITICAL) पहले से wait नहीं करेगा। Document स्पष्ट है: “Applications should not depend on being able to block shutdown”।4
5. Console ऐप और background processes को कैसा व्यवहार करना चाहिए
5.1. SetConsoleCtrlHandler और छोटी grace period
Console ऐप window messages नहीं पा सकता, इसलिए control signals SetConsoleCtrlHandler से register handler function पर आते हैं। प्रति signal default grace period इस प्रकार है।5
| Signal | कब होता है | Default grace period |
|---|---|---|
| CTRL_C_EVENT / CTRL_BREAK_EVENT | Ctrl+C / Ctrl+Break | कोई timeout नहीं |
| CTRL_CLOSE_EVENT | Console बंद करना, Task Manager “End task” (“Details” tab से ज़बरदस्ती process मारना बिना notification तुरंत exit है, और इस तालिका से बाहर है) | लगभग 5 सेकंड |
| CTRL_SHUTDOWN_EVENT | सिस्टम shutdown (service processes) | लगभग 20 सेकंड |
देखने योग्य दो बिंदु हैं। पहला, मूलतः केवल service के रूप में चल रही process CTRL_LOGOFF_EVENT और CTRL_SHUTDOWN_EVENT पा सकती है। Interactive session का ऐप sign-out पर terminate होता है, इसलिए इन signals की wait करने वाला design टिकता नहीं।5 दूसरा, जिस process ने gdi32.dll या user32.dll load किया हो उसे console ऐप समझने पर भी Windows ऐप माना जाता है, और LOGOFF/SHUTDOWN handlers नहीं बुलाए जाते। Official समाधान छिपी window बनाना और WM_QUERYENDSESSION/WM_ENDSESSION लेना है।6
flowchart TB
accTitle: प्रति console signal grace period
accDescr: Ctrl+C और Ctrl+Break का स्पष्ट timeout नहीं; console बंद पर लगभग 5 सेकंड और service process को shutdown signal पर लगभग 20 सेकंड; पार करने पर process ज़बरदस्ती terminate
ctrlc["CTRL_C / BREAK"] -->|"कोई timeout नहीं"| handler["HandlerRoutine cleanup"]
closeev["CTRL_CLOSE"] -->|"लगभग 5 सेकंड"| handler
shutev["CTRL_SHUTDOWN"] -->|"लगभग 20 सेकंड"| handler
handler --> timeout["Grace period बाद ज़बरदस्ती मार"]
चित्र 6: Ctrl+C और Ctrl+Break का स्पष्ट timeout नहीं; console बंद पर लगभग 5 सेकंड और service process को shutdown signal पर लगभग 20 सेकंड; पार करने पर process ज़बरदस्ती terminate।
// 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 में बस cleanup कर दें” वाला stock pattern रहा है, पर .NET 10 से runtime default termination-signal handler नहीं देता, और CTRL_CLOSE_EVENT/CTRL_SHUTDOWN_EVENT पर न ProcessExit न AssemblyLoadContext.Unloading चलता है। OS default handler process को तुरंत terminate कर देता है।7
flowchart TB
accTitle: .NET 10 में ProcessExit कैसे बदला
accDescr: .NET 9 तक runtime का default signal handler termination signals लेता, ProcessExit उठाता, फिर निकलता। .NET 10 से runtime default handler नहीं देता, OS default handling process तुरंत terminate करती है, और handler आप स्वयं register करते हैं
sig["CTRL_CLOSE / SHUTDOWN"] --> old9[".NET 9 तक: ProcessExit"]
sig --> new10[".NET 10 से: तुरंत exit"]
new10 -.-> alt["Handler स्वयं register करें"]
चित्र 7: .NET 9 तक runtime का default signal handler termination signals लेता, ProcessExit उठाता, फिर निकलता। .NET 10 से runtime default handler नहीं देता, OS default handling process तुरंत terminate करती है, और handler आप स्वयं register करते हैं।
इसके बजाय प्रत्येक ऐप model के मानक paths पर जाएँ।
- GUI ऐप: पिछले chapter के FormClosing / SessionEnding
- Generic Host (Worker Service सहित): IHostApplicationLifetime और BackgroundService.StopAsync। HostOptions.ShutdownTimeout से stop grace period स्पष्ट करें
- सादा console ऐप: SetConsoleCtrlHandler (या PosixSignalRegistration से SIGINT/SIGTERM समकक्ष subscribe करें)
flowchart TB
accTitle: प्रत्येक ऐप model exit notification कहाँ पाता है
accDescr: GUI ऐप FormClosing और SessionEnding प्लस निश्चित काम के लिए WM_ENDSESSION hook इस्तेमाल करता है; Generic Host IHostApplicationLifetime और StopAsync; सादा console ऐप SetConsoleCtrlHandler या PosixSignalRegistration। ProcessExit पर निर्भरता बाहरी-signal paths पर नहीं चलती
model{"कौन सा ऐप model?"}
model -->|"GUI"| gui["FormClosing / SessionEnding"]
model -->|"GUI नहीं"| other{"Host या console?"}
gui -.-> guihook["ENDSESSION hook"]
other -->|"Host"| host["Lifetime + StopAsync"]
other -->|"Console"| con["SetConsoleCtrlHandler"]
host -.-> hostto["ShutdownTimeout set करें"]
con -.-> ngx["ProcessExit पर निर्भर न करें"]
चित्र 8: GUI ऐप FormClosing और SessionEnding प्लस निश्चित काम के लिए WM_ENDSESSION hook इस्तेमाल करता है; Generic Host IHostApplicationLifetime और StopAsync; सादा console ऐप SetConsoleCtrlHandler या PosixSignalRegistration। ProcessExit पर निर्भरता बाहरी-signal paths पर नहीं चलती।
Grace period path से भिन्न है — GUI और console बंद पर लगभग 5 सेकंड, service के लिए chapter 6 की SCM grace period (लगभग 20 सेकंड, या PRESHUTDOWN का configure मान), और Ctrl+C पर कोई स्पष्ट timeout नहीं। हर path पर, पर, grace period सीमित है और भरोसा नहीं किया जा सकता, इसलिए design अक्ष यह है कि सामान्य मामला “प्रत्येक processing checkpoint पर पहले से save” है, “exit event में कड़ी मेहनत” नहीं।
6. Windows service को कैसा व्यवहार करना चाहिए — SHUTDOWN और PRESHUTDOWN
6.1. Shutdown notification की दो तरह
Service sign-out से प्रभावित नहीं होती, पर shutdown और restart पर रुकती है। Notification Service Control Manager (SCM) से control code के रूप में आती है, और पाने के लिए accept flag घोषित करना पड़ता है।8
| घोषणा | आने वाली notification | समय और grace period |
|---|---|---|
| SERVICE_ACCEPT_SHUTDOWN | SERVICE_CONTROL_SHUTDOWN | Shutdown processing के दौरान सूचित। Default लगभग 20 सेकंड, ऊपरी सीमा WaitToKillServiceTimeout |
| SERVICE_ACCEPT_PRESHUTDOWN | SERVICE_CONTROL_PRESHUTDOWN | SHUTDOWN से पहले सूचित। SCM service रुकने या timeout तक wait करता है |
flowchart TB
accTitle: Service को shutdown notifications का क्रम
accDescr: Shutdown शुरू होने पर PRESHUTDOWN घोषित services पहले configure grace period के साथ सूचित होती हैं, फिर SHUTDOWN notification लगभग 20 सेकंड default के साथ भेजी जाती है, और grace period खत्म होने पर process terminate
start["Shutdown शुरू"] --> pre["PRESHUTDOWN(यदि घोषित)"]
pre --> shut["SHUTDOWN(लगभग 20 सेकंड)"]
shut --> kill["Grace period खत्म → exit"]
चित्र 9: Shutdown शुरू होने पर PRESHUTDOWN घोषित services पहले configure grace period के साथ सूचित होती हैं, फिर SHUTDOWN notification लगभग 20 सेकंड default के साथ भेजी जाती है, और grace period खत्म होने पर process terminate।
PRESHUTDOWN timeout ChangeServiceConfig2 (SERVICE_CONFIG_PRESHUTDOWN_INFO) से configure हो सकता है; default Windows 10 Creators Update (build 15063) से 10 सेकंड, उससे पहले 3 मिनट है।9 यदि अभी भी पुराने ज्ञान से काम कर रहे हैं कि “PRESHUTDOWN 3 मिनट देता है”, वर्तमान OS पर अपेक्षित grace period का केवल 1/18 है। साथ ही, PRESHUTDOWN उस अंतराल पूरे सिस्टम का shutdown रोकता है, इसलिए document भी कहता है कि इसे “केवल special परिस्थितियों में इस्तेमाल करना चाहिए”।8
Handler-पक्ष अभ्यास भी मायने रखता है। Control handler को 30 सेकंड में लौटना चाहिए; समय लेने वाला stop-काम दूसरे thread पर छोड़ें, SERVICE_STOP_PENDING report करें, और तुरंत लौटें।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. Grace period पर निर्भर न करने वाला design
Grace period की छत WaitToKillServiceTimeout को service पक्ष से लिखकर बढ़ाना स्पष्ट रूप से recommended नहीं। Document उलटा माँगता है — service को cleanup जितना जल्दी हो खत्म करना चाहिए ताकि UPS-संचालित machine battery खत्म होने से पहले shutdown पूरा कर सके। मार्गदर्शन सामान्य काम में बार-बार save करना है ताकि न-save data न्यूनतम रहे, shutdown पर memory मुक्त करने में समय न गँवाना, और network साथी को सूचित करते बहुत लंबी wait न करना। साथ ही, SCM shutdown पर default से dependencies नहीं देखता, इसलिए stop processing “भले जिस service पर depend हों वह पहले गिर चुकी हो” तब भी काम करना चाहिए।8
flowchart TB
accTitle: Grace period पर निर्भर न करने वाला stop processing design
accDescr: यदि प्रत्येक processing checkpoint पर save करें ताकि न-save data हमेशा न्यूनतम रहे, stop notification आने पर cleanup कुछ सेकंड में खत्म होता है। Exit पर सब save करने वाला design grace period में नहीं समाएगा, और ज़बरदस्ती termination data खो देती है
good["प्रत्येक checkpoint पर save"] --> gstop["Stop → छोटा save → पूरा"]
bad["Exit पर सब save"] --> bstop["Stop → save grace period चूकता"]
bstop --> killed["ज़बरदस्ती मार → data हानि"]
चित्र 10: यदि प्रत्येक processing checkpoint पर save करें ताकि न-save data हमेशा न्यूनतम रहे, stop notification आने पर cleanup कुछ सेकंड में खत्म होता है। Exit पर सब save करने वाला design grace period में नहीं समाएगा, और ज़बरदस्ती termination data खो देती है।
.NET Worker Service (UseWindowsService) में SERVICE_CONTROL_STOP और SHUTDOWN host stop में translate होते हैं, और BackgroundService.StopAsync बुलाया जाता है। इस लेखन के समय stock implementation STOP/SHUTDOWN परिवार स्वीकार करता है; PRESHUTDOWN भी चाहिए तो extended handler चाहिए। दोनों तरह HostOptions.ShutdownTimeout स्पष्ट करें और StopAsync कुछ सेकंड में खत्म करें। Service बनाने के सामान्य विषय के लिए “Windows services कैसे बनाएँ और चलाएँ” देखें।
7. Restart के बाद automatic recovery
Device PC या बिना-उपस्थिति PC पर design दायरा केवल “shutdown से बचना” नहीं, “restart के बाद स्वयं लौटना” भी है।
7.1. RegisterApplicationRestart और recovery callback
यदि RegisterApplicationRestart call किया हो, ऐप crash (unhandled exception), unresponsive, update-driven ऐप restart, और update-driven OS restart के लिए restart candidate register होता है। Restart के लिए command-line arguments register कर सकते हैं, इसलिए यदि “कौन सी फ़ाइल खुली थी” और “कौन सा restore बिंदु” शामिल करें, restart के बाद जहाँ छोड़ा था वहाँ से जारी रख सकते हैं।10
अपनाए जाने वाले विनिर्देश इस प्रकार हैं।10
- Registration समस्या आने से पहले खत्म होना चाहिए (update परिदृश्य में WM_QUERYENDSESSION handling अंतिम मौका है)
- Restart loop रोकने के लिए 60 सेकंड से कम चली process restart नहीं होती
- Elevated चल रही process automatic restart की candidate नहीं (elevation consent बिना process दोबारा नहीं बन सकती)। Elevation चाहिए ऐप की automatic recovery UI को standard privilege पर रखकर और privilege काम service में अलग कर, या Task Scheduler कार्य “highest privileges से चलाएँ” जैसे स्पष्ट launch path से design होती है
- Crash या hang के बाद restart user consent से जाता है; update के बाद restart automatic है
- OS restart पार कर recover करने के लिए, restart माँगने वाले पक्ष (installer आदि) को EWX_RESTARTAPPS / SHUTDOWN_RESTARTAPPS flags के साथ shutdown API call करना चाहिए
यदि RegisterApplicationRecoveryCallback भी register करें, crash पर WER (Windows Error Reporting) callback बुलाता है और प्रगति पर data save करने की grace period देता है। यदि save समय ले, registration पर specified ping अंतराल में ApplicationRecoveryInProgress बार-बार call करना चाहिए वरना recovery काम बीच में कट जाता है। Save खत्म होने पर ApplicationRecoveryFinished से completion सूचित करें। ऐप-update समय “उपयोग में फ़ाइल बदलना और restart” Restart Manager का क्षेत्र है, विस्तार से “उपयोग में exe या DLL कैसे बदलें” में।
7.2. ARSO — update restart के बाद automatic sign-in
Windows Update restart के बाद, यदि कोई sign-in न करे, user-session ऐप नहीं लौटते। वह अंतर ARSO (Winlogon Automatic Restart Sign-On) भरता है। जब Windows Update restart शुरू करता है, वह अंतिम interactive user की credentials सुरक्षित सहेजता है, Autologon configure करता है, और restart के बाद उस user को automatic sign-in कर फिर screen lock करता है।11 shutdown /g जैसा आदेश भी है जो restart प्लस registered ऐप फिर से शुरू माँगता है। कुछ वातावरण इसे संगठनात्मक policy (DisableAutomaticRestartSignOn आदि) से बंद करते हैं, इसलिए बिना-उपस्थिति recovery design करते समय इस setting को सेट की तरह जाँचें। और यदि हमेशा चाहिए background काम के लिए user session में automatic launch पर निर्भर हैं, सही कदम शुरू से Windows service बनाना है।
flowchart TB
accTitle: Restart के बाद ऐप automatic कैसे लौटता है
accDescr: समस्या से पहले RegisterApplicationRestart register करें तो crash या unresponsive पर user consent के बाद ऐप restart होता है, और update-driven restart पर ARSO automatic sign-in और screen lock के बाद। 60 सेकंड से कम runtime और elevated processes दायरे से बाहर
reg["RegisterApplicationRestart"]
reg --> crash["Crash या hang"]
reg --> update["Update restart"]
crash -->|"Consent"| restart["ऐप restart"]
update --> arso["ARSO sign-in + lock"]
arso --> restart
restart -.-> limits["नहीं: 60 सेकंड से कम / elevated"]
चित्र 11: समस्या से पहले RegisterApplicationRestart register करें तो crash या unresponsive पर user consent के बाद ऐप restart होता है, और update-driven restart पर ARSO automatic sign-in और screen lock के बाद। 60 सेकंड से कम runtime और elevated processes दायरे से बाहर।
8. बिना notification power loss से बचना — लेखन design और UPS
8.1. ऐसा लेखन जो “जब भी कटे न टूटे” — temporary फ़ाइल + ReplaceFile
ट्रिप हुआ breaker, fail PSU, या खींचा plug न WM_ENDSESSION लाता है न PRESHUTDOWN। जब तक setting या माप परिणाम के लिए “original फ़ाइल को उसी जगह overwrite” करते हैं, लिखते-लिखते बिजली कटने पर पुरानी-नई मिली टूटी फ़ाइल रह सकती है।
मानक pattern उसी volume पर temporary फ़ाइल में पूरा लिखकर फिर अदला-बदली है। ReplaceFile “नई फ़ाइल में save → original अलग → नाम बदल → हटाएँ” क्रम को एक API में पैक करता है, और original फ़ाइल के creation time, ACL, और alternate streams जैसे गुण भी ले जाता है (तीनों फ़ाइलें उसी volume पर होनी चाहिए)।12 .NET का File.Replace इसे ज्यों-का-त्यों call करता है।
flowchart TB
accTitle: Temporary फ़ाइल और ReplaceFile से save और recovery flow
accDescr: Save पर temporary फ़ाइल में पूरा लिखें, flush करें, और ReplaceFile से अदला-बदली करें, पुरानी सामग्री .bak में छोड़ें। अगले launch पर primary फ़ाइल जाँचें और टूटी हो तो .bak पर जाएँ
subgraph save["Save पर"]
w["पूरी temporary फ़ाइल लिखें"] --> f["Disk पर flush"]
f --> r["ReplaceFile → .bak"]
end
subgraph startup["अगले launch पर"]
v["Primary जाँचें"]
v -->|"अक्षत"| use["ज्यों का त्यों इस्तेमाल"]
v -->|"टूटी"| bak[".bak पर जाएँ"]
end
r -.->|"किसी भी चरण बिजली कट"| v
चित्र 12: Save पर temporary फ़ाइल में पूरा लिखें, flush करें, और ReplaceFile से अदला-बदली करें, पुरानी सामग्री .bak में छोड़ें। अगले launch पर primary फ़ाइल जाँचें और टूटी हो तो .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, पर, multi-step namespace क्रिया है, और बिजली कटने पर atomicity spec से गारंटी नहीं। इसीलिए ऊपर का उदाहरण backup (.bak) रखता है — पढ़ने वाला पक्ष launch पर primary फ़ाइल जाँचता है और टूटी हो तो backup पर जाता है, सेट की तरह। इसे केवल-जोड़ log या CSV पर इस्तेमाल नहीं कर सकते, इसलिए वे ऐसा format इस्तेमाल करते हैं जो टूटन शामिल करे, जैसे “एक पंक्ति = एक record, और पढ़ते समय टूटी अंतिम पंक्ति फेंकें”।
8.2. WriteFile की सफलता disk तक पहुँचना नहीं
दूसरी धारणा यह है कि WriteFile सफलता लौटाए तब भी data केवल OS cache में हो सकता है। Windows फ़ाइल पढ़ना-लिखना सिस्टम buffer पर रखता है और lazy write से समय-समय disk पर प्रतिबिंबित करता है। Data निश्चित disk तक ले जाने के लिए या FlushFileBuffers से स्पष्ट flush करें, या CreateFile पर FILE_FLAG_WRITE_THROUGH specify करें ताकि प्रत्येक लेखन cache पार करे। File-system metadata हमेशा cache होता है, इसलिए metadata पुष्टि को भी flush या write-through चाहिए।13
हर बार FlushFileBuffers call करना अक्षम है, पर, और document भी बार-बार call के बजाय FILE_FLAG_NO_BUFFERING+WRITE_THROUGH विचार करने को प्रोत्साहित करता है।13 व्यवहार में “केवल transaction checkpoint पर या फ़ाइल बंद करने से ठीक पहले flush” यथार्थ समझौता है। इस परत की mechanics — cache manager, lazy write, और यह तथ्य कि hardware cache के कारण “flush किया फिर भी disk तक नहीं पहुँचा हो सकता” — गहराई से “Cache Manager: आपका WriteFile वास्तव में disk तक कब पहुँचता है?” में है।
8.3. UPS और battery निगरानी — power loss को shutdown बनाना
Device PC पर power loss का असली उपाय UPS है। UPS की भूमिका “power outage रोकना” नहीं, “बिना notification power loss” को “notification वाला नियोजित shutdown” बनाना मानें। Design दो-चरण setup है।
- Grace period design करना: UPS battery hold समय > “battery switch पकड़ें → ऐप और service cleanup → OS shutdown पूरा” का योग। यदि service stop processing धीमा हो, यह समीकरण नहीं टिकता (खंड 6.2)
- पता लगाना: AC से battery switch, और शेष क्षमता गिरना, PBT_APMPOWERSTATUSCHANGE event से सूचित होते हैं। Window वाले ऐप इसे WM_POWERBROADCAST के रूप में पाते हैं; बिना window service SERVICE_ACCEPT_POWEREVENT घोषित कर HandlerEx में SERVICE_CONTROL_POWEREVENT के रूप में पाती है (WM_POWERBROADCAST service control handler तक नहीं आता)। प्राप्ति पर GetSystemPowerStatus call करें, ACLineStatus (AC पर है या नहीं) और BatteryLifePercent जाँचें, और माप रोकना, save, और shutdown request तक ले जाएँ15
flowchart TB
accTitle: UPS से power loss को नियोजित shutdown बनाने का flow
accDescr: Outage UPS को battery पर switch करे तो PBT_APMPOWERSTATUSCHANGE सूचित होता है, power स्थिति जाँची जाती है, और save प्लस shutdown request बिना notification power loss को notification वाले नियोजित shutdown में बदलते हैं
outage["Outage"] --> ups["UPS battery पर"]
ups --> pbt["PBT_APMPOWERSTATUSCHANGE"]
pbt --> check["GetSystemPowerStatus"]
check --> saveop["रोकें और save करें"]
saveop --> req["Shutdown request"]
req --> normal["सामान्य notification flow(3 से 6)"]
चित्र 13: Outage UPS को battery पर switch करे तो PBT_APMPOWERSTATUSCHANGE सूचित होता है, power स्थिति जाँची जाती है, और save प्लस shutdown request बिना notification power loss को notification वाले नियोजित shutdown में बदलते हैं।
विशिष्ट USB-जुड़ा UPS Windows को battery दिखता है, इसलिए इस standard API से पकड़ सकते हैं। यदि vendor management software में “N% शेष पर OS shutdown” सुविधा हो, यह भी जाँचें कि सीमा ऐप के cleanup समय से मेल खाती है। Sleep या hibernation से resume, और लंबे समय चलने वाले मुद्दे, अलग अक्ष हैं, “Sleep, hibernation, Modern Standby, और लंबे समय चलने वाले ऐप” में।
9. कैसे verify करें — shutdown सुरक्षित आज़माना
Shutdown handling “लिख दिया पर production-समान स्थितियों में कभी नहीं आज़माया” बन जाती है। इसे सुरक्षित verify करने की प्रक्रिया रखें।
- Test machine या VM पर आज़माएँ: पहले production device PC पर न आज़माएँ। Hyper-V checkpoint (snapshot) वाले test वातावरण में shutdown, restart, और ज़बरदस्ती power loss (VM बंद करना) दोहराएँ। VM “power off”, पर, केवल “guest OS बिना notification रुकना” reproduce करता है; physical disk के अस्थिर cache या controller-dependent टूटन नहीं। यदि device PC के रूप में भेजें, अंतिम जाँच production-समान hardware पर वास्तविक बिजली-कट test है
- Sign-out से त्वरित जाँच: WM_QUERYENDSESSION → WM_ENDSESSION path sign-out पर भी चलता है (अंतर केवल lParam में ENDSESSION_LOGOFF bit), इसलिए development machine पर cleanup-code व्यवहार आसानी से पुष्टि कर सकते हैं1
- पूर्ण shutdown और hybrid अलग आज़माएँ:
shutdown /s /t 0(पूर्ण),shutdown /s /hybrid /t 0(default व्यवहार), औरshutdown /r /t 0(restart) प्रत्येक आज़माएँ2 - Cleanup कितना समय लेता है मापें: Cleanup function के प्रारंभ और अंत पर log में timestamp लिखें, और मापें कि 5 सेकंड (या service की configure grace period) में समाता है या नहीं
flowchart TB
accTitle: Verify करने योग्य क्रियाएँ और प्रत्येक क्या पुष्टि कर सकता है
accDescr: Sign-out notification path की सुविधाजनक जाँच है; shutdown-आदेश पूर्ण, hybrid और restart production notification path और grace period पुष्टि करते हैं; VM power-off अचानक-रुक लचीलापन जाँचता है; physical बिजली-कट अंतिम जाँच है जिसमें physical storage शामिल
signtest["Sign-out"] -.-> path1["QUERY → ENDSESSION path"]
signtest --> shuttest["shutdown /s /hybrid /r"]
shuttest -.-> path2["Production path + grace period"]
shuttest --> vmtest["VM power-off"]
vmtest -.-> path3["Guest अचानक रुक"]
vmtest --> hwtest["Physical बिजली-कट"]
hwtest -.-> path4["Storage सहित(अंतिम)"]
चित्र 14: Sign-out notification path की सुविधाजनक जाँच है; shutdown-आदेश पूर्ण, hybrid और restart production notification path और grace period पुष्टि करते हैं; VM power-off अचानक-रुक लचीलापन जाँचता है; physical बिजली-कट अंतिम जाँच है जिसमें physical storage शामिल।
बाद के isolation के लिए event log (System) उपयोगी है। सामान्य shutdown या restart पर event ID 1074 (किस process ने shutdown शुरू किया, किसके लिए, और किस कारण) दर्ज होता है। अचानक power loss या crash पर 1074 नहीं होता, और अगले boot पर event ID 41 (Kernel-Power) और 6008 (पिछला सिस्टम shutdown अप्रत्याशित था) दर्ज होते हैं।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 द्वारा restart” दिखाए और ऐप का data टूटा हो, समस्या cleanup code है। 6008/41 केवल “अप्रत्याशित shutdown” दिखाते हैं; वे blue-screen (crash) या ज़बरदस्ती reset पर भी दर्ज होते हैं, केवल power loss पर नहीं। यदि 41 का BugcheckCode शून्येतर हो तो crash है; यदि 0 हो और memory dump भी न हो, power loss संभावित है — आसपास की जानकारी से कारण अलग करें, और जब पता चले power loss थी, chapter 8 का लेखन design और UPS अगला कदम हैं।
10. सारांश
- Shutdown “सामान्य घटना है जो देर-सबेर आएगी”। Notification के बाद grace period सिद्धांततः लगभग 5 सेकंड ही है, इसलिए पूर्वापेक्षा बार-बार autosave है ताकि “exit पर जो करें” न्यूनतम रहे।
- Windows 8 से आगे के client OS पर, यदि fast startup चालू हो, Shut down hybrid shutdown है और kernel केवल hibernate हो रहा है। पूर्ण reset केवल Restart है — घटना प्रक्रिया में Restart लिखें।
- GUI ऐप WM_QUERYENDSESSION पर तुरंत TRUE लौटाता है, और निश्चित cleanup WM_ENDSESSION में करता है। WinForms/WPF FormClosing और SessionEnding query चरण से मेल खाते हैं, इसलिए वहाँ अधिकतम idempotent snapshot save करें। Shutdown के दौरान dialog न दिखाएँ।
- जो काम सचमुच बीच में नहीं काटा जा सकता, ShutdownBlockReasonCreate से कारण दिखाकर सुरक्षित होता है। पर कहीं गारंटी नहीं कि block कर सकते हैं।
- Console ऐप notification SetConsoleCtrlHandler से पाता है; service SERVICE_ACCEPT_PRESHUTDOWN/SHUTDOWN से। वर्तमान OS पर default PRESHUTDOWN grace period 10 सेकंड है। .NET में ProcessExit पर निर्भरता छोड़कर ऐप model के मानक path पर जाएँ।
- Restart के बाद recovery RegisterApplicationRestart (प्लस recovery callback) और ARSO से बिना-उपस्थिति हो सकती है।
- Power loss कोई notification नहीं लाती। Temporary-फ़ाइल + ReplaceFile अदला-बदली (backup + load-समय जाँच के सेट के साथ), checkpoints पर flush, और UPS जो “power loss को नियोजित shutdown बनाए” से तैयारी करें।
flowchart TB
accTitle: Shutdown handling की समग्र तस्वीर
accDescr: Notification वाले अंत के लिए कुछ सेकंड में दुकान बंद कर सकने वाला cleanup और restart के बाद automatic recovery; बिना notification power loss के लिए जब भी कटे न टूटने वाला लेखन और UPS, physical hardware सहित verification। ये दो स्तंभ लेख का निष्कर्ष हैं
ending{"कैसे खत्म होता है"}
ending -->|"Notification के साथ"| pillar1["कुछ-सेकंड cleanup(3 से 6)"]
ending -->|"Notification नहीं"| pillar2["सुरक्षित लेखन + UPS(8)"]
pillar1 --> recover["Restart बाद स्वतः recovery(7)"]
pillar2 --> verifytest["Hardware पर verify(9)"]
चित्र 15: Notification वाले अंत के लिए कुछ सेकंड में दुकान बंद कर सकने वाला cleanup और restart के बाद automatic recovery; बिना notification power loss के लिए जब भी कटे न टूटने वाला लेखन और UPS, physical hardware सहित verification। ये दो स्तंभ लेख का निष्कर्ष हैं।
- VM और sign-out से सुरक्षित verify करें, और बाद में event ID 1074/41/6008 से अलग करें।
अगली बार ऐप में सुविधा जोड़ते स्वयं से एक बार पूछें: यदि इस काम के बीच WM_ENDSESSION आए, या बिजली खींच ली जाए, अगले launch पर क्या बचा है? उस उत्तर को design में लिखना device PC के सामने सुबह सिर पकड़कर खड़े न होने का सबसे छोटा path है।
संबंधित लेख
- उपयोग में exe या DLL कैसे बदलें — Restart Manager और automatic update में “File In Use” समस्या
- Windows services कैसे बनाएँ और चलाएँ ── Task Scheduler और services में चुनाव से BackgroundService को Windows service बनाना
- Sleep, hibernation, Modern Standby, और लंबे समय चलने वाले ऐप — ‘रात भर रुक गया’ के इर्द-गिर्द design
- Windows I/O की गहराई(भाग 4)— Cache Manager: आपका WriteFile वास्तव में disk तक कब पहुँचता है?
- Crash पर logs और dumps छोड़ने वाले Windows ऐप design करना
- Windows ऐप में child processes को सुरक्षित संभालने की जाँच सूची
संबंधित consulting क्षेत्र
KomuraSoft LLC device-PC और लंबे समय चलने वाले ऐप के लिए shutdown और power-loss उपायों का design व implementation, Windows Update restart या sign-out से शुरू data corruption और “सुबह तक रुक चुका था” घटनाओं की root-cause investigation, और Windows service stop processing व automatic recovery की design review संभालता है। “हर shutdown पर कुछ टूटता लगता है, और पता नहीं कहाँ से शुरू करें” चरण से शुरू करना ठीक है।
संदर्भ लिंक
-
Microsoft Learn, WM_QUERYENDSESSION message. यह कि WM_QUERYENDSESSION session समाप्ति पर भेजा जाता है और ऐप को TRUE लौटाकर user के इरादे का सम्मान करना चाहिए (DefWindowProc का default भी TRUE है); कि cleanup WM_ENDSESSION तक टालना चाहिए; कि 5 सेकंड बाद सिस्टम shutdown रोकने वाले ऐप के लिए UI दिखाता है और user ज़बरदस्ती terminate कर सकता है; lParam में ENDSESSION_LOGOFF/CLOSEAPP/CRITICAL bits का अर्थ; कि shutdown और restart अलग नहीं बताए जा सकते; और कि data बार-बार save करना चाहिए ताकि exit पर कम save करना पड़े। ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7
-
Microsoft Learn, Fast startup causes hibernation or shutdown to fail in Windows 10 or Windows 8.1. यह कि fast startup पर kernel session बंद नहीं होता और hibernation माना जाता है, और kernel व device-driver state hiberfil.sys में सहेजी जाती है; कि “Restart” हमेशा पूर्ण boot करता है क्योंकि पूरी तरह नई Windows state चाहिए; कि fast startup default चालू है और बंद करना recommended नहीं; और कि Shutdown.exe का default पूर्ण shutdown है, /hybrid option hybrid व्यवहार देता है। ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, ShutdownBlockReasonCreate function (winuser.h). यह कि uninterruptible काम शुरू होने पर कारण string register करने के लिए call करें और खत्म होने पर ShutdownBlockReasonDestroy call करें; कि इसे केवल उस thread से call कर सकते हैं जिसने window बनाई; और कि user कारण कुछ सेकंड ही पढ़ेगा, इसलिए string छोटी और स्पष्ट हो। ↩ ↩2 ↩3
-
Microsoft Learn, Shutdown Changes for Windows Vista. यह कि WM_QUERYENDSESSION/WM_ENDSESSION का उत्तर प्रत्येक पर 5 सेकंड delayed हो सकता है और तब user जारी या cancel चुन सकता है; कि console ऐप या बिना दिखाई window वाला ऐप shutdown निरस्त नहीं कर सकता और 5 सेकंड बिना उत्तर या FALSE उत्तर पर स्वचालित terminate होता है; कि block चाहिए तो ShutdownBlockReasonCreate से कारण register करना चाहिए; और कि ऐप को shutdown block कर सकने पर निर्भर नहीं रहना चाहिए। ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, HandlerRoutine callback function. SetConsoleCtrlHandler से register handler द्वारा प्राप्त CTRL_C/BREAK/CLOSE/LOGOFF/SHUTDOWN events; कि CTRL_CLOSE_EVENT का default timeout लगभग 5000 milliseconds और service process पर CTRL_SHUTDOWN_EVENT लगभग 20000 milliseconds है; कि CTRL_LOGOFF/SHUTDOWN_EVENT मूलतः केवल services पाती हैं क्योंकि interactive ऐप logoff पर terminate होता है; और कि handler अलग thread पर चलता है। ↩ ↩2 ↩3
-
Microsoft Learn, SetConsoleCtrlHandler function. यह कि gdi32.dll या user32.dll load करने वाली process Windows ऐप मानी जाती है और CTRL_LOGOFF_EVENT/CTRL_SHUTDOWN_EVENT handlers नहीं बुलाए जाते; कि समाधान छिपी window बनाकर WM_QUERYENDSESSION/WM_ENDSESSION संभालना है; और कि signal handling के दौरान console functions सही काम न करें। ↩ ↩2
-
Microsoft Learn, .NET runtime no longer provides default termination signal handlers. यह कि .NET 10 से runtime Windows CTRL_SHUTDOWN_EVENT/CTRL_CLOSE_EVENT (Unix SIGTERM/SIGHUP समकक्ष) का default handler नहीं देता; कि OS default handling ऐप तुरंत terminate करती है और AppDomain.ProcessExit व AssemblyLoadContext.Unloading नहीं चलते; और कि ऐप model के अनुकूल signal handling high-level library या ऐप code में register करनी चाहिए। ↩ ↩2
-
Microsoft Learn, Service Control Handler Function. यह कि SERVICE_ACCEPT_PRESHUTDOWN घोषित service पहले SERVICE_CONTROL_PRESHUTDOWN पाती है, फिर SERVICE_ACCEPT_SHUTDOWN service SERVICE_CONTROL_SHUTDOWN; कि shutdown पर default grace period लगभग 20 सेकंड और OS restart पर छत WaitToKillServiceTimeout है; कि यह मान नहीं बढ़ाना चाहिए; कि control handler 30 सेकंड में लौटे, STOP_PENDING और wait hint report करे, और लंबा काम दूसरे thread पर छोड़े; कि UPS operations ध्यान में रखकर cleanup जितना जल्दी हो खत्म हो; और कि SCM shutdown पर default से dependencies नहीं देखता। ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, SERVICE_PRESHUTDOWN_INFO structure (winsvc.h). यह कि PRESHUTDOWN notification के बाद SCM service रुकने या timeout तक wait करता है; कि default timeout Windows 10 Creators Update (build 15063) से 10 सेकंड और उससे पहले 3 मिनट है; कि ChangeServiceConfig2 से configure होता है; और कि SERVICE_STOP_PENDING के दौरान स्थिति update जारी रह सकती है। ↩ ↩2
-
Microsoft Learn, RegisterApplicationRestart function (winbase.h). यह कि crash, unresponsive, update, और update के साथ computer restart के लिए restart register हो सकता है; कि restart के command-line arguments specify हो सकते हैं; कि registration समस्या से पहले होना चाहिए और update परिदृश्य में WM_QUERYENDSESSION handling अंतिम मौका है; कि 60 सेकंड से कम runtime process restart नहीं होती; कि crash या hang के बाद restart user consent से जाता है; और कि OS restart पार करने के लिए EWX_RESTARTAPPS/SHUTDOWN_RESTARTAPPS वाला shutdown चाहिए। ↩ ↩2 ↩3
-
Microsoft Learn, Winlogon automatic restart sign-on (ARSO). यह कि Windows Update automatic restart शुरू करे तो अंतिम interactive user की credentials सहेजता है और Autologon configure करता है; कि restart के बाद user को automatic sign-in कर session lock करता है; कि सफल sign-in के बाद सहेजे credentials हटते हैं; और कि Group Policy (DisableAutomaticRestartSignOn आदि) से configure हो सकता है। ↩ ↩2
-
Microsoft Learn, ReplaceFileW function (winbase.h). यह कि ReplaceFile “नई फ़ाइल में save, original का temporary नाम, नई फ़ाइल का नाम, original हटाना” के समकक्ष multi step एक function में पैक करता है; कि original फ़ाइल के creation time, DACL, encryption, compression और named streams जैसे गुण सुरक्षित रखता है; और कि backup, बदली जा रही फ़ाइल, और replacement फ़ाइल उसी volume पर होनी चाहिए। ↩ ↩2
-
Microsoft Learn, File Caching. यह कि लेखन default से सिस्टम cache पर जाते हैं और lazy write से disk पर प्रतिबिंबित होते हैं; कि FILE_FLAG_WRITE_THROUGH तुरंत disk पर लिखता है; कि FlushFileBuffers स्पष्ट flush कर सकता है; और कि file-system metadata हमेशा cache होता है, इसलिए metadata पुष्टि को flush या write-through चाहिए। ↩ ↩2 ↩3
-
Microsoft Learn, Troubleshoot unexpected reboots using system event logs. यह कि सामान्य restart event ID 1074 दर्ज करता है (किस process ने shutdown शुरू किया, किसके लिए, किस कारण); कि अप्रत्याशित restart event ID 41 (Kernel-Power) और 6008 दर्ज करता है; और कि ये IDs restart का प्रकार अलग कर सकते हैं। ↩ ↩2
-
Microsoft Learn, PBT_APMPOWERSTATUSCHANGE event. यह कि यह event battery और AC के बीच switch या शेष क्षमता गिरने पर WM_POWERBROADCAST से सूचित होता है; और कि प्राप्ति पर GetSystemPowerStatus call कर ACLineStatus, BatteryFlag, और BatteryLifePercent जैसे SYSTEM_POWER_STATUS fields जाँचने चाहिए। ↩
संबंधित लेख
निकटवर्ती विषयों में गहराई से जाने के लिए समान टैग वाले नवीनतम लेख।
Win32 Thread Pool API — CreateThreadpoolWork से thread बनाए बिना concurrency
क्या आपके native code में CreateThread calls बिखरी पड़ी हैं? यह लेख Vista में redesign की गई Win32 thread pool API — work, timer, wait और...
Named Pipes व्यवहार में — design से security तक, Windows की standard IPC
Named pipes — Windows की standard inter-process communication — की practical guide। यह लेख primary sources से byte और message mode का चुन...
Sleep से resume पर टूटने वाले apps — Windows power events कैसे काम करते हैं और उनसे बचने वाले business apps कैसे बनाएँ
Laptop खोला और business app के connections मर चुके थे — कारण वह design है जिसने sleep का हिसाब ही नहीं रखा। यह लेख WM_POWERBROADCAST noti...
DllMain और Loader Lock — DLL initialization में "कुछ मत करो" कहा जाने का असली कारण
DllMain से LoadLibrary क्यों न call करें और दूसरे thread से synchronize न करें। Primary sources से यह लेख बताता है कि loader lock हर DLL ...
"Not Responding" वास्तव में क्या है — Windows ऐप के hang का फैसला कैसे करता है, और hang न करने वाले ऐप कैसे design करें
Windows का "Not Responding" वह mechanism है जिसमें OS तय करता है कि window ने 5 सेकंड message नहीं लिया और उसे ghost window से बदल देता ह...
संबंधित विषय
ये पृष्ठ विषय को सेवाओं और निर्णयों के व्यापक संदर्भ में रखते हैं।
Windows के तकनीकी विषय
Windows विकास, बग जाँच और मौजूदा संपत्तियों के उपयोग का प्रवेश-द्वार।
इस विषय से जुड़ी सेवाएँ
यह लेख निम्नलिखित सेवाओं से सीधे जुड़ा है।
Windows ऐप विकास
व्यावसायिक ऐप, डिवाइस एकीकरण और संचार उपकरण, आवश्यकताओं से विकास तक।
अक्सर पूछे जाने वाले प्रश्न
इस लेख के विषय पर परामर्श में अक्सर पूछे जाने वाले प्रश्न।
- जो समस्या "Shut down" के बाद नहीं गई, "Restart" के बाद चली गई। क्यों?
- Windows 8 से आगे के client OS पर, जब fast startup चालू हो (hibernation समर्थित अधिकांश PC पर default), "Shut down" hybrid shutdown नामक mechanism इस्तेमाल करता है। User sign-out होता है, पर kernel और driver state hibernation फ़ाइल में सहेजी जाती है और अगले boot पर ज्यों-की-त्यों लौटती है। यानी OS का core reset नहीं हुआ। इसके विपरीत "Restart" हमेशा पूर्ण boot करता है, इसलिए driver और service की समस्या reset होती है। Isolation प्रक्रिया में "Restart" लिखें, "Shut down करके फिर चालू करें" नहीं। Command line से पूर्ण shutdown चाहिए तो shutdown /s इस्तेमाल कर सकते हैं।
- क्या ऐप save खत्म करे तब तक shutdown रोक सकता हूँ?
- अस्थायी wait माँग सकते हैं, पर भरोसे से रोक नहीं सकते। यदि केवल उस समय ShutdownBlockReasonCreate से कारण string register करें जब uninterruptible काम चल रहा हो, वह कारण "यह ऐप shutdown रोक रहा है" screen पर दिखता है और user जारी रखने या cancel करने का निर्णय ले सकता है। फिर भी user ज़बरदस्ती जारी रख सकता है, और ज़बरदस्ती shutdown या update-driven restart बिल्कुल wait न करे। सही रास्ता इसलिए "block" नहीं, बल्कि बार-बार autosave ताकि जोखिम में कम data रहे, साथ exit notification से कुछ सेकंड में खत्म होने वाला cleanup है।
- मेरी Windows service रोकने में लंबा समय लगता है। क्या shutdown grace period बढ़ा सकता हूँ?
- SERVICE_CONTROL_SHUTDOWN पाने वाली default setting में grace period लगभग 20 सेकंड है और WaitToKillServiceTimeout registry मान पर निर्भर करती है। उसे ऐप पक्ष से बढ़ाकर लिखना recommended नहीं। लंबी grace period चाहिए तो SERVICE_ACCEPT_PRESHUTDOWN घोषित कर SERVICE_CONTROL_PRESHUTDOWN पा सकते हैं; आप दूसरों से पहले सूचित होते हैं, और timeout ChangeServiceConfig2 से set हो सकता है (default Windows 10 Creators Update से 10 सेकंड, उससे पहले 3 मिनट)। पर PRESHUTDOWN उस अंतराल पूरे shutdown को रोकता है, इसलिए केवल सचमुच ज़रूरी मामलों तक सीमित रखें, और मूल रूप से stop-काम को कुछ सेकंड में खत्म design करें।
- .NET के AppDomain.ProcessExit में shutdown cleanup सुरक्षित है?
- इस पर निर्भर न करने की सलाह है। ऐतिहासिक रूप से runtime default signal handler register करता था, और CTRL_CLOSE_EVENT व CTRL_SHUTDOWN_EVENT पर ProcessExit चलता था, पर .NET 10 से runtime default termination-signal handler नहीं देता, और उन मामलों में ProcessExit नहीं चलता। Cleanup उस notification path पर लागू करें जो ऐप model से मेल खाए: GUI ऐप FormClosing या SessionEnding इस्तेमाल करें (वे query-चरण notifications हैं, इसलिए उन्हें idempotent save तक सीमित रखें; जो cleanup केवल session निश्चित होने के बाद चल सकता है वह WM_ENDSESSION hook में हो); Generic Host / Worker Service IHostApplicationLifetime और StopAsync इस्तेमाल करें; console ऐप SetConsoleCtrlHandler या PosixSignalRegistration इस्तेमाल करें।
- अचानक बिजली कटने से फ़ाइलें खराब होने से कैसे बचाऊँ?
- Power loss कोई notification नहीं लाती, इसलिए एकमात्र विकल्प ऐसे लिखना है जो बिजली जब भी कटे टूटे नहीं। आधार यह है कि original फ़ाइल को उसी जगह overwrite न करें: उसी volume पर temporary फ़ाइल में पूरा लिखें, flush करें, और ReplaceFile (.NET में File.Replace) से अदला-बदली करें। सामान्य काम में इससे या पूरी पुरानी फ़ाइल या पूरी नई फ़ाइल पढ़ सकते हैं, पर बिजली कटने पर ReplaceFile की atomicity spec से गारंटी नहीं, इसलिए backup (तीसरा argument) रखें और load-समय recovery लागू करें जो primary फ़ाइल जाँचे और टूटी हो तो backup पर जाए। साथ ही, WriteFile की सफलता का अर्थ data disk तक पहुँचना नहीं, इसलिए महत्वपूर्ण checkpoints पर FlushFileBuffers या FILE_FLAG_WRITE_THROUGH से लेखन पुष्टि करें। Device PC पर मानक setup इसे UPS से जोड़ना, battery switch पकड़ना, और सुरक्षित shutdown तक ले जाना है।