Bagaimana untuk mengakhiri aplikasi "Bersih" dalam Win32

Terjemahan Artikel Terjemahan Artikel
ID Artikel: 178893 - Melihat produk di mana artikel ini berlaku.
Perbesar semua | Perkecil semua

Pada Halaman ini

RINGKASAN

Dalam dunia yang sempurna, proses Anda bisa meminta proses lain, melalui beberapa bentuk komunikasi Inter-proses, untuk menutup. Namun, jika Anda tidak memiliki sumber-tingkat kontrol aplikasi yang Anda ingin untuk menutup, kemudian Anda mungkin tidak memiliki pilihan ini. Meskipun tidak dijamin "bersih" cara untuk menutup aplikasi Win32, ada langkah-langkah yang dapat Anda ambil untuk memastikan bahwa aplikasi menggunakan metode terbaik untuk membersihkan sumber daya.

INFORMASI LEBIH LANJUT

32-Bit proses (dan 16-Bit proses di bawah Windows 95)

Di bawah Win32, sistem operasi janji untuk membersihkan sumber daya yang dimiliki oleh proses ketika menutup turun. Ini, bagaimanapun, berarti bahwa proses itu sendiri memiliki kesempatan untuk melakukan setiap akhir flushes informasi untuk disk, setiap akhir komunikasi melalui koneksi remote, maupun artinya bahwa proses DLL akan memiliki kesempatan untuk mengeksekusi mereka Kode PROCESS_DETACH. Inilah sebabnya mengapa umumnya lebih baik untuk menghindari mengakhiri aplikasi di bawah Windows 95 dan Windows NT.

Jika Anda benar-benar harus menutup proses, ikuti langkah berikut:
  1. Posting WM_CLOSE untuk semua jendela Top-Level yang dimiliki oleh proses yang Anda ingin menutup. Banyak aplikasi Windows menanggapi pesan ini dengan mematikan.

    CATATAN: Aplikasi konsol menanggapi WM_CLOSE tergantung pada apakah atau tidak itu telah terinstal handler kontrol.

    Gunakan EnumWindows() untuk menemukan pegangan untuk windows target Anda. Dalam fungsi panggilan balik Anda, periksa untuk melihat apakah windows' proses ID pertandingan proses yang Anda ingin menutup. Anda dapat melakukan ini dengan menelepon GetWindowThreadProcessId(). Sekali Anda telah mendirikan sebuah pertandingan, menggunakan PostMessage() atau SendMessageTimeout() untuk mengirim pesan WM_CLOSE ke jendela.
  2. Gunakan WaitForSingleObject() untuk menunggu untuk menangani proses. Pastikan Anda menunggu dengan nilai timeout, karena ada banyak situasi di mana WM_CLOSE akan tidak menutup aplikasi. Ingat untuk membuat waktu yang cukup lama (dengan WaitForSingleObject(), atau dengan SendMessageTimeout()) sehingga pengguna dapat menanggapi setiap dialog kotak yang dibuat dalam menanggapi pesan WM_CLOSE.
  3. Jika nilai kembali WAIT_OBJECT_0, kemudian aplikasi ditutup sendiri bersih. Jika nilai kembali WAIT_TIMEOUT, maka Anda harus menggunakan TerminateProcess() shutdown aplikasi.

    CATATAN: Jika Anda getting3 kembali nilai dari WaitForSingleObject() lain kemudian WAIT_OBJECT_0 atau WAIT_TIMEOUT, menggunakan GetLastError() untuk menentukan penyebabnya.
Dengan mengikuti langkah-langkah ini, Anda memberikan aplikasi mungkin kesempatan terbaik shutdown bersih (selain IPC atau campur tangan pengguna).

Masalah 16-Bit (di bawah Windows NT)

Langkah-langkah yang sebelumnya bekerja untuk 16-bit aplikasi di bawah Windows 95, namun, Aplikasi Windows NT 16-bit bekerja sangat berbeda.

Di bawah Windows NT, semua aplikasi 16-bit berjalan di DOS virtual mesin (VDM). VDM ini berjalan sebagai proses Win32 (NTVDM) di bawah Windows NT. NTVDM proses memiliki proses id. Anda dapat memperoleh menangani proses melalui OpenProcess(), seperti Anda dapat dengan proses Win32 lainnya. Namun demikian, tidak ada aplikasi 16-bit yang berjalan di VDM memiliki proses ID, dan oleh karena itu Anda tidak bisa menangani proses dari OpenProcess(). Setiap aplikasi 16-bit dalam VDM telah menangani tugas 16-bit dan 32-bit benang eksekusi. ID menangani dan benang dapat ditemukan melalui panggilan ke fungsi VDMEnumTaskWOWEx(). Untuk tambahan informasi, silakan lihat artikel berikut dalam Pengetahuan Microsoft Base:
175030Bagaimana untuk menghitung aplikasi Win32
Pertama, dan paling langsung, pilihan ketika menutup 16-bit aplikasi di bawah Windows NT adalah untuk menutup seluruh proses NTVDM. Anda dapat melakukan ini dengan mengikuti langkah-langkah yang diuraikan di atas. Anda hanya perlu tahu ID proses proses NTVDM (lihat artikel KB 175030 dikutip di atas untuk menemukan ID proses NTVDM). Kelemahan dari pendekatan ini adalah bahwa menutup semua aplikasi 16-bit yang berjalan di VDM itu. Jika ini adalah bukan tujuan Anda, maka Anda perlu untuk mengambil pendekatan lain.

Jika Anda ingin menutup aplikasi 16-bit tunggal dalam NTVDM proses, berikut adalah langkah-langkah yang Anda butuhkan untuk mengambil:
  1. Posting WM_CLOSE untuk semua Top-Level windows yang dimiliki oleh proses, dan yang memiliki ID benang memiliki sama sebagai tugas 16-bit yang Anda ingin Matikan. Cara yang paling efektif untuk melakukannya adalah dengan menggunakan EnumWindows(). Dalam fungsi panggilan balik Anda, periksa untuk melihat jika jendela proses ID dan Thread ID cocok Anda ingin menutup tugas 16-bit. Ingat bahwa ID proses akan menjadi ID proses proses NTVDM yang aplikasi 16-bit berjalan.
  2. Meskipun Anda memiliki thread ID, Anda tidak punya cara untuk menunggu penghentian proses 16-bit. Sebagai hasilnya, Anda harus menunggu sewenang-wenang panjang waktu (untuk memungkinkan bersih menutup turun), dan kemudian mencoba untuk menutup aplikasi tetap. Jika aplikasi sudah tertutup turun, maka ini akan melakukan apa-apa. Jika itu belum ditutup, maka itu akan menghentikan aplikasi.
  3. Menghentikan aplikasi yang menggunakan fungsi yang disebut VDMTerminateTaskWOW(), yang dapat ditemukan di Vdmdbg.dll. Dibutuhkan ID proses VDM dan jumlah tugas tugas 16-bit.
Pendekatan ini memungkinkan Anda untuk menutup aplikasi 16-bit tunggal dalam VDM di bawah Windows NT. Namun, Windows 16-bit tidak pandai pembersihan sumber daya tugas dihentikan, dan tidak adalah WOWExec yang berjalan di VDM. Jika Anda mencari pendekatan yang terbersih untuk mengakhiri aplikasi 16-bit di bawah Windows NT, Anda harus mempertimbangkan mengakhiri VDM seluruh proses. Catatan: Jika Anda mulai 16-bit aplikasi yang Anda dapat mengakhiri kemudian, kemudian gunakan CREATE_SEPARATE_WOW_VDM dengan CreateProcess().

Contoh kode

Kode contoh menerapkan teknik-teknik yang dijelaskan di atas untuk 16-bit dan 32- sedikit aplikasi yang menggunakan dua fungsi berikut: TerminateApp() dan Terminate16App(). TerminateApp() membutuhkan ID proses 32-bit dan timeout (di miliseconds). Terminate16App(). Kedua fungsi menggunakan eksplisit menghubungkan ke DLL fungsi sehingga mereka akan kompatibel secara biner di Windows NT dan 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 ;
   }
				
Note This is a "FAST PUBLISH" article created directly from within the Microsoft support organization. The information contained herein is provided as-is in response to emerging issues. As a result of the speed in making it available, the materials may include typographical errors and may be revised at any time without notice. See Terms of Use for other considerations.

Properti

ID Artikel: 178893 - Kajian Terakhir: 16 September 2011 - Revisi: 2.0
Berlaku bagi:
  • Microsoft Win32 Application Programming Interface
Kata kunci: 
kbhowto kbkernbase kbthread kbmt KB178893 KbMtid
Penerjemahan Mesin
PENTING: Artikel ini diterjemahkan menggunakan perangkat lunak mesin penerjemah Microsoft dan bukan oleh seorang penerjemah. Microsoft menawarkan artikel yang diterjemahkan oleh seorang penerjemah maupun artikel yang diterjemahkan menggunakan mesin sehingga Anda akan memiliki akses ke seluruh artikel baru yang diterbitkan di Pangkalan Pengetahuan (Knowledge Base) dalam bahasa yang Anda gunakan. Namun, artikel yang diterjemahkan menggunakan mesin tidak selalu sempurna. Artikel tersebut mungkin memiliki kesalahan kosa kata, sintaksis, atau tata bahasa, hampir sama seperti orang asing yang berbicara dalam bahasa Anda. Microsoft tidak bertanggung jawab terhadap akurasi, kesalahan atau kerusakan yang disebabkan karena kesalahan penerjemahan konten atau penggunaannya oleh para pelanggan. Microsoft juga sering memperbarui perangkat lunak mesin penerjemah.
Klik disini untuk melihat versi Inggris dari artikel ini:178893

Berikan Masukan

 

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