Enumerate application windows and processes with Win32 APIs

Source: Internet
Author: User

Below are the key data types and function prototypes used in the program.

Code environment: Delphi7.0

OS: Windows2003

By clin003 at 20070427 from: http://blog.csdn.net/clin003

First, let's look at the functions of the execution program.
///// Execution program ////////////
Function tform1.shellrun (Spath: string; sparam: String = ''): Cardinal;
VaR
Lpstartupinfo: tstartupinfo;
Lpprocessinformation: tprocessinformation;
Begin
If sparam <> ''then Spath: = Spath + ''+ sparam;
Fillchar (lpstartupinfo, sizeof (tstartupinfo), 0 );
Fillchar (lpprocessinformation, sizeof (tprocessinformation), 0 );
If CreateProcess (nil, pchar (Spath), nil, nil, true,
Create_new_process_group or normal_priority_class, nil, nil,
Lpstartupinfo, lpprocessinformation) then
Result: = lpprocessinformation. dwprocessid
Else result: = 0; // if the program is successfully executed, the program information is returned. Otherwise, 0 is returned.
End;

////////////////////////////////

Data Type:
Tstartupinfo
Tprocessinformation: Information about processes activated and running by the storage Program
Function prototype:
The following is a function prototype for filling space in the process:
Procedure _ fillchar (var dest; count: integer; Value: Char); // There Is A VaR parameter of no type ..
Fill the Dest with the Count value character.
///////////////////////////
Create a program function prototype for a process:
Function CreateProcess (lpapplicationname: pchar; lpcommandline: pchar;
Lpprocessattributes, lpthreadattributes: psecurityattributes;
Binherithandles: bool; dwcreationflags: DWORD; lpenvironment: pointer;
Lpcurrentdirectory: pchar; const lpstartupinfo: tstartupinfo;
VaR lpprocessinformation: tprocessinformation): bool; stdcall;

We can compare the method we call with the function prototype to know which parameters are required, which can be nil (null.

Bytes -----------------------------------------------------------------------------------
Check whether the process is running the function.
//// // Check whether the process is running ////////////////
Function tform1.existsprocess (processid: thandle): Boolean;
VaR
Fsnapshothandle: thandle;
Lppe: tprocessentry32;
RET: Boolean;
Begin
Result: = false;
Fsnapshothandle: = createconlhelp32snapshot (th32cs_snapprocess, 0 );
If fsnapshothandle <= 0 Then exit;
Try
Lppe. dwsize: = sizeof (processentry32 );
RET: = process32first (fsnapshothandle, lppe );
While RET do
Begin
If lppe. th32processid = processid then
Begin
Result: = true;
Break;
End;
RET: = process32next (fsnapshothandle, lppe );
End;
Finally
Closehandle (fsnapshothandle );
End;
End;
///////////////////////////////

Data Type :{
Thandle is a longword type that stores a handle (or pointer)
Processentry32 is a record type that stores program information.
Not to mention Boolean}
Function prototype:
{The createconlhelp32snapshot () function creates a snapshot handle for the system information}
Function createmedilhelp32snapshot (dwflags, th32processid: DWORD): thandle;

{Function process32first () obtains the process list from the snapshot handle and repeats process32next until the function returns false. This will traverse the process list in the snapshot.
Two parameters: Snapshot handle and processentry32 structure .}
Function process32first (hsnapshot: thandle; var lppe: tprocessentry32): bool;

{
Note: Before calling process32first (), remember to set the dwsize Member of the processentry32 structure to sizeof (processentry32 ).
}

------------------------------------------
Terminate a process-core function 1 of this instance
/////// Terminate the process ////////////////////////////

Function tform1.killtask (exefilename: string): integer;
Const
Process_terminate =$ 0001;
VaR
Continueloop: bool;
Fsnapshothandle: thandle;
Fprocessentry32: tprocessentry32;
Begin
Result: = 0;
Fsnapshothandle: = createconlhelp32snapshot (th32cs_snapprocess, 0 );
Fprocessentry32.dwsize: = sizeof (fprocessentry32 );
Continueloop: = process32first (fsnapshothandle, fprocessentry32 );
While INTEGER (continueloop) <> 0 do
Begin
If (uppercase (extractfilename (fprocessentry32.szexefile) =
Uppercase (exefilename ))
Or (uppercase (fprocessentry32.szexefile) =
Uppercase (exefilename) then
Result: = INTEGER (terminateprocess (OpenProcess (
Process_terminate, bool (0 ),
Fprocessentry32.th32processid), 0 ));
Continueloop: = process32next (fsnapshothandle, fprocessentry32 );
End;
End;

//////////////////////////////////
Data Type:
Process_terminate: the message constant that terminates the process.

Function prototype:
{File name returned by the function extractfilename}
Function extractfilename (const filename: string): string;

{
The uppercase function converts lowercase letters to uppercase letters.
}
Function uppercase (const S: string): string;

{Open a process using the function OpenProcess to obtain the handle of the process}
Function OpenProcess (dwdesiredaccess: DWORD; binherithandle: bool; dwprocessid: DWORD): thandle; stdcall;

---------------------------------------------
////// Refresh the process list process //////////////

Procedure tform1.taskrefresh;
Begin
Task. Items. Clear;
Snap: = createconlhelp32snapshot (th32cs_snapprocess, 0 );
Proc. dwsize: = sizeof (tprocessentry32 );
Process32first (SNAP, Proc );
Repeat
Task. Items. Add (Proc. szexefile );
Until (not process32next (SNAP, Proc ));
Task. Selected [0]: = true;
Task. Hint: = task. Items. Strings [task. itemindex];
End;
//////////////////////////////////
Function:
Items. Add add a project to tlistbox.

 

Appendix: ========================================================== ==========================================
Use toolhelp32 library to enumerate Processes

Toolhelp32 library functions are in kernel32.dll. They are all standard API functions. However, Windows NT 4.0 does not provide these functions.
The toolhelp32 library contains various functions that can be used to enumerate processes and threads in the system and obtain information about memory and modules. The enumerated process only needs to use the following functions: createconlhelp32snapshot (), process32first (), and process32next ().
The first step to use the toolhelp32 function is to use the createconlhelp32snapshot () function to create the system information "snapshot ". This function allows you to select the type of information stored in the snapshot. If you are only interested in process information, you only need to include the th32cs_snapprocess flag. The createconlhelp32snapshot () function returns a handle. After the call is completed, the handle must be passed to closehandle ().
Next, call the process32first function to obtain the process list from the snapshot, and then call process32next again until the function returns false. This will traverse the process list in the snapshot. Both functions contain two parameters: Snapshot handle and processentry32 structure.
After process32first or process32next is called, processentry32 contains the key information of a process in the system. The process ID is stored in the th32processid of this structure. This ID can be passed to the OpenProcess () API to obtain the handle of the process. The corresponding executable file name and its storage path are stored in the szexefile structure member. You can also find other useful information in this structure.
Note: Before calling process32first (), remember to set the dwsize Member of the processentry32 structure to sizeof (processentry32 ).

By clin003 at 20070427 from: http://blog.csdn.net/clin003

 

Top-level window of enumeration

Enumeration top-level windows on the desktop may be easier than enumeration processes. You can use the enumwindows () function to enumerate top-level windows on the desktop. Do not use getwindow () to create a window list, because the complex parent-child and compatriot relationships (Z-order) between windows are prone to confusion and inaccurate enumeration results.
Enumwindows () has two parameters: one is the pointer to the callback function, and the other is the User-Defined lparam value. For each desktop window (or top-level window), it calls the callback function once. Then the callback function uses the window handle for some processing, such as adding it to the list. This method ensures that the enumerated results are not confused by the complex hierarchy of the window. Therefore, once the window handle is available, we can get the window title through getwindowtext.

Enumeration process

Creating a system process list is a little more complex than an enumeration window. This is mainly because the API functions used are dependent on different Win32 operating systems. In Windows 9x, Windows ME, Windows 2000 Professional, and Windows XP, we can use the APIS function in the toolhelp32 library. However, in Windows NT, we must use the APIS function in the psapi library, which is part of the SDK. This article will discuss the implementation of all the above platforms. The example program will wrap the APIs in the above library so that the packaged function can support all Win32 operating systems.

Use toolhelp32 library to enumerate Processes

Toolhelp32 library functions are in kernel32.dll. They are all standard API functions. However, Windows NT 4.0 does not provide these functions.
The toolhelp32 library contains various functions that can be used to enumerate processes and threads in the system and obtain information about memory and modules. The enumerated process only needs to use the following functions: createconlhelp32snapshot (), process32first (), and process32next ().
The first step to use the toolhelp32 function is to use the createconlhelp32snapshot () function to create the system information "snapshot ". This function allows you to select the type of information stored in the snapshot. If you are only interested in process information, you only need to include the th32cs_snapprocess flag. The createconlhelp32snapshot () function returns a handle. After the call is completed, the handle must be passed to closehandle ().
Next, call the process32first function to obtain the process list from the snapshot, and then call process32next again until the function returns false. This will traverse the process list in the snapshot. Both functions contain two parameters: Snapshot handle and processentry32 structure.
After process32first or process32next is called, processentry32 contains the key information of a process in the system. The process ID is stored in the th32processid of this structure. This ID can be passed to the OpenProcess () API to obtain the handle of the process. The corresponding executable file name and its storage path are stored in the szexefile structure member. You can also find other useful information in this structure.
Note: Before calling process32first (), remember to set the dwsize Member of the processentry32 structure to sizeof (processentry32 ).

Use the psapi library to enumerate Processes

In Windows NT, use psapi functions to create a process list. These functions are in psapi. dll. This file is distributed along with the Platform SDK, the latest version of the platform SDK can be downloaded from here: http://www.microsoft.com/downloads/details.aspx? Familyid = EBA0128F-A770-45F1-86F3-7AB010B398A3 & displaylang = en

 

The psapi. h and psapi. Lib files required for using this library are also in this platform SDK.
To use the functions in the psapi library, you must add psapi. lib to the Code project and include the psapi. h file in all the modules that call psapi. Remember to distribute psapi. dll along with the executable file because it is not distributed along with Windows NT. You can click here (http://www.microsoft.com/downloads/release.asp? Releaseid = 30337) download the distribution version of psapi. dll separately (you do not need to download the Platform SDK completely ).
Like toolhelp32, The psapi Library also contains a variety of useful functions. Due to space limitations, this article only discusses functions related to enumeration processes: enumprocesses (), enumprocessmodules (), getmodulefilenameex (), and getmodulebasename ().
The first step to create a process list is to call enumprocesses (). The declaration of this function is as follows:

BOOL EnumProcesses( DWORD *lpidProcess, DWORD cb, DWORD *cbNeeded );

Enumprocesses () includes three parameters: DWORD-type array pointer lpidprocess; the size and size of the array CB; and a pointer to DWORD cbneeded, which receives the length of the returned data. DWORD array is used to save the currently running process IDs. Cbneeded returns the memory size used by the array. The following formula shows how many processes are returned: nreturned = cbneeded/sizeof (DWORD ).
Note: although the document names the returned DWORD "cbneeded", there is actually no way to know the size of the array to be uploaded. Enumprocesses () does not return an array value greater than that passed by the CB parameter in cbneeded. Result: The only way to ensure the success of the enumprocesses () function is to allocate a DWORD array. If the returned cbneeded is equal to CB, allocate a large array and keep trying until the cbneeded value is less than CB.
Now you get an array whose elements Save the ID of each process in the system. If you want to obtain the process name, you must first obtain a handle. To obtain the handle from the process ID, you must call OpenProcess ().
Once a handle is available, you need to obtain the first module of the process. Therefore, call the enumprocessmodules () API:

EnumProcessModules( hProcess, &hModule, sizeof(hModule), &cbReturned );

After the call, the hmodule variable is saved as the first module in the process. Remember that a process has no name, but the first module of the process is the executable module of the process. Now you can use the module handle returned by hmodule to call the getmodulefilenameex () or getmodulebasename () API function to obtain the full path name, or only the name of the executable module of the process. Both functions have four parameters: Process Handle, module handle, buffer pointer of the returned name, and buffer size.
Repeat this call process with each process ID returned by the enumprocesses () API, you can create a list of Windows NT processes.

How to handle a 16-bit Process

In Windows 95, Windows 98, and Windows ME, toolhelp32 treats 16-bit programs equally, and they have their own process IDs like Win32 programs. However, this is not the case in Windows NT, Windows 2000, or Windows XP. In these operating systems, the 16-bit program runs in the so-called vdm (that is, DOS machine ).
To enumerate 16-bit programs in Windows NT, Windows 2000, and Windows XP, you must use a function named vdmenumtaskwowex. The source code module must contain vdmdbg. h, and the vdmdbg. Lib file must be linked to the project. Both files are in the Platform SDK. The declaration of this function is as follows:

INT WINAPI VDMEnumTaskWOWEx( DWORD dwProcessId, TASKENUMPROCEX fp,LPARAM lparam );

Dwprocessid is the 16-bit task process identifier to be enumerated in NTVDM. The FP parameter is a pointer to the callback enumeration function. The parameter lparam is a user-defined value and is passed to the enumeration function. Enumeration functions should be defined as follows:

BOOL WINAPI Enum16( DWORD dwThreadId,                     WORD hMod16,                     WORD hTask16,                     PSZ pszModName,                     PSZ pszFileName,                     LPARAM lpUserDefined );

This function is called once for each 16-bit task running in the NTVDM process. The NTVDM process ID is passed into vdmenumtaskwowex (). If you want to continue enumeration, false is returned. If you want to terminate enumeration, true is returned. Note that this is relative to enumwindows.

By clin003 at 20070427 from: http://blog.csdn.net/clin003

References

  • MSJ "under the hood" 1996/08 by pietrek, Matt.
  • MSJ "under the hood" 1996/11 by pietrek, Matt.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.