2009-06-11 27 views
14

को बंद या फिर से शुरू कर रहा है, मुझे पता है कि जब विंडोज बंद हो रहा है, तो यह प्रत्येक एप्लिकेशन को WM_QUERYENDSESSION संदेश भेजता है। विंडोज़ बंद होने पर यह पता लगाना आसान बनाता है। हालांकि, क्या यह जानना संभव है कि कंप्यूटर पावर-ऑफ पर जा रहा है या विंडोज़ बंद होने के बाद इसे पुनरारंभ करना है या नहीं।यह पता लगाने के लिए कि विंडोज

मैं विशेष रूप से आशावादी नहीं हूं, एमएसडीएन में प्रलेखन के बारे में यह कहना है कि WM_QUERYENDSESSION: "... यह निर्धारित करना संभव नहीं है कि कौन सी घटना हो रही है," लेकिन स्टैक ओवरफ्लो की संचयी चतुरता कभी मुझे आश्चर्यचकित नहीं करती है।

उत्तर

5
here से

:

आप निर्धारित करने के लिए "\ एक्सप्लोरर \ शटडाउन सेटिंग HKCU \ Software \ Microsoft \ Windows \ CurrentVersion" से DWORD मान पढ़ सकते हैं क्या उपयोगकर्ता पिछले शट डाउन से चयनित संवाद।

एक चौराहे समाधान का थोड़ा सा, लेकिन यह चाल करना चाहिए।

+11

यह निश्चित रूप से माना जाता है कि सिस्टम अब बंद हो रहा है क्योंकि वर्तमान उपयोगकर्ता ने इसे शुरू किया है, और एक्सप्लोरर में ऐसा किया है। यदि यह एक प्रोग्रामेटिक शट डाउन है, किसी अन्य ऐप से शट डाउन है, या किसी अन्य उपयोगकर्ता द्वारा शटडाउन है, तो आपको पिछले शटडाउन का कारण मिल जाएगा। – MSalters

+5

-1 क्योंकि उत्तर अधूरा और विंडोज एक्सप्लोरर के लिए विशिष्ट है। यह विंडोज 7 में ** हटाया गया ** प्रतीत होता है। – unixman83

+1

यह विंडोजएक्सपी के तहत अच्छी तरह से काम करता है लेकिन एपीआई हुकिंग सुझाव के लिए विंडोज 7 – conceptacid

5

आमतौर पर काम करने वाली एक चाल WM_ENDSESSION को फँसाना और इसे लॉग करना है। अब समय का ट्रैक रखें। अगर प्रणाली उचित अवधि के भीतर वापस आती है (5 मिनट कहें)। फिर वह एक रिबूट था, शटडाउन नहीं।

आइडिया: प्रणाली 5 मिनट के भीतर ऊपर वापस आता है, तो यह वास्तव में बात उपयोगकर्ता क्लिक किया 'शट डाउन' या 'रिबूट' करता है?

यदि आपको वास्तव में शटडाउन का पता लगाने की आवश्यकता है (और एकमात्र कारण मुझे लगता है कि आपको ऐसा करने की आवश्यकता होगी तो अगर आप एक शट डाउन रीबूट के बीच एक अस्पष्ट व्यवहार सॉफ्टवेयर अंतर के आधार पर हैं) तो आप API hooking की जांच कर सकते हैं ExitWindowsEx और संबंधित कार्यों लेकिन मैं इस दृष्टिकोण की सिफारिश नहीं करता हूं। यदि आपको वास्तव में इसे सीधे पहचानने की आवश्यकता है तो रीथिंक करें।

+1

+1 के तहत नहीं। समय की जांच सुझाव शुद्ध अनुमान है। –

+0

@ जो, आधुनिक एसीपीआई पावर प्रबंधन के साथ: नींद, हाइबरनेट, लैन पर वेक, और इसी तरह। रीबूट (या गर्म बूट) की परिभाषा परिभाषित करना मुश्किल हो रहा है। रीबूट (या पर्याप्त बंद) द्वारा अधिकांश लोगों का मतलब यह है कि प्रणाली एक सामान्य अवधि में बहुत कम समय के लिए नहीं थी। – unixman83

6

विंडोज 7 (और शायद विस्टा/8/सर्वर में भी) में आप सिस्टम इवेंट्स का उपयोग यह ट्रैक करने के लिए कर सकते हैं कि विंडोज बंद हो रहा है या कंप्यूटर बंद कर रहा है या फिर पुनरारंभ करना है। हर बार शट डाउन/रीबूट शुरू किया जाता है (किसी भी माध्यम से - स्टार्ट मेनू में बटन पर क्लिक करके, या प्रोग्रामेटिक रूप से), विंडोज 7 सिस्टम लॉग, स्रोत USER32, इवेंट आईडी 1074 में एक या दो घटनाएं लिखता है। आप इन घटनाओं को रिकॉर्ड कर सकते हैं यदि आप आप इवेंट व्यूअर को व्यवस्थापकीय उपकरण से खोलते हैं (केवल सिस्टम आईडी को देखने के लिए सिस्टम लॉग फ़िल्टर करें)। इन घटनाओं के विवरण (संदेश) में शटडाउन प्रकार शामिल है। तो आप आवश्यक शब्द (शट डाउन, रीबूट/रीस्टार्ट) की तलाश में, इस प्रकार की सबसे हाल की घटना (शटडाउन शुरू करने के बाद) के वर्णन को पार्स कर सकते हैं।

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

विंडोज एक्सपी में, मेरे अनुभव से, एक ईवेंट 1074 केवल तभी दर्ज किया जाता है जब शट डाउन/रीबूट प्रोग्रामेटिक रूप से किया जाता है (उदाहरण के लिए प्रोग्राम इंस्टॉल या शटडाउन.एक्सई यूटिलिटी का उपयोग करके)। इसलिए यह खोल (एक्सप्लोरर) से शुरू किए गए शटडाउन को पंजीकृत नहीं करता है, लेकिन शायद आप इस विधि को किसी अन्य उत्तर में प्रस्तावित रजिस्ट्री से मूल्य पढ़ने के साथ जोड़ सकते हैं। साथ ही, ध्यान रखें कि WinXP में इवेंट 1074 के संदेश में "रीस्टार्ट" शब्द शामिल है, इससे कोई फर्क नहीं पड़ता कि वास्तविक प्रकार का शटडाउन क्या है, इसलिए आपको "शट डाउन टाइप:" फ़ील्ड देखना चाहिए, जो या तो "शटडाउन" या "रिबूट"।

इससे संबंधित, जब भी किसी कारण से विंडोज़ बंद/रीबूट करने में विफल रहता है तो एक इवेंट आईडी 1073 रिकॉर्ड किया जाता है (उदाहरण के लिए यदि कोई एप्लिकेशन WM_QUERYENDSESSION के जवाब के रूप में बंद करने की अनुमति नहीं देता है)। उस मामले में संदेश में WinXP में "शटडाउन", "रीबूट" या "पावर ऑफ" के रूप में शब्द भी शामिल होंगे। Win7 के लिए इस मामले की घटना हमारे मामले में कम उपयोगी है, क्योंकि इससे शट डाउन और रीबूट के बीच कोई फर्क नहीं पड़ता है। लेकिन WinXP के लिए - यदि आपको केवल शट डाउन/रीबूट को रोकने की आवश्यकता है, तो कुछ क्रियाएं करें, फिर संबंधित शट डाउन या रीबूट प्रक्रिया जारी रखें - इसे अपेक्षा के अनुसार काम करना चाहिए।

+1

यह ध्यान रखना महत्वपूर्ण है कि EventLog स्थानीय संदेश दिखाता है ताकि ऑपरेटिंग सिस्टम स्थानीयकरण के आधार पर "शटडाउन" या "रीबूट" जैसे कीवर्ड अलग-अलग हों। – tpx86

1

विंडोज 7 के लिए संभावित प्रयोगात्मक समाधान निम्न हो सकता है। (मुझे यकीन है कि अगर यह अन्य स्थानीयकरणों के साथ अच्छी तरह से काम करता है नहीं कर रहा हूँ, इसलिए मैं इसे एक समाधान कहेंगे)

using System.Diagnostics.Eventing.Reader; 

namespace MyApp 
{ 
public class RestartDetector : IDisposable 
{ 
    public delegate void OnShutdownRequsted(bool restart); 
    public OnShutdownRequsted onShutdownRequsted; 

    private EventLogWatcher watcher = null; 

    public RestartDetector() 
    { 
     try 
     { 
      EventLogQuery subscriptionQuery = new EventLogQuery(
       "System", PathType.LogName, "*[System[Provider[@Name='USER32'] and (EventID=1074)]]"); 

      watcher = new EventLogWatcher(subscriptionQuery); 

      // Make the watcher listen to the EventRecordWritten 
      // events. When this event happens, the callback method 
      // (EventLogEventRead) is called. 
      watcher.EventRecordWritten += 
       new EventHandler<EventRecordWrittenEventArgs>(
        EventLogEventRead); 

      // Activate the subscription 
      watcher.Enabled = true; 
     } 
     catch (EventLogReadingException e) 
     { 
     } 
    } 

    public void EventLogEventRead(object obj, EventRecordWrittenEventArgs arg) 
    { 
     bool restart = false; 
     try 
     { 
      // Make sure there was no error reading the event. 
      if (arg.EventRecord != null) 
      { 
       String[] xPathRefs = new String[1]; 
       xPathRefs[0] = "Event/EventData/Data"; 
       IEnumerable<String> xPathEnum = xPathRefs; 

       EventLogPropertySelector logPropertyContext = new EventLogPropertySelector(xPathEnum); 
       IList<object> logEventProps = ((EventLogRecord)arg.EventRecord).GetPropertyValues(logPropertyContext); 

       string[] eventData = (string[])logEventProps[0]; 

       foreach (string attribute in eventData) 
       { 
        if (attribute.Contains("restart")) { restart = true; break; } 
       } 
      } 
     } 
     catch (Exception e) 
     { 
     } 
     finally 
     { 
      if (onShutdownRequsted != null) { onShutdownRequsted(restart); } 
     } 
    } 

    public void Dispose() 
    { 
     // Stop listening to events 
     if (watcher != null) 
     { 
      watcher.Enabled = false; 
      watcher.Dispose(); 
     } 
    } 
} 
} 

निम्न XML का एक उदाहरण है जो ईवेंट लॉग करने के लिए लिखा है जब एक पीसी पुनरारंभ है:

- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"> 
- <System> 
    <Provider Name="USER32" /> 
    <EventID Qualifiers="32768">1074</EventID> 
    <Level>4</Level> 
    <Task>0</Task> 
    <Keywords>0x80000000000000</Keywords> 
    <TimeCreated SystemTime="2015-12-15T11:10:43.000000000Z" /> 
    <EventRecordID>90416</EventRecordID> 
    <Channel>System</Channel> 
    <Computer>WIN7PC</Computer> 
    <Security UserID="S-1-5-21-1257383181-1549154685-2724014583-1000" /> 
    </System> 
- <EventData> 
    <Data>C:\Windows\system32\winlogon.exe (WIN7PC)</Data> 
    <Data>WIN7PC</Data> 
    <Data>No title for this reason could be found</Data> 
    <Data>0x500ff</Data> 
    <Data>restart</Data> 
    <Data /> 
    <Data>WIN7PC\WIN7PCUser</Data> 
<Binary>FF00050000000000000000000000000000000000000000000000000000000000</Binary> 
    </EventData> 
    </Event> 
संबंधित मुद्दे