在CS程序中启动其他应用后,要获取进程的主窗体其实很简单:
Process p = Process.Start(exePath);
//p.WaitForInputIdle();
p.Refresh();
IntPtr mainWnd = p.MainWindowHandle;
但是,总有很多特殊的情况,上面的方法根本无法用,所以,要用Windows API来搞定了
1、如果窗口信息很固定而且没有重名的话,可以用Findwindow搞定
[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
IntPtr clientWnd = FindWindow(null,"FormClient");
2、根据标题枚举窗口句柄
//枚举窗体
[DllImport("User32.dll", EntryPoint = "EnumWindows", SetLastError = true)]
public static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, uint lParam);
//获取窗体标题
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpText, int nCount);
//设置错误状态
[DllImport("kernel32.dll", EntryPoint = "SetLastError")]
public static extern void SetLastError(uint dwErrCode);
//线程主窗口句柄
private static IntPtr processMainWnd = IntPtr.Zero;
//要查找的窗口名称
private static String winTitle = "__Web__Form__Main__";
//声明委托函数
public delegate bool WNDENUMPROC(IntPtr hwnd, uint lParam);
//枚举进程句柄,非线程安全
[SecuritySafeCritical]
public static IntPtr GetCurrentWindowHandle()
{
IntPtr ptrWnd = IntPtr.Zero;
bool bResult = EnumWindows(new WNDENUMPROC(EnumWindowsProc), (uint)0);
if (!bResult && Marshal.GetLastWin32Error() == 0)
{
ptrWnd = processMainWnd;
}
return ptrWnd;
}
//枚举函数,获取主窗口句柄然后退出
[SecuritySafeCritical]
private static bool EnumWindowsProc(IntPtr hwnd, uint lParam)
{
//根据标题获取窗体
var sb = new StringBuilder(50);
GetWindowText(hwnd, sb, sb.Capacity);
if (winTitle.Equals(sb.ToString()))
{
processMainWnd = hwnd;
SetLastError(0);
return false;
}
return true;
}
3、跟进进程id枚举获取主窗体句柄
//枚举窗体
[DllImport("User32.dll", EntryPoint = "EnumWindows", SetLastError = true)]
//获取父窗体
[DllImport("user32.dll", EntryPoint = "GetParent", SetLastError = true)]
//根据窗口获取线程句柄
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern int GetWindowThreadProcessId(IntPtr hwnd, out uint pid);
//设置错误状态
[DllImport("kernel32.dll", EntryPoint = "SetLastError")]
public static extern void SetLastError(uint dwErrCode);
//线程主窗口句柄
private static IntPtr processMainWnd = IntPtr.Zero;
//枚举进程句柄
[SecuritySafeCritical]
public static IntPtr GetCurrentWindowHandle(int processId)
{
IntPtr ptrWnd = IntPtr.Zero;
bool bResult = EnumWindows(new WNDENUMPROC(EnumWindowsProc), (uint)processId);
if (!bResult && Marshal.GetLastWin32Error() == 0)
{
ptrWnd = processMainWnd;
}
return ptrWnd;
}
//枚举函数,获取主窗口句柄然后退出
[SecuritySafeCritical]
private static bool EnumWindowsProc(IntPtr hwnd, uint lParam)
{
uint uiPid = 0;
//根据启动方式不同,这里要有相应修改
if (GetParent(hwnd) == IntPtr.Zero)
{
GetWindowThreadProcessId(hwnd, out uiPid);
if (uiPid == lParam)
{
processMainWnd = hwnd;
SetLastError(0);
return false;
}
}
}
4、跟进窗口WindowsClassName举获取主窗体句柄
//查找桌面
[DllImport("User32.dll", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
public static extern IntPtr GetDesktopWindow();
//获取窗体句柄
[DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern IntPtr GetWindow(IntPtr hwnd, int wFlag);
//获取窗体类
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
public const int GW_CHILD = 5;
public const int GW_HWNDNEXT = 2;
//枚举桌面窗口,根据WindowsClassName获取句柄
[SecuritySafeCritical]
public static IntPtr GetWinHandleByClasName(String windowClassNmae)
{
//取得桌面窗口,再获取第一个子窗口
IntPtr hwnd = GetDesktopWindow();
hwnd = GetWindow((IntPtr)hwnd, System.Convert.ToInt32(GW_CHILD));
//通过循环来枚举所有的子窗口
while ((long)hwnd != 0)
{
System.Text.StringBuilder ClassName = new System.Text.StringBuilder(256);
GetClassName((IntPtr)hwnd, ClassName, ClassName.Capacity);
String tmpClassName= ClassName.ToString().Trim();
if (tmpClassName.Length > 0)
{
if (tmpClassName.Equals(windowClassNmae))
{
break;
}
}
hwnd = GetWindow((IntPtr)hwnd, System.Convert.ToInt32(GW_HWNDNEXT));
}
return hwnd;
}