كيفية إنهاء تطبيق "بوضوح" في Win32

ترجمات الموضوعات ترجمات الموضوعات
معرف المقالة: 178893 - عرض المنتجات التي تنطبق عليها هذه المقالة.
توسيع الكل | طي الكل

في هذه الصفحة

الموجز

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

معلومات أخرى

عمليات 32-بت (و 16 بت العمليات ضمن Windows 95)

ضمن Win32 ، promises نظام التشغيل لتنظيف الموارد المملوكة من قبل عملية عند ذلك إيقاف تشغيل. هذا لا ، على الرغم من ذلك، يعني تنته عملية نفسه الفرصة للقيام أي مسح النهائية من المعلومات إلى القرص أي اتصال النهائي عبر اتصال بعيد ولا يعني التي للعملية سيكون DLL الخاص الفرصة بتنفيذ تعليمات برمجية PROCESS_DETACH الخاصة بهم. هذا السبب أفضل بشكل عام تجنب إنهاء أحد تطبيقات ضمن Windows 95 و Windows NT.

إذا كان يجب حتماً إيقاف عملية ، اتبع الخطوات التالية:
  1. نشر WM_CLOSE إلى كافة الإطارات المستوى الأعلى المملوكة من قبل العملية التي تريد إيقاف تشغيل. تستجيب تطبيقات Windows العديد من هذه الرسالة عن طريق إيقاف تشغيل.

    ملاحظة: استجابة التطبيق وحدة التحكم WM_CLOSE يعتمد على ما إذا كان تم تثبيته معالج تحكم.

    استخدم EnumWindows() مقابض الإطارات الهدف. في الخاص بك وظيفة رد الاتصال مطابقة تحقق لمعرفة ما إذا كان الإطارات معالجة معرّف العملية التي تريد إيقاف تشغيل. يمكنك القيام بذلك عن طريق استدعاء GetWindowThreadProcessId(). بعد تأسيس "مطابقة" ، استخدم PostMessage() أو SendMessageTimeout() لنشر رسالة WM_CLOSE إلى الإطار.
  2. استخدم WaitForSingleObject() لانتظار مقبض العملية. تأكد من الانتظار مع قيمة مهلة بسبب وجود العديد من المواقف التي WM_CLOSE سوف لا يتم إيقاف التطبيق. تذكر لجعل المهلة طويلة بما يكفي (إما مع WaitForSingleObject() أو مع SendMessageTimeout()) بحيث يمكن لمستخدم الاستجابة إلى مربع الحوار أي خانات التي تم إنشاؤها في الاستجابة لرسالة WM_CLOSE.
  3. إذا كانت قيمة الإرجاع WAIT_OBJECT_0 ثم التطبيق إغلاق نفسه بوضوح. إذا كانت قيمة الإرجاع WAIT_TIMEOUT ثم يجب عليك استخدام TerminateProcess() إلى إيقاف تشغيل التطبيق.

    ملاحظة: إذا لم تكن getting3 إرجاع قيمة من WaitForSingleObject() الأخرى ثم WAIT_OBJECT_0 أو WAIT_TIMEOUT استخدام GetLastError() لتحديد السبب.
اتبع الخطوات التالية فإنك تعطي التطبيق فرصة المحتملة أفضل لإيقاف بوضوح (الحجم المتوفر والذي يقدر من IPC أو تدخل المستخدم).

المشاكل 16 بت (تحت Windows NT)

يسبق الخطوات العمل التطبيقات ذات 16 بت ضمن Windows 95, ومع ذلك، تعمل تطبيقات Windows NT 16-بت جداً بشكل مختلف.

تحت Windows NT أو تشغيل كافة التطبيقات ذات 16 بت في جهاز DOS ظاهري (VDM). يعمل هذا VDM كعملية Win32 (NTVDM) تحت Windows NT. فشلت عملية NTVDM إلى معرّف عملية. يمكنك الحصول على مؤشر إلى عملية عبر OpenProcess() ، مثلما الحال مع أي عملية Win32. وبالرغم من ، أي من تطبيقات 16 بت قيد التشغيل في VDM أن يكون لديك معرف عملية ثم ولذلك لا يمكنك الحصول على "معالجة المؤشر" من OpenProcess(). يحتوي كل تطبيق 16-بت في VDM المهام 16-بت "المؤشر" و 32-بت من مؤشر ترابط التنفيذ. يمكن العثور على معرف مؤشر مع مؤشر الترابط خلال استدعاء الدالة VDMEnumTaskWOWEx(). للحصول على مزيد من المعلومات، الرجاء مراجعة المقالة التالية في "قاعدة المعارف لـ Microsoft:
175030كيفية تعداد تطبيقات في Win32
الخيار الأول و الأكثر مباشرة عند إيقاف تشغيل تطبيقات ذات 16-بت تحت Windows NT إيقاف تشغيل عملية NTVDM بأكمله. يمكنك القيام بذلك عن طريق اتباع الخطوات الموضحة أعلاه. تحتاج إلى معرفته معرّف العملية للعملية NTVDM (راجع في KB المقالة 175030 المذكورة أعلاه للبحث عن معرف العملية من NTVDM). هو downside هذا الأسلوب أن أن يتم إغلاقه كافة تطبيقات 16 بت التي يتم تشغيلها في ذلك VDM. إذا لم يكن هذا الهدف ، فأنت بحاجة لاتخاذ أسلوب آخر.

إذا كنت ترغب في إيقاف تشغيل تطبيق 16-بت واحد ضمن عملية NTVDM فيما يلي الخطوات بحاجة لاتخاذ:
  1. نشر WM_CLOSE إلى كافة الإطارات المستوى الأعلى التي يملكها العملية و التي لها نفس المالك مؤشر ترابط المعرف المهمة 16 بت التي ترغب في إيقاف تشغيل. طريقة أكثر فعالية للقيام بذلك باستخدام EnumWindows(). في وظيفة "رد الاتصال" ، تحقق مما إذا كان معرّف العملية في الإطار ومعرّف مؤشر ترابط يطابق المهمة 16 بت التي ترغب في إيقاف تشغيل. تذكر الانتقال معرّف العملية أن يكون معرّف العملية للعملية NTVDM تطبيق 16-بت قيد التشغيل.
  2. على الرغم من أنه لديك معرف مؤشر ترابط لديك أية طريقة يمكن الانتظار في حالة إنهاء عملية 16-بت. نتيجة لذلك، التي يجب الانتظار لفترة إجبارية من الوقت (للسماح نظيف إيقاف تشغيل) وحاول إيقاف التطبيق على أية حال؟. إذا تم إيقاف التطبيق مسبقاً ، ثم هذا سوف نفذ أي شيء. إذا لم إيقاف تشغيله, ثم فإنه سيتم إنهاء التطبيق.
  3. إنهاء التطبيق الذي يستخدم استدعاء VDMTerminateTaskWOW() في Vdmdbg.dll دالة. يستغرق معرّف العملية في VDM ورقم المهمة مهمة 16 بت.
يعتبر هذا الأسلوب يتيح إمكانية إيقاف تشغيل تطبيق 16-بت واحد ضمن VDM تحت Windows NT. ومع ذلك، غير جيدة جدًا في تنظيف موارد المهمة أنهى Windows 16-بت وهو لا هذا ولا ذاك WOWExec قيد التشغيل في VDM. إذا كنت تبحث عن طريقة ممكنة cleanest إنهاء تطبيق 16-بت تحت Windows NT يجب إنهاء عملية VDM كاملة. ملاحظة: إذا تم تشغيل أحد تطبيقات 16 بت يمكنك إنهاء ثم استخدام CREATE_SEPARATE_WOW_VDM مع CreateProcess().

رمز نموذج

نموذج التعليمات البرمجية بتنفيذ التقنيات الموضح أعلاه 16-بت وتطبيقات 32-بت باستخدام الدالات التالية اثنين: TerminateApp() و Terminate16App(). TerminateApp() تأخذ معرف عملية 32-بت مهلة (في miliseconds). Terminate16App(). استخدم كلا الدالتين الارتباط صريح إلى دالات DLL بحيث تكون متوافقة الثنائية عبر Windows NT و Windows 95.
   //******************
   //Header
   //******************

   #include <windows.h>

   #define TA_FAILED 0
   #define TA_SUCCESS_CLEAN 1
   #define TA_SUCCESS_KILL 2
   #define TA_SUCCESS_16 3

   DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout ) ;
   DWORD WINAPI Terminate16App( DWORD dwPID, DWORD dwThread,
                        WORD w16Task, DWORD dwTimeout );

   //******************
   //Source
   //******************

   #include "TermApp.h"
   #include <vdmdbg.h>

   typedef struct
   {
      DWORD   dwID ;
      DWORD   dwThread ;
   } TERMINFO ;

   // Declare Callback Enum Functions.
   BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam ) ;

   BOOL CALLBACK Terminate16AppEnum( HWND hwnd, LPARAM lParam ) ;

   /*----------------------------------------------------------------
   DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout )

   Purpose:
      Shut down a 32-Bit Process (or 16-bit process under Windows 95)

   Parameters:
      dwPID
         Process ID of the process to shut down.

      dwTimeout
         Wait time in milliseconds before shutting down the process.

   Return Value:
      TA_FAILED - If the shutdown failed.
      TA_SUCCESS_CLEAN - If the process was shutdown using WM_CLOSE.
      TA_SUCCESS_KILL - if the process was shut down with
         TerminateProcess().
      NOTE:  See header for these defines.
   ----------------------------------------------------------------*/ 
   DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout )
   {
      HANDLE   hProc ;
      DWORD   dwRet ;

      // If we can't open the process with PROCESS_TERMINATE rights,
      // then we give up immediately.
      hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE,
         dwPID);

      if(hProc == NULL)
      {
         return TA_FAILED ;
      }

      // TerminateAppEnum() posts WM_CLOSE to all windows whose PID
      // matches your process's.
      EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM) dwPID) ;

      // Wait on the handle. If it signals, great. If it times out,
      // then you kill it.
      if(WaitForSingleObject(hProc, dwTimeout)!=WAIT_OBJECT_0)
         dwRet=(TerminateProcess(hProc,0)?TA_SUCCESS_KILL:TA_FAILED);
      else
         dwRet = TA_SUCCESS_CLEAN ;

      CloseHandle(hProc) ;

      return dwRet ;
   }

   /*----------------------------------------------------------------
   DWORD WINAPI Terminate16App( DWORD dwPID, DWORD dwThread,
                        WORD w16Task, DWORD dwTimeout )

   Purpose:
      Shut down a Win16 APP.

   Parameters:
      dwPID
         Process ID of the NTVDM in which the 16-bit application is
         running.

      dwThread
         Thread ID of the thread of execution for the 16-bit
         application.

      w16Task
         16-bit task handle for the application.

      dwTimeout
         Wait time in milliseconds before shutting down the task.

   Return Value:
      If successful, returns TA_SUCCESS_16
      If unsuccessful, returns TA_FAILED.
      NOTE:  These values are defined in the header for this
      function.

   NOTE:
      You can get the Win16 task and thread ID through the
      VDMEnumTaskWOW() or the VDMEnumTaskWOWEx() functions.
   ----------------------------------------------------------------*/ 
   DWORD WINAPI Terminate16App( DWORD dwPID, DWORD dwThread,
                        WORD w16Task, DWORD dwTimeout )
   {
      HINSTANCE      hInstLib ;
      TERMINFO      info ;

      // You will be calling the functions through explicit linking
      // so that this code will be binary compatible across
      // Win32 platforms.
      BOOL (WINAPI *lpfVDMTerminateTaskWOW)(DWORD dwProcessId,
         WORD htask) ;

      hInstLib = LoadLibraryA( "VDMDBG.DLL" ) ;
      if( hInstLib == NULL )
         return TA_FAILED ;

      // Get procedure addresses.
      lpfVDMTerminateTaskWOW = (BOOL (WINAPI *)(DWORD, WORD ))
         GetProcAddress( hInstLib, "VDMTerminateTaskWOW" ) ;

      if( lpfVDMTerminateTaskWOW == NULL )
      {
         FreeLibrary( hInstLib ) ;
         return TA_FAILED ;
      }

      // Post a WM_CLOSE to all windows that match the ID and the
      // thread.
      info.dwID = dwPID ;
      info.dwThread = dwThread ;
      EnumWindows((WNDENUMPROC)Terminate16AppEnum, (LPARAM) &info) ;

      // Wait.
      Sleep( dwTimeout ) ;

      // Then terminate.
      lpfVDMTerminateTaskWOW(dwPID, w16Task) ;

      FreeLibrary( hInstLib ) ;
      return TA_SUCCESS_16 ;
   }

   BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam )
   {
      DWORD dwID ;

      GetWindowThreadProcessId(hwnd, &dwID) ;

      if(dwID == (DWORD)lParam)
      {
         PostMessage(hwnd, WM_CLOSE, 0, 0) ;
      }

      return TRUE ;
   }

   BOOL CALLBACK Terminate16AppEnum( HWND hwnd, LPARAM lParam )
   {
      DWORD      dwID ;
      DWORD      dwThread ;
      TERMINFO   *termInfo ;

      termInfo = (TERMINFO *)lParam ;

      dwThread = GetWindowThreadProcessId(hwnd, &dwID) ;

      if(dwID == termInfo->dwID && termInfo->dwThread == dwThread )
      {
         PostMessage(hwnd, WM_CLOSE, 0, 0) ;
      }

      return TRUE ;
   }
				

الخصائص

معرف المقالة: 178893 - تاريخ آخر مراجعة: 25/جمادى الأولى/1425 - مراجعة: 2.4
تنطبق على
  • Microsoft Win32 واجهة برمجة تطبيقات, عندما تستخدم مع:
    • Microsoft Windows 95
    • Microsoft Windows NT 4.0
    • the operating system: Microsoft Windows 2000
    • the operating system: Microsoft Windows XP
كلمات أساسية: 
kbmt kbhowto kbkernbase kbthread KB178893 KbMtar
ترجمة آلية
هام: تمت ترجمة هذا المقال باستخدام برنامج ترجمة آلية لشركة مايكروسوفت بدلاً من الاستعانة بمترجم بشري. تقدم شركة مايكروسوفت كلاً من المقالات المترجمة بواسطة المترجمين البشر والمقالات المترجمة آليًا وبالتالي ستتمكن من الوصول إلى كل المقالات الموجودة في قاعدة المعرفة الخاصة بنا وباللغة الخاصة بك. بالرغم من ذلك، فإن المقالة المترجمة آليًا لا تكون دقيقة دائمًا وقد تحتوي على أخطاء إملائية أو لغوية أو نحوية، مثل تلك الأخطاء الصادرة عن متحدث أجنبي عندما يتحدث بلغتك. لا تتحمل شركة مايكروسوفت مسئولية عدم الدقة أو الأخطاء أو الضرر الناتج عن أية أخطاء في ترجمة المحتوى أو استخدامه من قبل عملائنا. تعمل شركة مايكروسوفت باستمرار على ترقية برنامج الترجمة الآلية
اضغط هنا لرابط المقالة باللغة الانجليزية178893

إرسال ملاحظات

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com