كيفية اكتشاف ما إذا كان ويندوز هو إغلاق أو إعادة تشغيل

StackOverflow https://stackoverflow.com/questions/981306

سؤال

وأنا أعلم أنه عندما إيقاف Windows, يرسل WM_QUERYENDSESSION رسالة إلى كل تطبيق.هذا يجعل من السهل للكشف عن ويندوز عندما يتم إيقاف.ولكن هل من الممكن أن أعرف إذا كان الكمبيوتر الذهاب إلى انقطاع التيار الكهربائي أو بعد إعادة تشغيل Windows الاغلاق.

أنا لا سيما الأمل النظر في وثائق MSDN هذا القول عن WM_QUERYENDSESSION:"...ليس من الممكن تحديد أي حدث يحدث" ، ولكن التراكمي ذكاء ستاكوفيرفلوو لم يتوقف لتدهش لي.

هل كانت مفيدة؟

المحلول

من عند هنا:

يمكنك قراءة قيمة DWORD من إعداد "HKCU Software Software Windows Windows CurrentVersion Explorer إيقاف تشغيل" لتحديد آخر مستخدم آخر من مربع حوار إيقاف التشغيل.

قليلا من محلول دوار، ولكن يجب أن تفعل الخدعة.

نصائح أخرى

في نظام التشغيل Windows 7 (وربما أيضا في ويندوز فيستا / 8 / Server) هل يمكن استخدام نظام الأحداث لتتبع ما إذا كان إيقاف Windows (و إيقاف تشغيل الكمبيوتر) أو إعادة تشغيل.كل وقت إيقاف التشغيل/إعادة تشغيل الكمبيوتر يبدأ (بأي وسيلة - النقر على زر ابدأ أو برمجيا), ويندوز 7 يكتب واحد أو اثنين من الأحداث في سجل النظام ، المصدر USER32, معرف الحدث 1074.يمكنك أن ترى هذه الأحداث المسجلة إذا كنت فتح "عارض الأحداث" من "أدوات إدارية" (تصفية سجل النظام أن نرى فقط معرف 1074).وصف (رسالة) من هذه الأحداث يحتوي على اغلاق نوع.لذلك يمكن تحليل وصف آخر حدث من هذا النوع (بعد اغلاق شرع) ، وتبحث عن كلمة اللازمة (إيقاف التشغيل, إعادة التشغيل/إعادة التشغيل).

لم نحاول أن نرى اغلاق نوع مكتوب في الحدث عند استخدام زر الطاقة بأمان إيقاف التشغيل ويندوز (عادة تعطيل هذه الوظيفة) ، ولكن بعض المواقع تشير إلى أن الدول "قوة من نوع" بدلا من "إيقاف التشغيل" - حتى التحقق من ذلك ، إذا كنت بحاجة إلى أن تكون على يقين.أو ببساطة البحث عن "إعادة تشغيل" نوع - إذا كان لم يتم العثور على ، ثم "إيقاف التشغيل" نوع هو المفترض.

في نظام التشغيل Windows XP من تجربتي الحدث 1074 يتم تسجيلها إلا إذا كان إيقاف التشغيل/إعادة التشغيل يتم ذلك برمجيا (مثلا ، خلال برنامج تثبيت أو استخدام shutdown.exe المنفعة).لذلك لا تسجيل إغلاق بدأت من قذيفة (Explorer) ، ولكن ربما يمكن الجمع بين هذا الأسلوب مع القراءة القيمة من التسجيل على النحو المقترح في جواب آخر.كما نضع في اعتبارنا أن في ويندوز إكس بي رسالة الحدث 1074 يحتوي على كلمة "إعادة تشغيل" لا يهم ما نوع حقيقي من الاغلاق ، لذلك يجب أن ننظر في "إغلاق نوع:" الحقل الذي سوف الدولة إما "إيقاف" أو "إعادة التشغيل".

ذات الصلة إلى هذا معرف الحدث 1073 هو مسجل كلما ويندوز يفشل في إيقاف التشغيل/إعادة التشغيل لسبب ما (مثلا ، إذا كان تطبيق لا تسمح إلى إيقاف استجابة WM_QUERYENDSESSION).في هذه الحالة الرسالة أيضا تحتوي على كلمات مثل "shutdown", "إعادة تشغيل" أو "إيقاف" في ويندوز إكس بي.For Win7 هذا النوع من الأحداث هو أقل فائدة في حالتنا ، لأنه لن يحدث أي فرق بين إيقاف تشغيل و إعادة التشغيل.ولكن لويندوز إكس بي - إذا كنت تحتاج فقط إلى اعتراض إيقاف التشغيل/إعادة التشغيل ، تنفيذ بعض الإجراءات ، ثم مواصلة المقابلة إيقاف تشغيل أو إعادة تشغيل العملية - يجب أن تعمل كما هو متوقع.

خدعة تعمل عادة هي فخ WM_ENDSESSION وقم بتسجيله. الآن تتبع الوقت. إذا ظهر النظام مرة أخرى ضمن بيروبر معقولة (قل 5 دقائق). ثم كان ذلك إعادة تشغيل، وليس إيقاف التشغيل.

فكرة: إذا ظهر النظام احتياطيا في غضون 5 دقائق، فهل ذلك هل حقا يهم إذا نقر المستخدم "إيقاف التشغيل" أو "إعادة التشغيل"؟

إذا كنت بحاجة فعلا إلى اكتشاف إيقاف التشغيل (والسبب الوحيد الذي أعتقد أنك بحاجة إلى القيام بذلك هو إذا كنت تبعا في اختلاف برامج سلوكي غامض بين إيقاف التشغيل مقابل إعادة التشغيل)، فيمكنك التحقيق API hooking من ExitWindowsEx والوظائف ذات الصلة ولكني لا أوصي بهذا النهج. إعادة التفكير إذا كنت بحاجة حقا للكشف عن هذا مباشرة.

يمكن أن يكون الحل التجريبي المحتمل لنظام التشغيل Windows7 ما يلي. (لست متأكدا مما إذا كان هذا يعمل بشكل جيد مع الترحيلات الأخرى، لذلك أود أن أسميها الحل

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>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top