捕获正在运行的IE实例(C#)






4.53/5 (16投票s)
2002年4月1日
6分钟阅读

235597

4144
如何在你的机器上查找正在运行的 Internet Explorer 实例。
引言
在本文中,我们将研究如何在您的机器上查找正在运行的 Internet Explorer 实例。本文还将深入介绍 Windows API 以及如何从 C# 调用 Win32 API 函数。您还将学习如何实现回调函数。
在代码中,我大量使用了如下所示的 **Win32 API** 函数。
[DllImport("user32.Dll")]
public static extern int EnumWindows(CallBack x, int y);
[DllImport("User32.Dll")]
public static extern void GetWindowText(int h, StringBuilder s, int nMaxCount);
[DllImport("User32.Dll")]
public static extern void GetClassName(int h, StringBuilder s, int nMaxCount);
[DllImport("User32.Dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, int msg, int wParam, int lParam);
在接下来的内容中,我将解释这些不同函数的作用。为了使用 EnumWindows
等 Win32 API
函数,我们需要导入实现这些函数的 Win32 DLL
。
Win32 API – 简要说明
Windows API 包含大量用 C/C++ 编写的函数、常量、回调函数、消息和结构,您可以在您的程序中调用和使用它们。它们执行操作系统更底层的服务,如内存管理、进程切换、磁盘访问等。它们帮助应用程序直接与处理器进行交互。Win 32 API
是为 32 位处理器创建的。它具有平台无关性。API 函数的很大一部分是通过一些库实现的,例如 Kernel32.dll(操作系统内核函数)、User32.dll(用户界面函数)等
。这些 DLL(动态链接库)文件位于 Windows 系统目录所在的位置。这些 DLL 文件“导出”函数,从而允许外部程序使用它们的函数。您会注意到我在程序中使用了 handle
(句柄)的概念。handle
是 Windows 中的一个内部结构,用于跟踪系统中任何对象(如窗口、按钮、图标、菜单、文件等)的属性。程序可以通过对象的 handle
来操作这些对象。handle
本身只是一个 32 位整数,当它作为参数传递给 API 函数时,其重要性就显而易见了。
在 C# 中实现 Win32 API
说了这么多,让我们回到之前的地方。 在 C# 中,要访问这些外部 API 函数,我们需要 System.Runtime.InteropServices
命名空间。该命名空间提供了一组有用的类,用于访问 COM 对象和本机 API。其中一个重要类是 DllImportAttribute
,它用于定义包含外部方法实现的 DLL 位置,例如 Win32 API
的本机系统 API user32.dll
的 EnumWindows (..)
。C# 中的代码编写方式如下:
[DllImport("user32.Dll")]
public static extern int EnumWindows(CallBack x, int y);
extern
关键字表示该方法是在外部实现的。extern
方法必须声明为 static
。
理解回调:
请注意代码中使用的委托,如下所示:
public delegate bool IECallBack(int hwnd, int lParam);
现在让我们研究回调是如何实现的。当您单击 GetIE
按钮时,它会调用事件处理程序 GetIE_Click
。代码如下所示:
private void GetIE_Click(object sender, System.EventArgs e)
{
listBoxHandle = listBox1.Handle; //store a listbox handle here.
EnumWindows (new CallBack (IEInstance.EnumWindowCallBack),
(int)listBoxHandle) ;
label1.Text = "Total Instances of Internet Explorer : "+i;
}
private static bool EnumWindowCallBack(int hwnd, int lParam)
{
windowHandle = (IntPtr)hwnd;
listBoxHandle = (IntPtr)lParam;
// getting an instance of listbox from its handle.
ListBox lb =(ListBox)ListBox.FromHandle(listBoxHandle);
StringBuilder sb = new StringBuilder(1024);
StringBuilder sbc = new StringBuilder(256);
GetClassName(hwnd,sbc,sbc.Capacity);
GetWindowText((int)windowHandle, sb, sb.Capacity);
String xMsg = sb+" "+sbc+" "+windowHandle;
if( sbc.Length > 0 )
{
if( sbc.ToString().Equals("IEFrame"))
{
myAl.Add(windowHandle);
i++;
lb.Items.Add(xMsg); }
}
return true;
}
我们在示例中调用的委托 IECallBack
接受两个参数:hwnd
(窗口句柄)和 lParam
(应用程序定义的,任何需要传递的附加参数,在示例中我们传递了 ListBox 类的句柄)。这两个参数都是整数。我们定义一个名为 EnumWindowCallBack (..)
的函数,其签名与我们程序中的委托匹配,然后 API 函数 EnumWindows (..)
调用它来执行任务。EnumWindows (..)
枚举所有现有窗口(可见或不可见),并提供所有当前打开的顶级窗口的句柄。每次找到一个窗口时,该函数就会调用委托(名为 IECallBack
),该委托又会调用 EnumWindowCallBack (..)
函数并将窗口句柄传递给它。这是因为 API 函数(EnumWindows(..)
)只能找到句柄,但不知道如何处理它。由回调函数(EnumWindowCallBack (..)
)决定如何处理该句柄。它调用 API 函数 GetWindowText
(..)和 GetClassName
(..)来获取每个窗口的标题和类名。EnumWindow
(..)函数继续逐个传递窗口句柄,直到所有窗口都被枚举,或者直到进程被中止。如果发生错误,函数返回 0,否则返回非零值。
枚举只是回调函数使用的一个场景。其他常见的用法是为窗口等对象创建消息处理例程。因此,当 API 函数希望调用它的程序执行某些必要任务时,它会要求一个关联的回调函数。回调函数返回零表示失败,返回非零值表示成功。您会注意到我们将 EnumWindowCallBack (..)
的返回值设置为 True
以继续枚举。
函数 GetWindowText
检索普通窗口标题栏中显示的文本。它接受三个参数:要读取其标题的窗口的 handle
,一个 String 变量,用于接收窗口的文本,我们使用了 StringBuilder 对象,以便它有足够的空间来读取可变长度的字符串,最后一个参数是字符串的字节大小。
函数 GetClassName
检索窗口所属的窗口类的名称。窗口类确定一组共享同一主窗口的窗口的许多属性。其参数遵循与 GetWindowText
相同的解释。您会看到,在上面的代码中,我们只关心“IEFrame”类型的类名,因为我们只对处理 Internet Explorer 窗口感兴趣。
您一定已经注意到 IntPtr
类型的用法。它是一个整数,其大小随平台而变化(在 32 位平台上为 32 位,在 64 位平台上为 64 位)。它用于表示指针或句柄。
关闭 IE 实例
单击 CloseIE
按钮即可关闭包含 Internet Explorer 实例的窗口。请看下面的代码:
private void RemoveIE_Click(object sender, System.EventArgs e)
{
int index=listBox1.SelectedIndex;
listBox1.Items.RemoveAt(index);
int count =0;
IEnumerator myEnumerator = myAl.GetEnumerator();
while ( myEnumerator.MoveNext() ) {
if ( count == index )
{
listBoxHandle = (IntPtr)myEnumerator.Current;
break;
}
count++;
}
PostMessage(listBoxHandle,0x0010/*WM_CLOSE*/,0,0);
myAl.RemoveAt(count );
label1.Text = "Total Instances of Internet Explorer :" +myAl.Count;
}
请注意,我们使用了一个 ArrayList
类(属于 System.Collections
命名空间)来存储所有窗口句柄。当列表框中选择一个项目要移除时,我们就从 ArrayList
中提取该窗口的句柄,并使用该窗口句柄和 WM_CLOSE
消息调用 PostMessage
函数。这将关闭打开的窗口。我们还将该实例从 ArrayList
中移除,并将列表框中的选定项移除。
结论
希望以上文章能对您有所帮助。这个概念有很多好处,例如在运行时更改您的 Windows 控件中的 IE 实例。