Introduction

In this article we
are going to study how to find the running instances of Internet
Explorer on your machine. This article will also provide an insight on
the windows API and how to call Win32 API functions from C#. You will
also learn how to implement callback functions.

In the code I have
extensively used the Win 32 API functions as shown below:

As we go about, I
would explain the need for these different functions. In order to use
the Win32 API functions like EnumWindows (..), and the
like we need to import the Win32 DLLs that implement these
functions.

Win32 API –a
brief explanation

The Windows API has a
number of functions, constants, callback functions, messages and
structures written in C/C++ that you can call and use in your programs.
They perform lower level services on the OS such as memory management,
process switching, disk access etc. They help the application to
interface directly with the processor. Win 32 API is created for
32-bit processor. It has a platform independent nature. A large part of
the API functions are implemented using some of these libraries like Kernel32.dll
(Operating system kernel functions), User32.dll (user interface
functions) etc. These DLL (Dynamic Link Library) files are found
wherever the Windows System directory is located. These DLL files
“export” functions thus allowing external programs to use their
functions. You would notice that I have used the concept of handles
in the program. A handle
is an internal structure in Windows that keeps track of the properties
of any object (like windows, buttons, icons, menus, files etc) in the
system. A program is able to manipulate these objects via the handle
to the object. A handle itself is just a 32-bit integer and its
significance becomes apparent when it is passed as a parameter to an API
function from a program calling those functions.

Implementation
of Win32 API in C#

That
said let us get back to where we had left ourselves. In C#, to access these external
API functions we need the namespace System.Runtime.InteropServices.
This namespace provides a collection of classes useful for accessing COM
objects, and native APIs. One of the important classes present in it is
the DllImportAttribute, which is used to define the dll location
that contains the implementation of an extern method like EnumWindows
(..) of the native system API user32.dll of Win32 API.
Shown below is the way the code is written in C#:

The
delegate in our example called IECallBack takes two arguments: hwnd
(handle to the window) and lParam (application-defined, any
additional parameter which needs to be passed, in the example we have
passed the handle to the ListBox class). Both the arguments are
integers. We define a function called EnumWindowCallBack (..) that
matches the signature of the delegate in our program and it is then
called by the API function EnumWindows (..) to
execute a task. EnumWindows (..) enumerates through
all existing windows (visible or not) and provides a handle to all of
the currently open top-level windows. Each time a window is located, the
function calls the delegate (named IECallBack) which in turn
calls the EnumWindowCallBack
(..) function and passes the window handle to it. This
is because the API function (EnumWindows(..)
can only locate the handle but does not know what to do with it. It
is upon the callback function (EnumWindowCallBack
(..) ) to decide what to do with the handle. It calls API
functions GetWindowText (..) and GetClassName (..) to
obtain the title and class name of each window. The EnumWindow
(..) function continues passing the window handles, one at a time, until
all windows have been enumerated, or until the process has been aborted.
If an error occurs, the function returns 0 else a non-zero value.

Enumeration
is just one scenario where callback functions are used. Other common
practice of using them is to create message handler routines for objects
like windows. Hence, an API function will require an associated callback
function whenever it wants the program, calling the API, to do some
necessary tasks. Callback functions return zero to indicate failure and
non-zero values to indicate success. You would notice that we have set
the return value of EnumWindowCallBack
(..) to True to continue enumeration.

The function GetWindowText
retrieves the text that appears in the title bar of the regular windows.
It takes three parameters: a
handle to the window whose title it wants to read, a
String variable that receives
the window’s text, we have taken a StringBuilder
object so that it can have enough room to read variable length strings
and the last parameter is the size in bytes of the string.

The
function GetClassName retrieves the name of the window class to
which the window belongs. The window class determines a number of
properties common to a group of windows that are inherited from a main
window. Its parameters follow the same explanation as for those of GetWindowText.
You would see that in the code above we are only concerned with
‘IEFrame’ type of class names because we are interested in dealing
with Internet Explorer windows only.

You
must have observed the use of the type IntPtr. It is an integer
whose size varies with the platform (is 32 bit on 32 bit platforms and
64 bit on 64 bit platform). It is used to represent a pointer or a
handle.

Closing an instance of IE

On clicking on the CloseIE
button we are able to close the window containing an instance of
Internet Explorer. Consider the code shown below:

Note
that we have used an ArrayList class (part of the System.Collections
namespace) to hold all the window handles. The moment an item is
selected in the listbox to be removed, we extract the handle of the
window from the ArrayList and call the PostMessage
function with that window handle and a WM_CLOSE message. This
closes the open window. We also remove the instance from the ArrayList
and the selected item from the ListBox.

Conclusion

Hope the above article was useful in explaining the concepts. This
concept has a lot of benefits like changing an instance of IE from your
windows control at run-time.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Comments and Discussions

Hi, i have a windows service which is executing EnumWindowCallBack.
The service is running as LocalSystem account and is interacting with Desktop. The service is writing all URLS opened by me in a text file. It is working fine for me BUT when i switch as a different XP user, and open any IE window, The service can not detect this new IE window.

My aim is to get running instances of IE for all users logged in.

Can some one help. I can send the code if any body is willing to help me.

Can we get IWebBrowser , IWebBrowser2 or actually InternetExplorer Application object ? from one of the instance ?
Suppose that we know url, browsed all open pages. Decided that we want to connect one of them for automation purposes how can we get com object from handle, hwnd ?
(and SHDocVw.ShellWindows is not working on vista by the way. Without using ShellWindows, ShellWindowsClass please)

Hi
I think misstyped the dll import declaration in the article.
It should be
public static extern int EnumWindows(IECallBack x, int y);
as in the source. Not
public static extern int EnumWindows(CallBack x, int y);
As the article says.

Some apps (IE is one of them) can have more than one top-level window. With his approach, it is possible to identify all instances of IE (windows, not processes), but with yours you will get only one window.

Can you help me, how can i find the running instances of an application on a network. Just like peer to peer chat programs do. I'll be grateful if you can help me with code some example (preferably in vb.net).

// Get all instances of Notepad running on the specified computer.
// 1. Using the computer alias (do not precede with "\\").
Process [] remoteByName = Process.GetProcessesByNam("notepad", "myComputer");

The RemoveIE_Click code has me worried. Your entire application depends on the two lists of data to be in sync for proper running.

What I would do is to create a small class/struct that has both pieces of data the lists store, then either override ToString or set the DisplayMember property on the listbox to point to a property on your class/struct.

Now when you want to get that IEWindow object back out, use the SelectedItem property on the listbox and cast it back to IEWindow (cast or use 'as').

Until I read this I didn't know how to do callbacks for a Win32 API call, thanks

James

Sonork: Hasaki"I left there in the morning
with their God tucked underneath my arm
their half-assed smiles and the book of rules.
So I asked this God a question
and by way of firm reply,
He said - I'm not the kind you have to wind up on Sundays.""Wind Up" from Aqualung, Jethro Tull 1971