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.
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:
- 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. - 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.
- 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:
175030
(http://support.microsoft.com/kb/175030/EN-US/
)
Bagaimana 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
(http://support.microsoft.com/kb/175030/EN-US/
)
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:
- 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.
- 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.
- 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
(http://go.microsoft.com/fwlink/?LinkId=151500)
for other considerations.