同理,可以用在很多场合
using System.Runtime.InteropServices;
[DllImport("User32.DLL")]
public static extern int SendMessage(
IntPtr hWnd, uint Msg, int wParam, int lParam);
public delegate bool WNDENUMPROC(
IntPtr hwnd, int lParam);
[DllImport("user32.dll")]
public static extern int EnumWindows(
WNDENUMPROC lpEnumFunc, int lParam);
[DllImport("user32.dll")]
public static extern int EnumChildWindows(
IntPtr hWndParent,WNDENUMPROC lpEnumFunc, int lParam);
[DllImport("user32.dll")]
public static extern int GetWindowText(
IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll")]
public static extern int GetClassName(
IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll")]
public static extern bool IsWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.DLL")]
public static extern IntPtr FindWindowEx(
IntPtr hwndParent, IntPtr hwndChildAfter,
string lpszClass, string lpszWindow);
[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(
IntPtr hWnd, out uint dwProcessId);
[DllImport("psapi.dll")]
public static extern uint GetModuleBaseName(
IntPtr hProcess, IntPtr hModule,
StringBuilder lpBaseName, uint nSize);
public const uint PROCESS_VM_OPERATION = 0x0008;
public const uint PROCESS_VM_READ = 0x0010;
public const uint PROCESS_VM_WRITE = 0x0020;
public const uint PROCESS_QUERY_INFORMATION = 0x0400;
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(
uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
[DllImport("kernel32.dll")]
public static extern bool CloseHandle(IntPtr handle);
[DllImport("user32.dll")]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
public const int GWL_STYLE = -16;
public const int ES_READONLY = 0x800;
public const uint MEM_COMMIT = 0x1000;
public const uint MEM_RELEASE = 0x8000;
public const uint MEM_RESERVE = 0x2000;
public const uint PAGE_READWRITE = 4;
[DllImport("kernel32.dll")]
public static extern IntPtr VirtualAllocEx(
IntPtr hProcess, IntPtr lpAddress, uint dwSize,
uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
public static extern bool VirtualFreeEx(
IntPtr hProcess, IntPtr lpAddress,
uint dwSize, uint dwFreeType);
[DllImport("kernel32.dll")]
public static extern bool WriteProcessMemory(
IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer,
int nSize, ref uint vNumberOfBytesRead);
[DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(
IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer,
int nSize, ref uint vNumberOfBytesRead);
private IntPtr richHandle;
public string GetProcessName(uint AProcessId)
{
StringBuilder vBuffer = new StringBuilder(256);
IntPtr vProcess = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
false, AProcessId);
try
{
if (GetModuleBaseName(
vProcess, IntPtr.Zero, vBuffer,
(uint)vBuffer.Capacity) > 0)
{
return vBuffer.ToString();
}
else
return string.Empty;
}
finally
{
CloseHandle(vProcess);
}
}
public bool EnumChild(IntPtr hwnd, int lParam)
{
if (!IsWindowVisible(hwnd))
return true; // 不可见
StringBuilder vBuffer = new StringBuilder(256);
GetClassName(hwnd, vBuffer, vBuffer.Capacity);
if (vBuffer.ToString().ToLower() == "richedit20a")
{
if ((GetWindowLong(hwnd, GWL_STYLE) & ES_READONLY)
!= ES_READONLY) // 非只读
{
richHandle = hwnd;
return false;
}
}
return true;
}
public bool EnumFunc(IntPtr hwnd, int lParam)
{
if (!IsWindowVisible(hwnd))
return true; // 不可见
StringBuilder vBuffer = new StringBuilder(256);
GetClassName(hwnd, vBuffer, vBuffer.Capacity);
if (vBuffer.ToString() == "#32770")
{
uint vProcessId;
GetWindowThreadProcessId(hwnd, out vProcessId);
if (GetProcessName(vProcessId).ToLower() == "qq.exe")
{
GetWindowText(hwnd, vBuffer, vBuffer.Capacity);
// 标题中含"聊天中"
if (vBuffer.ToString().IndexOf("聊天中") >= 0)
{
EnumChildWindows(hwnd, @EnumChild, lParam);
return false;
}
}
}
return true;
}
[StructLayout(LayoutKind.Sequential)]
public struct GETTEXTLENGTHEX
{
public uint flags;
public uint codepage;
}
[StructLayout(LayoutKind.Sequential)]
public struct GETTEXTEX
{
public int cb;
public int flags;
public int codepage;
public IntPtr lpDefaultChar;
public IntPtr lpUsedDefChar;
}
public const int GTL_DEFAULT = 0;
public const int GT_DEFAULT = 0;
public const int WM_USER = 0x0400;
public const int EM_GETTEXTEX = WM_USER + 94;
public const int EM_GETTEXTLENGTHEX = WM_USER + 95;
public string Process_ReadRichEditText(IntPtr AHandle)
{
if (!IsWindow(AHandle))
return string.Empty;
string vReturn = string.Empty;
uint vProcessId;
GetWindowThreadProcessId(AHandle, out vProcessId);
IntPtr vProcess = OpenProcess(
PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE,
false, vProcessId);
try
{
uint vNumberOfBytesRead = 0;
IntPtr vPointer = VirtualAllocEx(
vProcess, IntPtr.Zero, 0x1000,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
GETTEXTLENGTHEX vGetTextLengthEx = new GETTEXTLENGTHEX();
vGetTextLengthEx.flags = GTL_DEFAULT;
vGetTextLengthEx.codepage = 1200; // Unicode
IntPtr vAddress = Marshal.AllocCoTaskMem(
Marshal.SizeOf(vGetTextLengthEx));
Marshal.StructureToPtr(vGetTextLengthEx, vAddress, false);
WriteProcessMemory(vProcess, vPointer, vAddress,
Marshal.SizeOf(vGetTextLengthEx),
ref vNumberOfBytesRead);
Marshal.FreeCoTaskMem(vAddress);
int L = SendMessage(
AHandle, EM_GETTEXTLENGTHEX,
(int)vPointer, 0);
VirtualFreeEx(vProcess, vPointer, 0, MEM_RELEASE);
if (L <= 0)
return vReturn;
GETTEXTEX vGetTextEx = new GETTEXTEX();
vGetTextEx.cb = L * 2 + 2;
vGetTextEx.flags = GT_DEFAULT;
vGetTextEx.codepage = 1200; // Unicode
vGetTextEx.lpDefaultChar = IntPtr.Zero;
vGetTextEx.lpUsedDefChar = IntPtr.Zero;
vPointer = VirtualAllocEx(vProcess, IntPtr.Zero,
(uint)(Marshal.SizeOf(vGetTextEx) + L * 2 + 2),
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
vAddress = Marshal.AllocCoTaskMem(Marshal.SizeOf(vGetTextEx));
Marshal.StructureToPtr(
vGetTextEx, vAddress, false);
WriteProcessMemory(vProcess, vPointer, vAddress,
Marshal.SizeOf(vGetTextEx),
ref vNumberOfBytesRead);
Marshal.FreeCoTaskMem(vAddress);
SendMessage(AHandle, EM_GETTEXTEX, (int)vPointer,
(int)vPointer + Marshal.SizeOf(vGetTextEx));
vAddress = Marshal.AllocCoTaskMem(L * 2);
ReadProcessMemory(vProcess,
(IntPtr)((int)vPointer + Marshal.SizeOf(vGetTextEx)),
vAddress, L * 2, ref vNumberOfBytesRead);
vReturn = Marshal.PtrToStringUni(vAddress, L * 2);
Marshal.FreeCoTaskMem(vAddress);
VirtualFreeEx(vProcess, vPointer, 0, MEM_RELEASE);
}
finally
{
CloseHandle(vProcess);
}
return vReturn;
}
private void button1_Click(object sender, EventArgs e)
{
richHandle = IntPtr.Zero;
EnumWindows(EnumFunc, 0);
if (richHandle == IntPtr.Zero)
return;
Console.WriteLine(Process_ReadRichEditText(richHandle));
}