如何强制Internet Explorer打开它当前运行的实例而不是创建一个新实例?

如何以编程方式启动IE( iexplore.exe )并在当前运行的实例中导航(通过打开新选项卡或替换当前URL)而不是创建新实例。

我已经搜索了命令行开关,并尝试使用InternetExplorer.Application ,但无济于事。

这是我需要的 (IE6-IE9会很好):

 ShellExecute(Handle, 'open', 'iexplore.exe', '"http://google.com" -single_instance', nil, SW_RESTORE); 

这是一些代码来展示我的尝试。 Delphi中的代码(部分基于如何从HWND获取IHTMLDocument2 ):

 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, eg 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; 

你的方法’1’确实有效。 至少在这里,问题是’Shell DocObject View’窗口不是顶级窗口的直接子窗口。 在IE8中,“Internet Explorer_Server”窗口是“Shell DocObject View”的子窗口,它是“TabWindowClass”的子节点,它是“Frame Tab”的子节点。 如果你可以确认’FindWindowEx’在方法1中返回0,那就是它失败的原因。 以下是修改为使用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; 

至于方法’2’,我在网上看到一些链接,表明IE不支持返回其活动对象的引用,但我没有任何官方参考。