How to force Internet Explorer to open it's current running instance rather than creating a new one?
c#, c++, delphi, internet-explorer, winapi
Solution
Your method '1' actually works. The problem, at least here, is that 'Shell DocObject View' window is not an immediate child of the top-level ie window. Here with IE8, 'Internet Explorer_Server' window is a child of 'Shell DocObject View', which is a child of 'TabWindowClass', which is a child of 'Frame Tab'. If you can confirm 'FindWindowEx' returns 0 in method 1, that's why it fails. The below is the code modified to use `EnumChildWindows`:
function EnumChilds(hwnd: HWND; lParam: LPARAM): BOOL; stdcall;
const
Server = 'Internet Explorer_Server';
var
ClassName: array[0..24] of Char;
begin
GetClassName(hwnd, ClassName, Length(ClassName));
Result := ClassName <> Server;
if not Result then
PLongWord(lParam)^ := hwnd;
end;
function GetActiveIEServerWindow(const Activate: Boolean=True): HWND;
var
Wnd, WndChild: HWND;
begin
Result := 0;
Wnd := FindWindow('IEFrame', nil); // top level IE
if Wnd <> 0 then
begin
// WndChild := FindWindowEx(Wnd, 0, 'Shell DocObject View', nil);
// if WndChild <> 0 then
// begin
// WndChild := FindWindowEx(WndChild, 0, 'Internet Explorer_Server', nil);
WndChild := 0;
EnumChildWindows(Wnd, @EnumChilds, LongWord(@WndChild));
if WndChild <> 0 then
begin
Result := WndChild;
if Activate then
begin
if IsIconic(Wnd) then
ShowWindow(Wnd, SW_RESTORE)
else
SetForegroundWindow(Wnd);
end;
end;
// end;
end;
end;
As for method '2', I've seen a few links on the web that state IE does not support returning a reference for its active object, but I don't have any official reference for that.
Problem
How to programatically launch IE (`iexplore.exe`) and navigate in the current running instance (by opening a new tab, or replacing the current URL) Rather than creating a new instance. I have searched for a command line switch, and tried using `InternetExplorer.Application`, to no avail. Here is a pseudo of what I need (IE6-IE9 would be nice): ``` ShellExecute(Handle, 'open', 'iexplore.exe', '"http://google.com" -single_instance', nil, SW_RESTORE); ``` Here is some code to demonstrate my attempts. code in Delphi (partly based on How to get IHTMLDocument2 from a HWND): ``` implementation uses ShellApi, ComObj, ActiveX, SHDocVw, MSHTML; function GetIEFromHWND(WHandle: HWND; var IE: IWebbrowser2): Boolean; type TObjectFromLResult = function(LRESULT: lResult; const IID: TIID; wParam: WPARAM; out pObject): HRESULT; stdcall; var hInst: HMODULE; lRes: Cardinal; Msg: UINT; pDoc: IHTMLDocument2; ObjectFromLresult: TObjectFromLresult; begin Result := False; hInst := LoadLibrary('oleacc.dll'); if hInst <> 0 then try @ObjectFromLresult := GetProcAddress(hInst, 'ObjectFromLresult'); if @ObjectFromLresult <> nil then begin Msg := RegisterWindowMessage('WM_HTML_GETOBJECT'); if SendMessageTimeOut(WHandle, Msg, 0, 0, SMTO_ABORTIFHUNG, 1000, lRes) <> 0 then if ObjectFromLresult(lRes, IHTMLDocument2, 0, pDoc) = S_OK then begin (pDoc.parentWindow as IServiceprovider).QueryService( IWebbrowserApp, IWebbrowser2, IE); Result := IE <> nil; end; end; finally FreeLibrary(hInst); end; end; function GetActiveIEServerWindow(const Activate: Boolean=True): HWND; var Wnd, WndChild: HWND; begin Result := 0; Wnd := FindWindow('IEFrame', nil); // top level IE if Wnd <> 0 then begin 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 Result := WndChild; if Activate then begin if IsIconic(Wnd) then ShowWindow(Wnd, SW_RESTORE) else SetForegroundWindow(Wnd); end; end; end; end; end; // Method 1 procedure TForm1.Button1Click(Sender: TObject); const navOpenInNewTab = $800; var IEServerWnd: HWND; IE: IWebBrowser2; begin IEServerWnd := GetActiveIEServerWindow; if (IEServerWnd <> 0) and GetIEFromHWnd(IEServerWnd, IE) then begin // *** this opens the Default browser, e.g Google Chrome // *** if IE is the Default browser, an empty new window is opened. OleVariant(IE).Navigate('http://www.yahoo.com', Longint(navOpenInNewTab)); end else begin ShellExecute(Handle, 'open', 'iexplore.exe', '"http://google.com"', nil, SW_RESTORE); end; end; procedure InternetExplorerNavigate(URL: WideString); const navOpenInNewTab = $800; var IE: OleVariant; begin try // *** this always fails (security constraints?) IE := GetActiveOleObject('InternetExplorer.Application'); except IE := CreateOleObject('InternetExplorer.Application'); end; IE.Visible := True; IE.Navigate(URL, Longint(navOpenInNewTab)); end; // Method 2 procedure TForm1.Button2Click(Sender: TObject); begin InternetExplorerNavigate('http://google.com'); end; ```