Figure 1 Win32API.cs // Win32API: wrapper for selected Win32 API functions
// To compile:
// csc /t:library /out:Win32API.dll Win32API.cs
//
using System;
using System.Drawing;
using System.Text;
using System.Runtime.InteropServices;
//////////////////
// namespace to wrap Win32 API functions. Add them here as you need...
//
namespace Win32API {
[StructLayout(LayoutKind.Sequential)]
public struct POINT {
public POINT(int xx, int yy) { x=xx; y=yy; }
public int x;
public int y;
public override string ToString() {
String s = String.Format("({0},{1})", x, y);
return s;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SIZE {
public SIZE(int cxx, int cyy) { cx=cxx; cy=cyy; }
public int cx;
public int cy;
public override string ToString() {
String s = String.Format("({0},{1})", cx, cy);
return s;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT {
public int left;
public int top;
public int right;
public int bottom;
public int Width() { return right - left; }
public int Height() { return bottom - top; }
public POINT TopLeft() { return new POINT(left,top); }
public SIZE Size() { return new SIZE(Width(), Height()); }
public override string ToString() {
String s = String.Format("{0}x{1}", TopLeft(), Size());
return s;
}
}
public class Win32 {
[DllImport("user32.dll")]
public static extern bool IsWindowVisible(int hwnd);
[DllImport("user32.dll")]
public static extern int GetWindowText(int hwnd,
StringBuilder buf, int nMaxCount);
[DllImport("user32.dll")]
public static extern int GetClassName(int hwnd,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder buf,
int nMaxCount);
[DllImport("user32.dll")]
public static extern int GetWindowRect(int hwnd, ref RECT rc);
[DllImport("user32.dll")]
// note the runtime knows how to marshal a Rectangle
public static extern int GetWindowRect(int hwnd, ref Rectangle rc);
// ... add more here
}
}
Figure 2 WinArray.cs // WinArray: generate ArrayList of top-level windows using EnumWindows.
//
using System;
using System.Collections;
using System.Runtime.InteropServices;
namespace WinArray {
public class WindowArray : ArrayList {
private delegate bool EnumWindowsCB(int hwnd, IntPtr param);
// This is declared private since only I use itno need
[DllImport("user32")]
private static extern int EnumWindows(EnumWindowsCB cb,
IntPtr param);
private static bool MyEnumWindowsCB(int hwnd, IntPtr param) {
GCHandle gch = (GCHandle)param;
WindowArray itw = (WindowArray)gch.Target;
itw.Add(hwnd);
return true;
}
// This is the only public method, the only one you need to call
public WindowArray() {
GCHandle gch = GCHandle.Alloc(this);
EnumWindowsCB ewcb = new EnumWindowsCB(MyEnumWindowsCB);
EnumWindows(ewcb, (IntPtr)gch);
gch.Free();
}
}
}
Figure 3 ListWin.cs using System;
using System.Text;
using System.Drawing;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Win32API; // home-brew wrapper for native API
using WinArray; // home-brew window iterator
class MyApp {
// global command-line switches
static bool bRectangle = false; // show window rect using Rectangle
static bool bRect = false; // show window Rect using RECT
static bool bClassName = false; // show class name
static bool bTitle = false; // show title
static bool bHwnd = false; // show HWND
[STAThread]
// main entry point
static int Main(string[] args) {
// Parse command line. Switches can come in any order.
if (args.GetLength(0)<=0)
return help();
for (int i=0, len=args.GetLength(0); i<len; i++) {
if (args[i].StartsWith("/") || args[i].StartsWith("-") ) {
for (int j=1; j<args[i].Length; j++) {
switch (args[i][j]) {
case 'c': bClassName = true; break;
case 'h': bHwnd = true; break;
case 'r': bRect = true; break;
case 'R': bRectangle = true; break;
case 't': bTitle = true; break;
case '?': default: return help();
}
}
}
}
WindowArray itw = new WindowArray();
foreach (int hwnd in itw) {
if (Win32.IsWindowVisible(hwnd)) {
if (bHwnd) {
Console.Write("{0:x8}", hwnd);
}
if (bClassName) {
StringBuilder cname = new StringBuilder(256);
Win32.GetClassName(hwnd, cname, cname.Capacity);
Console.Write(" {0}",cname);
}
if (bRectangle) {
Rectangle rc = new Rectangle();
Win32.GetWindowRect(hwnd, ref rc);
Console.Write(" {0}",rc);
} else if (bRect) {
RECT rc = new RECT();
Win32.GetWindowRect(hwnd, ref rc);
Console.Write(" {0}",rc);
}
if (bTitle) {
StringBuilder title = new StringBuilder(256);
Win32.GetWindowText(hwnd, title, title.Capacity);
Console.Write(" {0}",title);
}
Console.WriteLine();
}
}
return 0;
}
static int help() {
Console.WriteLine("ListWin: List top-level windows.");
Console.WriteLine(" Copyright 2002 Paul DiLascia.");
Console.WriteLine("Format: ListWin [/chrRt]");
Console.WriteLine("Options:");
Console.WriteLine(" /c(lassname) show window class name");
Console.WriteLine(" /h(wnd) show HWNDs");
Console.WriteLine(" /t(itle) show title (caption)");
Console.WriteLine(" /r(ect) show window rect using RECT");
Console.WriteLine(" /R(ectangle) show window rect using Rectangle");
Console.WriteLine("");
return 0;
}
}
Figure 6 kp #include "stdafx.h"
#include "EnumProc.h"
typedef list<string> CStringList; // like MFC, but with STL
inline BOOL isswitch(TCHAR c) { return c==L'/' || c==L'-'; }
int main(int argc, TCHAR* argv[], TCHAR* envp[])
{
CStringList cmdargs; // command-line args (processes to kill)
BOOL bDisplayOnly=FALSE; // don't kill, just show results
BOOL bQuiet=FALSE; // suppress error messages
BOOL bZap=FALSE; // force-kill process
// Parse command line. Switches can come in any order.
for (int i=1; i<argc; i++) {
if (isswitch(argv[i][0])) {
for (UINT j=1; j<strlen(argv[i]); j++) {
switch(tolower(argv[i][j])) {
case '?': help(); return 0;
case 'n': bDisplayOnly=TRUE; break;
case 'q': bQuiet=TRUE; break;
case 'z': bZap=TRUE; break;
default:
return help();
}
}
} else {
cmdargs.push_back(argv[i]); // got a non-switch arg: add
// to list
}
}
if (cmdargs.size()<=0)
help();
// Now iterate args (module names), killing each one
CStringList::iterator it;
for (it=cmdargs.begin(); it!=cmdargs.end(); it++) {
CFindKillProcess fkp;
DWORD pid = fkp.FindProcess(it->c_str());
if (pid) {
if (bDisplayOnly) {
_tprintf(_T("Kill process %d(0x%08x)\n"),pid,pid);
} else {
fkp.KillProcess(pid, bZap);
}
} else if (!bQuiet) {
_tprintf(_T("Error: Can't find process '%s'.\n"),it-
>c_str());
}
}
return 0;
}
Figure 7 EnumProc
EnumProc.h // Code from last month's column not shown: CProcessIterator,
// CWindowIterator, etc.
//////////////////
// Handy class to facilitate finding and killing a process by name.
//
class CFindKillProcess {
public:
CFindKillProcess();
~CFindKillProcess();
DWORD FindProcess(LPCTSTR lpModname, BOOL bAddExe=TRUE);
BOOL KillProcess(DWORD pid, BOOL bZap);
};
EnumProc.cpp #include "stdafx.h"
#include "EnumProc.h"
// Code from last month's column not shown: CProcessIterator,
// CWindowIterator, etc.
////////////////////////////////////////////////////////////////
// CFindKillProcess - to find/kill a process by module name.
//
CFindKillProcess::CFindKillProcess()
{
}
CFindKillProcess::~CFindKillProcess()
{
}
//////////////////
// Search for process whose module name matches parameter.
// Finds "foo" or "foo.exe"
//
DWORD CFindKillProcess::FindProcess(LPCTSTR modname, BOOL bAddExe)
{
CProcessIterator itp;
for (DWORD pid=itp.First(); pid; pid=itp.Next()) {
TCHAR name[_MAX_PATH];
CProcessModuleIterator itm(pid);
HMODULE hModule = itm.First(); // .EXE
if (hModule) {
GetModuleBaseName(itm.GetProcessHandle(),
hModule, name, _MAX_PATH);
string sModName = modname;
if (strcmpi(sModName.c_str(),name)==0)
return pid;
sModName += ".exe";
if (bAddExe && strcmpi(sModName.c_str(),name)==0)
return pid;
}
}
return 0;
}
//////////////////
// Kill a process cleanly: Close main windows and wait.
// bZap=TRUE to force kill.
//
BOOL CFindKillProcess::KillProcess(DWORD pid, BOOL bZap)
{
CMainWindowIterator itw(pid);
for (HWND hwnd=itw.First(); hwnd; hwnd=itw.Next()) {
DWORD bOKToKill = FALSE;
SendMessageTimeout(hwnd, WM_QUERYENDSESSION, 0, 0,
SMTO_ABORTIFHUNG|SMTO_NOTIMEOUTIFNOTHUNG, 100, &bOKToKill);
if (!bOKToKill)
return FALSE; // window doesn't want to die: abort
PostMessage(hwnd, WM_CLOSE, 0, 0);
}
// I've closed the main windows; now wait for process to die.
BOOL bKilled = TRUE;
HANDLE hp=OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE,FALSE,pid);
if (hp) {
if (WaitForSingleObject(hp, 5000) != WAIT_OBJECT_0) {
if (bZap) { // didn't die: force kill it if zap requested
TerminateProcess(hp,0);
} else {
bKilled = FALSE;
}
}
CloseHandle(hp);
}
return bKilled;
}
|