📄 pviewer.c
字号:
/******************************************************************************
P R O C E S S V I E W E R
Name: pviewer.c
Description:
This program demonstrates the usage of special registry APIs
for collecting performance data.
C files used in this app:
pviewer.c - this file
pviewdat.c - updates the dialog
perfdata.c - gets performance data structures
objdata.c - access performance data objects
instdata.c - access performance data instances
cntrdata.c - access performance data counters
******************************************************************************/
#include <windows.h>
#include <winperf.h>
#include "perfdata.h"
#include "pviewdat.h"
#include "pviewdlg.h"
#include <string.h>
#include <stdio.h>
#define INDEX_STR_LEN 10
#define MACHINE_NAME_LEN MAX_COMPUTERNAME_LENGTH+2
#define MACHINE_NAME_SIZE MACHINE_NAME_LEN+1
TCHAR INDEX_PROCTHRD_OBJ[2*INDEX_STR_LEN];
TCHAR INDEX_COSTLY_OBJ[3*INDEX_STR_LEN];
TCHAR gszMachineName[MACHINE_NAME_SIZE];
TCHAR gszCurrentMachine[MACHINE_NAME_SIZE];
DWORD gPerfDataSize = 50*1024; // start with 50K
PPERF_DATA gpPerfData;
DWORD gCostlyDataSize = 100*1024; // start wiih 100K
PPERF_DATA gpCostlyData;
PPERF_OBJECT gpProcessObject; // pointer to process objects
PPERF_OBJECT gpThreadObject; // pointer to thread objects
PPERF_OBJECT gpThreadDetailsObject; // pointer to thread detail objects
PPERF_OBJECT gpAddressSpaceObject; // pointer to address space objects
PPERF_OBJECT gpImageObject; // pointer to image objects
HKEY ghPerfKey = HKEY_PERFORMANCE_DATA; // get perf data from this key
HKEY ghMachineKey = HKEY_LOCAL_MACHINE; // get title index from this key
HCURSOR ghCursor[2]; // 0 = arrow, 1 = hourglass
HANDLE ghMemUpdateEvent; // to signal a refresh of mem stats
HANDLE ghMemUpdateMutex; // to restrict overlapping refreshes
HINSTANCE ghInstance; // handle for pviewer app
/****
Prototypes
****/
BOOL CALLBACK PviewDlgProc (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
void PviewDlgRefresh (HWND hWnd);
void PviewDlgRefreshCostlyData (HWND hPviewDlg);
void PviewDlgRefreshProcess (HWND hWnd);
void PviewDlgRefreshThread (HWND hWnd);
void PviewDlgRefreshCurSelProcess (HWND hWnd);
void PviewDlgRefreshCurSelThread (HWND hWnd);
WORD PviewDlgGetCurSelPriority (HWND hWnd);
BOOL PviewDlgChangePriority (HWND hWnd, DWORD wParam, WORD wItem);
BOOL PviewDlgTerminateProcess (HWND hPviewDlg);
BOOL CALLBACK MemDlgProc (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
void MemDlgUpdateThread (HWND hWnd);
void MemDlgRefresh (HWND hWnd, HWND hPviewDlg);
void MemDlgRefreshCurSelImage (HWND hMemDlg, HWND hPviewDlg);
INT GetCurSelText (HWND hList, LPTSTR str);
DWORD GetCurSelData (HWND hWnd, DWORD dwList);
INT ReSelectText (HWND hList, INT StartIndex, LPTSTR str);
void SetPerfIndexes (HWND hWnd);
DWORD GetTitleIdx (HWND hWnd, LPTSTR TitleSz[], DWORD LastIndex, LPTSTR Name);
void SetListBoxTabStops (HWND hWnd);
void SetLocalMachine (void);
BOOL ConnectComputer (HWND hWnd);
void DisableControls (HWND hPviewDlg);
void EnableControls (HWND hPviewDlg);
//********************************************************
//
// WinMain --
//
// Build Up: create the program's dialog box,
// load the desired icons, enter the message
// loop.
//
// Tear Down: free up the memory allocated by the
// dialog box proc, and exit.
//
int WINAPI WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HANDLE hWndDialog;
MSG msg;
ghInstance = hInstance;
// load our default cursors
//
ghCursor[0] = LoadCursor (0, IDC_ARROW);
ghCursor[1] = LoadCursor (0, IDC_WAIT);
// open our dialog box
//
hWndDialog = CreateDialogParam (hInstance,
MAKEINTRESOURCE (PVIEW_DLG),
NULL,
(DLGPROC) PviewDlgProc,
(LONG)0);
// the almighty Windows message loop:
//
while (GetMessage (&msg, NULL, 0, 0))
if (!IsDialogMessage (hWndDialog, &msg))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
// close up shop
//
DestroyWindow (hWndDialog);
LocalFree (gpPerfData);
return 0;
}
/*****************
PviewDlg functions
*****************/
//********************************************************
// PviewDlgProc --
//
// Pview dialog procedure
//
BOOL CALLBACK PviewDlgProc (HWND hWnd,
UINT wMsg,
WPARAM wParam,
LPARAM lParam)
{
WORD wItem;
switch (wMsg)
{
case WM_INITDIALOG:
SetClassLong (hWnd, GCL_HICON, (LONG)LoadIcon(ghInstance, TEXT("VIEWPICON")) );
SetListBoxTabStops (hWnd);
SendDlgItemMessage (hWnd, PVIEW_COMPUTER, EM_LIMITTEXT, MACHINE_NAME_LEN, 0);
PostMessage (hWnd, WM_COMMAND, PVIEW_REFRESH, 0);
break;
case WM_CLOSE:
PostQuitMessage (0);
break;
case WM_COMMAND:
// handle our app-specific controls:
switch (LOWORD (wParam))
{
// works just like "close"
//
case PVIEW_EXIT:
PostQuitMessage (0);
break;
// if somebody moved the highlight in the thread list,
// update the view
//
case PVIEW_THREAD_LIST:
if (HIWORD(wParam) == LBN_DBLCLK || HIWORD(wParam) == LBN_SELCHANGE)
{
PviewDlgRefreshCurSelThread (hWnd);
PostMessage (hWnd, WM_COMMAND, PVIEW_REFRESH_COSTLY_DATA, 0);
}
break;
// if somebody clicked on a new process, update all of the
// affected information.
//
case PVIEW_PROCESS_LIST:
if (HIWORD(wParam) == CBN_DBLCLK || HIWORD(wParam) == CBN_SELCHANGE)
{
PviewDlgRefreshCurSelProcess (hWnd);
PostMessage (hWnd, WM_COMMAND, PVIEW_REFRESH_COSTLY_DATA, 0);
if (HIWORD(wParam) == CBN_DBLCLK)
PostMessage (hWnd, WM_COMMAND, PVIEW_MEMORY_DETAIL, 0);
}
break;
// the user wishes to view the memory stats in detail:
//
case PVIEW_MEMORY_DETAIL:
//
// check to see if we can get exclusive access
// to the memory statistics
//
if (WaitForSingleObject (ghMemUpdateMutex, 0))
// we can't, so just return.
//
return FALSE;
else
{
// we have exclusive access, so start up the
// memory statistics dialog.
//
// release the mutex first so the dialog can use it.
//
ReleaseMutex (ghMemUpdateMutex);
DialogBoxParam (NULL,
MAKEINTRESOURCE (MEMORY_DLG),
hWnd,
(DLGPROC) MemDlgProc,
(LONG)hWnd);
}
break;
// somebody clicked one of the priority radio
// buttons. Find out which one was selected...
//
case PVIEW_PRIORITY_HIGH:
case PVIEW_PRIORITY_NORMAL:
case PVIEW_PRIORITY_IDL:
if (SendDlgItemMessage (hWnd, PVIEW_PRIORITY_HIGH, BM_GETCHECK, 0, 0))
wItem = PVIEW_PRIORITY_HIGH;
else if (SendDlgItemMessage (hWnd, PVIEW_PRIORITY_NORMAL, BM_GETCHECK, 0, 0))
wItem = PVIEW_PRIORITY_NORMAL;
else
wItem = PVIEW_PRIORITY_IDL;
// if the user actually clicked on a NEW state,
// do the change.
//
if (LOWORD(wParam) != wItem)
{
// of course, if it's a remote machine, disallow
// the modification.
//
if (lstrcmp (gszCurrentMachine, gszMachineName))
{
SendDlgItemMessage (hWnd, wItem, BM_SETCHECK, 1, 0);
SetFocus (GetDlgItem (hWnd, wItem));
MessageBox (hWnd,
TEXT("Cannot change process priority on remote machine"),
TEXT("Set priority"),
MB_ICONEXCLAMATION|MB_OK);
}
// at this point, we know we are affecting the local
// machine, and a change has to be made.
// Just Do It(TM).
//
else if (PviewDlgChangePriority (hWnd, wParam, wItem))
PviewDlgRefresh (hWnd);
}
break;
case PVIEW_THREAD_HIGHEST:
case PVIEW_THREAD_ABOVE:
case PVIEW_THREAD_NORMAL:
case PVIEW_THREAD_BELOW:
case PVIEW_THREAD_LOWEST:
//
// this selection hasn't been fleshed out yet.
//
PviewDlgRefreshCurSelThread (hWnd);
break;
// terminate the selected process
//
case PVIEW_TERMINATE:
if (PviewDlgTerminateProcess (hWnd))
PviewDlgRefresh (hWnd);
break;
// if the text has changed, we want to connect and
// view another system's processes...
//
case PVIEW_COMPUTER:
if (HIWORD(wParam) == EN_CHANGE)
EnableWindow (GetDlgItem (hWnd, PVIEW_CONNECT), TRUE);
else
return FALSE;
break;
// we were told to connect, go ahead and try...
//
case PVIEW_CONNECT:
if (ConnectComputer (hWnd))
{
SetPerfIndexes (hWnd);
PviewDlgRefresh (hWnd);
}
break;
// refresh the current information displayed
//
case PVIEW_REFRESH:
if (ConnectComputer (hWnd))
SetPerfIndexes (hWnd);
PviewDlgRefresh (hWnd);
break;
// refresh the currently updated costly
// statistics
//
case PVIEW_REFRESH_COSTLY_DATA:
if (WaitForSingleObject (ghMemUpdateMutex, 0))
return FALSE;
PviewDlgRefreshCostlyData (hWnd);
ReleaseMutex (ghMemUpdateMutex);
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//********************************************************
//
// PviewDlgRefresh --
//
// Refresh the pview dialog.
//
void PviewDlgRefresh (HWND hWnd)
{
static HANDLE hMemUpdateThread = NULL;
static DWORD MemUpdateThreadID;
MSG Msg;
SetCursor (ghCursor[1]);
if (hMemUpdateThread) // get memory data
SetEvent (ghMemUpdateEvent);
else
hMemUpdateThread = CreateThread (NULL,
0,
(LPTHREAD_START_ROUTINE)MemDlgUpdateThread,
(LPVOID)hWnd,
0,
&MemUpdateThreadID);
// get performance data
//
gpPerfData = RefreshPerfData (ghPerfKey, INDEX_PROCTHRD_OBJ, gpPerfData, &gPerfDataSize);
gpProcessObject = FindObject (gpPerfData, PX_PROCESS);
gpThreadObject = FindObject (gpPerfData, PX_THREAD);
// refresh
//
PviewDlgRefreshProcess (hWnd);
PviewDlgRefreshThread (hWnd);
// Remove all mouse and key messages. They are not accepted
// while the cursor is a hourglass.
//
while (PeekMessage (&Msg, hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE));
while (PeekMessage (&Msg, hWnd, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE));
SetCursor (ghCursor[0]);
}
//********************************************************
//
// PviewDlgRefreshCostlyData --
//
// Refresh the costly data.
//
void PviewDlgRefreshCostlyData (HWND hPviewDlg)
{
LPTSTR szProcessName;
LPTSTR szThreadName;
PPERF_INSTANCE pInstance;
DWORD dwIndex;
dwIndex = GetCurSelData (hPviewDlg, PVIEW_PROCESS_LIST);
pInstance = FindInstanceN (gpProcessObject, dwIndex);
szProcessName = InstanceName (pInstance);
RefreshPviewDlgMemoryData (hPviewDlg,
pInstance,
gpProcessObject,
gpAddressSpaceObject);
dwIndex = GetCurSelData (hPviewDlg, PVIEW_THREAD_LIST);
pInstance = FindInstanceN (gpThreadObject, dwIndex);
szThreadName = InstanceName (pInstance);
RefreshPviewDlgThreadPC (hPviewDlg,
szProcessName,
szThreadName,
gpThreadDetailsObject,
gpCostlyData);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -