如何强制Internet Explorer中打开它的当前运行的实例,而不是创建一个新的? [英] How to force Internet Explorer to open it's current running instance rather than creating a new one?
问题描述
如何以编程方式启动IE浏览器( IEXPLORE.EXE
),并在当前正在运行的实例导航(打开一个新标签,或替换当前URL)而不是创建新实例。
我已经寻找一个命令行开关,并尝试使用 InternetExplorer.Application
,都无济于事。
下面是一个伪的什么,我需要(IE6-IE9将是不错):
的ShellExecute(手柄,开放,IEXPLORE.EXE,
'http://google.com-single_instance',
为零,SW_RESTORE);
下面是一些代码来证明我的尝试。在Delphi代码(部分基于如何从HWND 得到的IHTMLDocument2):
实施
使用ShellAPI的,ComObj,ActiveX等SHDOCVW,MSHTML;
功能GetIEFromHWND(例WHandle:HWND; VAR IE:IWebBrowser2的):布尔;
型
TObjectFromLResult =功能(LRESULT:LRESULT; const的IID:TIID;
的wParam:WPARAM;出pObject):HRESULT; STDCALL;
变种
HINST:HMODULE;
LRES:红衣主教;
消息:UINT;
PDOC:的IHTMLDocument2;
ObjectFromLresult:TObjectFromLresult;
开始
结果:=假;
HINST:=调用LoadLibrary('oleacc.dll');
如果HINST<> 0,那么
试
@ObjectFromLresult:= GetProcAddress的(HINST,'ObjectFromLresult');
如果@ObjectFromLresult<>零然后
开始
消息:= RegisterWindowMessage('WM_HTML_GETOBJECT');
如果SendMessageTimeOut(例WHandle,味精,0,0,SMTO_ABORTIFHUNG,1000,LRES)LT;> 0,那么
如果ObjectFromLresult(LRES,的IHTMLDocument2,0,PDOC)= S_OK然后
开始
(pDoc.parentWindow为的IServiceProvider).QueryService(
IWebbrowserApp,IWebBrowser2的,IE);
结果:= IE<>零;
端;
端;
终于
FreeLibrary则(HINST);
端;
端;
功能GetActiveIEServerWindow(常量激活:布尔= TRUE):HWND;
变种
Wnd中,WndChild:HWND;
开始
结果:= 0;
Wnd中:= FindWindow函数('IEFrame',无); //顶级IE
如果Wnd中<> 0,那么
开始
WndChild:= FindWindowEx(Wnd中,0,壳牌DocObject的视图,无);
如果WndChild<> 0,那么
开始
WndChild:= FindWindowEx(WndChild,0,'互联网Explorer_Server',无);
如果WndChild<> 0,那么
开始
结果:= WndChild;
如果激活然后
开始
如果IsIconic(Wnd中),那么
的ShowWindow(Wnd中,SW_RESTORE)
,否则
SetForegroundWindow(Wnd中);
端;
端;
端;
端;
端;
//方法1
过程TForm1.Button1Click(发件人:TObject的);
常量
navOpenInNewTab = $ 800元;
变种
IEServerWnd:HWND;
IE:IWebBrowser2的;
开始
IEServerWnd:= GetActiveIEServerWindow;
如果(IEServerWnd<> 0)和GetIEFromHWnd(IEServerWnd,IE),那么
开始
// ***这将打开默认浏览器,如谷歌浏览器
// ***如果IE为默认浏览器,打开一个空的新窗口。
OleVariant(IE)的.Navigate('http://www.yahoo.com',Longint型(navOpenInNewTab));
端
,否则
开始
的ShellExecute(手柄,开放,IEXPLORE.EXE,
'http://google.com,
为零,SW_RESTORE);
端;
端;
程序InternetExplorerNavigate(网址:WideString的);
常量
navOpenInNewTab = $ 800元;
变种
IE:OleVariant;
开始
试
// ***这个总是失败(安全约束?)
IE:= GetActiveOleObject('InternetExplorer.Application');
除了
IE:= CreateOleObject('InternetExplorer.Application');
端;
IE.Visible:= TRUE;
IE.Navigate(URL,Longint型(navOpenInNewTab));
端;
//方法2
过程TForm1.Button2Click(发件人:TObject的);
开始
InternetExplorerNavigate('http://google.com');
端;
您的方法'1',实际工作。这个问题,至少在这里,是壳牌DocObject的视图窗口不是顶级的IE窗口的直接子。这里用IE8,互联网Explorer_Server窗口的壳牌DocObject的视图',这是'TabWindowClass',这是'帧标签'的孩子的孩子的孩子。如果你能在1的方法确认FindWindowEx'返回0,这就是为什么它失败。以下是修改为使用 EnumChildWindows
中的代码:
函数EnumChilds( HWND:HWND; lParam:一个LPARAM):BOOL; STDCALL;
常量
服务器='互联网Explorer_Server';
变种
类名:数组[0..24]字符的;
开始
GetClassName(HWND,类名,长度(类名));
结果:=类名<>服务器;
如果没有结果,那么
PLongWord(lParam的)^:= HWND;
端;
功能GetActiveIEServerWindow(常量激活:布尔= TRUE):HWND;
变种
Wnd中,WndChild:HWND;
开始
结果:= 0;
Wnd中:= FindWindow函数('IEFrame',无); //顶级IE
如果Wnd中<> 0,那么
开始
// WndChild:= FindWindowEx(Wnd中,0,壳牌DocObject的视图,无);
//如果WndChild<> 0,那么
//开头
// WndChild:= FindWindowEx(WndChild,0,'互联网Explorer_Server',无);
WndChild:= 0;
EnumChildWindows(Wnd中,@EnumChilds,长字(@WndChild));
如果WndChild<> 0,那么
开始
结果:= WndChild;
如果激活然后
开始
如果IsIconic(Wnd中),那么
的ShowWindow(Wnd中,SW_RESTORE)
,否则
SetForegroundWindow(Wnd中);
端;
端;
//结束;
端;
端;
至于方法'2',我已经看到了说明IE浏览器在网络上几个环节不支持返回其活动对象的引用,但我没有对任何官方的参考。
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;
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 offical reference for that.
这篇关于如何强制Internet Explorer中打开它的当前运行的实例,而不是创建一个新的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!