IWebBrowser2によるURLの取得

解決


Penguin  2007-01-11 04:25:31  No: 64192

よろしくお願いします。
Windows XP SP2
Visual Studio 2005
この様な環境です、MSDNの方で質問したのですがレスが付きそうもないので
仕方なくマルチポストのような格好になるのですが、お許しください。

現在アクティブなインターネットエクスプローラのURLを取得したいのですが、
COMコンポーネントの知識が無く、何処をどの様に修正してよいのか分かりません
間違い誤認識ございましたらご指摘願います。

下記のコードをデバッグしますと
「test1.exe の 0x0040106a でハンドルされていない例外が発生しました: 0xC0000005: 場所 0x00000000 を読み込み中にアクセス違反が発生しました。」
←印の部分でこの様なエラーが出てしまいます

#include <windows.h>
#include <tchar.h>
#include <atlbase.h>  // ATL基本機能用ヘッダファイル
#include <atlhost.h>  // ATL コンテナ機能サポート用ヘッダファイル

void main()
{
  HWND hWindow = FindWindow(L"IEFrame", NULL);  
  DWORD thid = GetWindowThreadProcessId(hWindow, NULL);
  static CComQIPtr< IWebBrowser2 > pWB2;
  BSTR LocationURL;
  char theURL[ 256 ];
  ::ZeroMemory( theURL, 256 );
  pWB2->get_LocationURL( &LocationURL );
  int n = WideCharToMultiByte( CP_ACP, 0, LocationURL, SysStringLen( LocationURL ), theURL, sizeof( theURL ) - 1, 0, 0 );
  printf ("%s", theURL);
  ::SysFreeString( LocationURL );  // リソースの開放
}


Blue  2007-01-11 19:23:58  No: 64193

ATLを使わない方法ですが、こんな感じ。
BSTRはcomdef.hの_bstr_tクラスを使うとconst char*にキャストできるので便利。
(WideCharToMultiByteはおそらく内部で処理される)

// 一番最初に見つかったInternet Explorerの表示しているURLを取得する
// 環境:Windows Xp Pro SP2/Visual C++ 6.0 Enter SP6/Internet Explorer 6.0 SP2
#include <windows.h>
#import <shdocvw.dll>
#import <mshtml.tlb>

HRESULT GetIEURL( _bstr_t& url )
{
    HRESULT hr = S_OK;

    SHDocVw::IShellWindowsPtr pSW = NULL;

    try
    {
        hr = pSW.CreateInstance( __uuidof( SHDocVw::ShellWindows ) );
        if ( FAILED( hr ) ) _com_issue_error( hr );

        // Internet Explorer と Explorere が列挙される
        for ( long i = 0; i < pSW->Count; ++i )
        {
            SHDocVw::IWebBrowser2Ptr pIE = NULL;
            if ( pIE = pSW->Item( i ) )
            {
                MSHTML::IHTMLDocumentPtr pDoc = NULL;
                if ( pDoc = pIE->GetDocument() ) // IInternet Explorerかどうか判定
                {
                    url = pIE->GetLocationURL();
                    break;
                }
            }
        }
    }
    catch (_com_error& e)
    {
        hr = e.Error();
    }
    if ( pSW ) pSW.Release();

    return hr;
}

int main()
{
    if ( SUCCEEDED( ::CoInitialize( NULL ) ) )
    {
        _bstr_t url;
        if ( SUCCEEDED( GetIEURL( url ) ) )
        {
            // 確認
            ::MessageBox( NULL, url, TEXT( "URL" ), MB_OK );
        }
        ::CoUninitialize();
    }
    return 0;
}


Blue  2007-01-11 19:56:03  No: 64194

ちなみに
>現在アクティブなインターネットエクスプローラの
が微妙ですが、任意のウィンドウハンドルをもつIEを限定する場合、
SHDocVw::IWebBrowser2PtrのGetHWND(もしくはHWND)で取得できる値を
HWND型にキャストすると判定できます。

但し、IEコンポーネントを使っているようなアプリ(たとえばSleipnirとか)
を使っている場合、

pIE->GetHWND();

で取得しようとすると_com_errorが発生します。
なので、ここだけは邪道ですが、get_HWNDをつかって戻り値で成功しているか判定します。)

以下変更したコード
// 指定したウィンドウハンドルを持つInternet Explorerの表示しているURLを取得する
// 環境:Windows Xp Pro SP2/Visual C++ 6.0 Enter SP6/Internet Explorer 6.0 SP2
#include <windows.h>
#import <shdocvw.dll>

HRESULT GetIEURL( _bstr_t& url, const HWND target )
{
    HRESULT hr = S_OK;

    SHDocVw::IShellWindowsPtr pSW = NULL;

    try
    {
        hr = pSW.CreateInstance( __uuidof( SHDocVw::ShellWindows ) );
        if ( FAILED( hr ) ) _com_issue_error( hr );

        for ( long i = 0; i < pSW->Count; ++i )
        {
            SHDocVw::IWebBrowser2Ptr pIE = NULL;
            if ( pIE = pSW->Item( i ) )
            {
                long hWnd;
                if ( SUCCEEDED( pIE->get_HWND( &hWnd ) ) && 
                     ( reinterpret_cast< HWND >( hWnd ) == target ) )
                {
                    url = pIE->GetLocationURL();
                    break;
                }
            }
        }
    }
    catch (_com_error& e)
    {
        hr = e.Error();
    }
    if ( pSW ) pSW.Release();

    return hr;
}

int main()
{
    if ( SUCCEEDED( ::CoInitialize( NULL ) ) )
    {
        _bstr_t url;
        HWND target = ::FindWindow( TEXT( "IEFrame" ), NULL );
        if ( target && SUCCEEDED( GetIEURL( url, target ) ) )
        {
            ::MessageBox( NULL, url, TEXT( "URL" ), MB_OK );
        }
        ::CoUninitialize();
    }
    return 0;
}

ただ、ウィンドウハンドルがわかるのであれば、別にIWebBrowser2を使う必要もないかなぁと。
(SendMessageとか使っていけばEditにある文字列を取得することが出来そうな)


Penguin  2007-01-13 08:18:51  No: 64195

ありがとうございました
コードまで書いていただきお手数おかけしました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加