كيفية استخدام SetConsoleHandler() لمنع مكالمات الخروج

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

  •  22-08-2019
  •  | 
  •  

سؤال

وأنا أعلم أنه لا بد لي من استخدام setconsolehandler() إذا كنت أرغب في إدارة أحداث إغلاق وحدة التحكم.

أنا لا أعرف كيفية منع CTRL_CLOSE_EVENT.لقد حاولت إرجاع خطأ/صحيح إذا اكتشف هذا الحدث، لكن لم أنجح

هذا ما لدي حتى الآن (شكرًا لك أنطون جوجوليف!)

[DllImport("Kernel32")]
public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add);

public delegate bool HandlerRoutine(CtrlTypes CtrlType);

public enum CtrlTypes{
    CTRL_C_EVENT = 0,
    CTRL_BREAK_EVENT,
    CTRL_CLOSE_EVENT,
    CTRL_LOGOFF_EVENT = 5,
    CTRL_SHUTDOWN_EVENT
}

private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
{ 
    if(ctrlType == CtrlTypes.CTRL_CLOSE_EVENT)
        return false;// I have tried true and false and viceversa with the return   
                     // true/false but I cant seem to get it right.
    return true;
}


//and then I use this to call it
SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);

هل من الممكن أيضًا تشغيل مؤشر ترابط جديد لمراقبة ما إذا كانت وحدة التحكم تغلق وحظر هذا الإغلاق إذا كان الخيط الرئيسي في منتصف القيام بشيء ما؟

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

المحلول

وثائق SetConsoleCtrlHandler() تقول:

<اقتباس فقرة>   

وهذا النظام يولد CTRL_CLOSE_EVENT، CTRL_LOGOFF_EVENT، والإشارات CTRL_SHUTDOWN_EVENT عندما يغلق المستخدم وحدة التحكم، بتسجيل الخروج، أو إيقاف النظام بحيث أن عملية ديها فرصة لتنظيف قبل الإنهاء.

وهذا يعني أنه على عكس عند التعامل مع CTRL + C أو CTRL + BREAK الأحداث، العملية الخاصة بك لا تحصل على فرصة لإلغاء وثيقة، تسجيل الخروج، أو إيقاف.

نصائح أخرى

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

إذا كنت في حاجة حقا لبدء موضوع، هل يمكن استخدام حالة الانتظار (AutoResetEvent في C #) والبدء في الخيط الخاص بك (على الرغم موضوع جديد ربما ليست هناك حاجة في معظم الحالات) ثم يخطر حالة الانتظار عندما موضوع الخاص بك هو تم الانتهاء من. ومع ذلك، فقط القيام بأي تنظيف في معالج يكفي في معظم الحالات.

إذا في أسوأ حال كنت لم الانتظار إلى الأبد، وسوف تظل عملية التشغيل وعليك أن تكون قادرا على رؤية ذلك عند تسجيل الدخول مرة أخرى (على الأقل على نظام التشغيل Windows XP). ومع ذلك، وهذا يتسبب في سطح المكتب إلى وقفة لنحو 20 ثانية قبل الذهاب إلى الشاشة تسجيل الخروج (في حين ينتظر applicaiton الخاص للخروج)، ثم توقف مرة أخرى في شاشة تسجيل الخروج (افترض بينما كان يحاول ل2nd الوقت) . بالطبع، أنصح بشدة ضد انتظار إلى الأبد. لأي الاشياء منذ فترة طويلة يجب عليك ان تضع هذا حقا في الخدمة.

لقد وجدت "اختراقًا" محتملاً يمكن أن يمنع التطبيق من الإغلاق، مع الاستمرار في الالتزام بدقة بطلب إغلاق وحدة التحكم.أعتقد أن هذا مناسب بشكل خاص لتطبيقات واجهة المستخدم الرسومية التي أنشأت وحدة تحكم باعتبارها "إضافية".من وثائق MSDN، عند النقطة التي يُسمى فيها معالج Ctrl بـ موضوع جديد يتم إنشاؤه في عملية استدعاء المعالج.الحل الذي أقترحه هو إيقاف الخيط الغازي المهاجم قبل أن يتمكن المعالج الافتراضي من استدعاء ExitProcess.في روتين المعالج (الكود في C++):

// Detach Console:
FreeConsole();
// Prevent closing:
ExitThread(0);
return TRUE; // Not reached

يحرر: يبدو أن هذا يسبب بعض المشكلات، كما هو متوقع على ما أعتقد.يتم تعليق استدعاء لاحق لـ AllocConsole() إلى أجل غير مسمى، لذا أظن أن الخروج من مؤشر الترابط قبل الأوان يفشل في التنظيف بشكل صحيح.

تحرير 2:

للتوضيح أعلاه، لم أجد أية مشكلات مباشرة تتعلق بالاستمرار في تشغيل البرنامج.لكن ضع في اعتبارك أننا قمنا بإنهاء سلسلة رسائل أنشأها kernel32 بالقوة، لذلك قد تكون أي موارد داخل kernel32 في حالة غير محددة.قد يتسبب هذا في حدوث مشكلات غير متوقعة عند استمرار تشغيل البرنامج.

أعتقد أن هذه المشكلات ستكون في الغالب مرتبطة بواجهة برمجة تطبيقات وحدة التحكم.كما ذكر، AllocConsole فشل في العمل من هذه النقطة فصاعدا (سوف يتعطل التطبيق)، لذلك لا يمكن للبرنامج فتح وحدة تحكم جديدة.من المحتمل جدًا أن تفشل وظائف وحدة التحكم الأخرى أيضًا.في الأساس، أي شيء تفعله من تلك النقطة فصاعدًا والذي يستدعي kernel32 بأي شكل من الأشكال (بشكل مباشر أو غير مباشر) يخضع لسلوك غير محدد، لكنني أظن أنه لن تكون هناك أي مشكلات في الممارسة العملية خارج وظائف وحدة التحكم.

استنتاجي هو أنه يجب عليك تجنب هذه الطريقة إذا كان ذلك ممكنًا، ولكن إذا كان الإنهاء المبكر أسوأ، فيمكن اعتبار ذلك بمثابة حل طارئ، يجب استخدامه بشكل مقتصد وبعناية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top