Automating IE
Connect to a running instance of Internet
Explorer
1. Using ObjectFromLResult.
You can use function ObjectFromLResult to
obtain an interface to IHtmlDocument2 or IWebbrowser2 from a running
instance of IE, if you have a "Internet Explorer_Server"
HWND.
The following shows a Spyxx-picture of the structure
of a running instance of IE.
To reach Internet Explorer_Server we need to go from
IEFrame -> Shell DocObject View
-> Internet Explorer_server.
In this example there is also another instance you
can connect to:
IEFrame -> BaseBar ->
RebarWindow32 -> OCHost -> Shell Embeddeding -> Shell
DocObject View -> Internet Explorer_server.
It is because the Search Explorer is opened and
contain a Webbrowser document.
The following sample will do the following:
If a instance of Internet Explorer is running, we
will connct to it - using the ObjectFromLResult function - and
direct the browser to IE & Delphi Homepage.
Then we will open the Search Explorer Bar in the
browser and replace the normal content with a different content -
using the same function.
ObjectFromLResult is a MSAA function (Microsoft
Active Accessibility) and is located in oleacc.dll. In Windows 2000
and Windows NT with Service Pack 6 MSAA is part of the operating
system, but on older version you might need to install MSAA runtime
components:
MSAA
Runtime Components (RDK)
type
TObjectFromLResult = function(LRESULT: lResult; const
IID: TIID; WPARAM: wParam; out pObject): HRESULT; stdcall;
function GetIEFromHWND(WHandle: HWND; var IE: IWebbrowser2): HRESULT;
var
hInst: HWND;
lRes: Cardinal;
MSG: Integer;
pDoc: IHTMLDocument2;
ObjectFromLresult: TObjectFromLresult;
begin
hInst := LoadLibrary('Oleacc.dll');
@ObjectFromLresult := GetProcAddress(hInst, 'ObjectFromLresult');
if @ObjectFromLresult <> nil then begin
try
MSG :=
RegisterWindowMessage('WM_HTML_GETOBJECT');
SendMessageTimeOut(WHandle, MSG, 0, 0,
SMTO_ABORTIFHUNG, 1000, lRes);
Result := ObjectFromLresult(lRes, IHTMLDocument2,
0, pDoc);
if Result = S_OK then
(pDoc.parentWindow as
IServiceprovider).QueryService(IWebbrowserApp, IWebbrowser2, IE);
finally
FreeLibrary(hInst);
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Wnd: HWND;
WndChild: HWND;
x: Olevariant;
vaClsID, vaEnabled, vaDummy: Olevariant;
BarIE, IE: iwebbrowser2;
begin
Wnd := FindWindow('IEFrame', nil);
if Wnd = 0 then //No running instance of Internet
Explorer so stop!
begin
showmessage('No Running instance of Internet Explorer');
exit;
end;
// walk Shell DocObject View->Internet Explorer_Server
WndChild := FindWindowEX(Wnd, 0, 'Shell DocObject View', nil);
if WndChild <> 0 then begin
WndChild := FindWindowEX(WndChild, 0, 'Internet
Explorer_Server', nil);
if WndChild <> 0 then
begin
GetIEFromHWnd(WndChild, IE); //Get
Iwebbrowser2 from Handle
//Navigate to IE & Delphi
IE.Navigate('http://www.euromind.com/iedelphi',
x, x, x, x);
vaCLSID :=
'{30D02401-6A81-11D0-8274-00C04FD5AE38}';
vaEnabled := True;
vaDummy := 0;
// open Search Explorer Bar
IE.ShowBrowserBar(vaCLSID, vaEnabled, vaDummy);
// find Internet
Explorer_Server for Search Explorer Bar
WndChild :=
FindWindowEX(Wnd, 0, 'Basebar', nil);
if WndChild <> 0 then begin
WndChild := FindWindowEX(WndChild,
0, 'RebarWindow32', nil);
if WndChild <> 0 then
begin
WndChild :=
FindWindowEX(WndChild, 0, 'OCHost', nil);
if WndChild
<> 0 then begin
WndChild
:= FindWindowEX(WndChild, 0, 'Shell Embedding', nil);
if
WndChild <> 0 then begin
WndChild := FindWindowEX(WndChild, 0, 'Shell DocObject View', nil);
if
WndChild <> 0 then begin
WndChild := FindWindowEX(WndChild, 0, 'Internet Explorer_Server', nil);
if WndChild <> 0 then
begin
GetIEFromHWnd(WndChild, BarIE); //Get Iwebbrowser2 from Handle
BarIE.Navigate('www.euromind.com/iedelphi/ie5tools/automate.htm', x, x, x,
x);
//Navigate Search Explorer Bar
end;
end;
end;
end;
end;
end;
end;
end;
end;
|
2. Using IShellWindows
Click Button1 to have the locationurls from all
running instances of Internet Explorer - including open folders and
Windows Explorer - shown in a listbox.
uses
shdocvw_tlb;
procedure TForm1.Button1Click(Sender: TObject);
var
x: Integer;
Sw: IShellWindows;
begin
sw := CoShellWindows.Create;
for x := 0 to SW.Count - 1 do
Listbox1.Items.Add((Sw.Item(x) as IWebbrowser2).LocationUrl);
end; |
Sinking events from IShellWindows.
DShellWindowsEvent has two events
OnWindowRegistered (called when a new instance of IE is created) and
OnWindowRevoked (called whel an instance of IE is closed).
Drop a DShellWindowEvent-component on your form and
connect it to your instance of IShellwindows:
var
sw : Ishellwindows;
begin
sw := CoShellWindows.Create;
DshellwindowsEvents1.Connect(sw);
end;
|
The following code will keep track of running instances of Internet
Explorer - add or remove them from a listbox based on information
from OnWindowRegistered and OnWindowRevoked
uses
shdocvw_tlb;
procedure TForm1.DShellWindowsEvents1WindowRegistered(Sender:
TObject;lCookie: Integer);
begin
Listbox1.Items.Add('Instance with Cookie no: '+InttoStr(lCookie));
end;
procedure TForm1.DShellWindowsEvents1WindowRevoked(Sender:
TObject;lCookie: Integer);
begin
Listbox1.Items.Delete(Listbox1.Items.IndexOf('Instance with Cookie no: '+InttoStr(lCookie)));
end;
procedure TForm1.FormCreate(Sender: TObject);
var
sw : Ishellwindows;
begin
FormStyle:=fsStayOnTop;
sw := CoShellWindows.Create;
DshellwindowsEvents1.Connect(sw);
end;
|
Sending commands to a running instance of IE
You can obtain an IWebbrowser2-interface from each
of the running instances listed in IShellwindows by simple
typecasting if
WB:=Shellwindows.Items(x) as IWebbrowser2;
The following code will close all running instances of IE when
Button1 is clicked:
procedure TForm1.Button1Click(Sender: TObject);
var
x : Integer;
sw: Ishellwindows;
wb: IWebbrowser2;
begin
sw := CoShellWindows.Create;
for x := 0 to sw.count do
begin
WB := Sw.Item(x) as IWebbrowser2;
if wb<>nil then WB.Quit;
end;
end;
|
Sinking Events from a running instance of IE.
Drop a DWebbrowserEvents2-component on your
form and connect it to an instance of IE by using
DWebbrowserEvents21.Connect(IE);
var
ShellWin : shdocvw_tlb.IShellWindows;
IE : IWebbrowser2;
begin
IE:=shellwin.Item(Shellwin.Count-1) as IWebbrowser2;
DWebbrowserEvents21.Connect(IE);
end;
|
The following code opens a new instance of IE, lets it navigate and
captures the statustext-change in a listbox:
uses
shdocvw_tlb;
procedure TForm1.Button1Click(Sender: TObject);
var
x: Olevariant;
sw: Ishellwindows;
wb: IWebbrowser2;
begin
WB := CoInternetExplorer.Create;
WB.Visible := True;
DWebbrowserEvents21.Connect(WB);
WB.Navigate('http://www.euromind.com/iedelphi', x, x, x, x);
end;
procedure TForm1.DWebBrowserEvents21StatusTextChange(Sender:
TObject;const Text: WideString);
begin
listbox1.items.add(text);
end;
procedure TForm1.DWebBrowserEvents21Quit(Sender: TObject);
begin
DWebbrowserEvents21.DisConnect;
end;
|
The demo LogView demonstrates how to log
events from all running instances of IE to a common log-listbox. The
demo uses DWebbrowserEvents2 and ShellWindowEvents:
var
ShellWin: IShellWindows; //NB!!
Connection: Integer;
procedure InterfaceConnect(const Source: IUnknown; const IID: TIID;
const Sink: IUnknown; var Connection: Longint);
var
CPC: IConnectionPointContainer;
CP: IConnectionPoint;
begin
Connection := 0;
if Succeeded(Source.QueryInterface(IConnectionPointContainer, CPC)) then
if Succeeded(CPC.FindConnectionPoint(IID, CP)) then
CP.Advise(Sink, Connection);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
X: Integer;
begin
ShellWin := CoShellWindows.Create;
ShellWinEvents.Connect(ShellWin);
for x := 0 to ShellWin.Count - 1 do
InterfaceConnect(ShellWin.Item(x) as IWebbrowser2, DwebbrowserEvents2, WBevents, Connection);
end;
procedure TForm1.ShellWinEventsWindowRegistered(Sender: TObject; lCookie: Integer);
begin
InterfaceConnect(ShellWin.Item(ShellWin.Count - 1) as IWebbrowser2, DwebbrowserEvents2, WBevents, Connection);
end;
procedure TForm1.WBEventsBeforeNavigate2(Sender: TObject;
const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
Headers: OleVariant; var Cancel: WordBool);
begin
listbox1.items.add(url);
end;
|
Links:
Q176792 - HOWTO- Connect to a Running Instance of Internet Explorer
Q249232 - HOWTO- Get IHTMLDocument2 from a HWND