Windows 8のデスクトップアプリケーションからHTML \ JSのModernアプリケーションのコンテンツへのアクセス

あるプログラムから別のプログラムのコンテンツにアクセスする必要がある場合があります。 たとえば、そこからコンテンツを取得したり、アクションを自動化したりします。 従来のWindowsアプリケーションの場合、この問題は非常に簡単に解決されます。FindWindowを使用して親ウィンドウを見つけ、そのHWNDを知って、子ウィンドウとその上のコントロールを一覧表示できます。 そして、ここに完全な自由があります-これらの要素に書かれたテキストを取得し、サイズと位置を変更し、マウスクリックをエミュレートするメッセージを送信したり、キーボードからテキストを入力したり、既存の要素を削除して新しい要素を作成することもできます。



しかし、現代のアプリケーションでは、すべてが異なります。 たとえば、標準のWindows8スイートの天気アプリを見てみましょう。 サイドバーで開いて、通常の(デスクトップ)アプリケーションから何とかして、それが示す温度を知りたいとします。 Spy ++を使用してWeatherウィンドウを見ると、Windows.UI.Core.CoreWindowなどの親ウィンドウと、それに囲まれたWeb Platform Embeddingウィンドウが表示されます。 そのため、HTML \ Jsで記述され、組み込みのブラウザコンポーネント内にあるモダンなアプリケーションが私たちの前にあります。 つまり、Windowsコントロールを使用した上記の操作は意味がありません。すべてのコンテンツが完全にレンダリングされるため、このウィンドウにはありません。



しかし、まだ現在の温度を取得しようとしましょう。





そもそも、MSDNには2つの記事があり、そのスタイルは正反対の内容です。他の人のコンポーネントに組み込まれているIEで手を伸ばすことは警告されます。 Active Accessibilityによる内部使用向けであり、情報提供のみを目的として文書化されています。クライアントもサーバーもこの関数を呼び出さないでください。Blah blah blah ... " )。 そして、2番目のものは、すべてが大丈夫であり、あなたができることを言い、さらにそれを行う方法についてのコードを提供します。 1つ目は私たちにとって興味のないもので、2つ目はKB 249232です。



ObjectFromLresult



、エラーがありますObjectFromLresult



関数の呼び出しで、彼らは間違ったインターフェースをとろうとしますが、その結果、何も機能しません。 しかし、これは一般にMSDNスタイルですので、慣れる必要があります。



それで、私たちのベンチャーの本質は何ですか?

  1. 指定されたタイトルとクラス(それぞれ「Weather」と「Windows.UI.Core.CoreWindow」)を持つ最上位ウィンドウを見つけます。
  2. 「子供」をリストし、「Internet Explorer_Server」クラスのウィンドウを見つけます。
  3. このウィンドウにWM_HTML_GETOBJECTメッセージを送信し、応答でポインターを取得しますObjectFromLresult



    関数を使用して、IHTMLDocument2インターフェイスへのポインターに変換できます。
  4. IHTMLDocument2を使用することで、ドキュメントで何でもできます。コンテンツの取得、変更、「クリック」のエミュレート、Javascriptの実行などです。




ポイント3〜4の領域のどこかで、Windowsセキュリティメカニズムが邪魔になり、モダンアプリケーションを互いに、またデスクトップアプリケーションから分離することはほぼ確実であり、 以前の記事で説明したツールの一部を使用する準備がすでに整っていました。 しかし... ...これは必要ありませんでした。 Weatherアプリケーションはサンドボックスで動作しているように見えますが、低整合性のようです。安全に彼にメッセージを送信し、IHTMLDocument2へのポインターを受け取り、データを交換できます。 セキュリティの障壁を克服する必要はありませんでした-それらは単に存在しません。



結果:





メインコード
 #include "stdafx.h" #include <iostream> #include <sstream> #include <mshtml.h> #include <atlbase.h> #include <oleacc.h> #include "conio.h" using namespace std; BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam) { TCHAR buf[100]; ::GetClassName( hwnd, (LPTSTR)&buf, 100 ); if ( _tcscmp( buf, _T("Internet Explorer_Server") ) == 0 ) { *(HWND*)lParam = hwnd; return FALSE; } else return TRUE; }; void GetDocInterface(HWND hWnd) { CoInitialize( NULL ); // Explicitly load MSAA so we know if it's installed HINSTANCE hInst = ::LoadLibrary( _T("OLEACC.DLL") ); if ( hInst != NULL ) { if ( hWnd != NULL ) { HWND hWndChild=NULL; // Get 1st document window ::EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild ); if ( hWndChild ) { CComPtr<IHTMLDocument2> spDoc; LRESULT lRes; UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") ); ::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes ); LPFNOBJECTFROMLRESULT pfObjectFromLresult = (LPFNOBJECTFROMLRESULT)::GetProcAddress( hInst, "ObjectFromLresult" ); if ( pfObjectFromLresult != NULL ) { HRESULT hr; hr = (*pfObjectFromLresult)( lRes, IID_IHTMLDocument2, 0, (void**)&spDoc ); if ( SUCCEEDED(hr) ) { BSTR bstrContent = NULL; IHTMLElement *p = 0; spDoc->get_body(&p); if (p) { p->get_innerHTML( &bstrContent ); std::wstring ws(bstrContent, SysStringLen(bstrContent)); std::string s(ws.begin(), ws.end()); cout << s; p->Release(); } } } } // else document not ready } // else Internet Explorer is not running ::FreeLibrary( hInst ); } // else Active Accessibility is not installed CoUninitialize(); } int _tmain(int argc, _TCHAR* argv[]) { wstring windowTitle, windowClass; wcout << "Please enter parent window title (you can find it by Spy++):" << endl; std::getline(std::wcin, windowTitle); wcout << "Please enter parent window class (you can find it by Spy++):" << endl; std::getline(std::wcin, windowClass); HWND hwnd = FindWindow(windowClass.c_str(), windowTitle.c_str()); wcout << "HWND is " << hwnd << endl; GetDocInterface(hwnd); _getch(); return 0; }
      
      







Githubのプロジェクト全体



All Articles