UWSCでウインドウハンドルからCOMオブジェクトを取得する

公式掲示板で、GetAllWinで取得できるのに、GetActiveOleObjが失敗するケースがあがっていた。
初期adminユーザーだと特定条件下でなるようなのだけど、原因は不明。
それにともなって、いろいろと調べたところ、IEを別ユーザーで起動すると、同じような状況になることがわかった。


で、別ユーザーで起動したIEのCOMオブジェクトが取得できないか、調べてみた。
どうやら「Internet Explorer_Server」のウインドウハンドルにメッセージを送ると、IHTMLDocument2オブジェクトが取得できるらしい。
スクリプトを書いてみた。



OPTION EXPLICIT

IFB GET_UWSC_NAME = "ie_getObject.uws" THEN
	DIM wid = GETID("", "IEFrame")
	DIM ie = IeObject.Get(wid)
	PRINT wid + ":" + ie + ":" + ie.document.URL
ENDIF


MODULE IeObject
	DEF_DLL RegisterWindowMessageA(string): dword: user32
	DEF_DLL SendMessageTimeoutA(dword, dword, dword, dword, dword, dword, var dword): dword: user32
	DEF_DLL ObjectFromLresult(dword, {dword, dword, dword, dword}, dword, var dword): dword: oleacc

	CONST CLASS_NAME = "Internet Explorer_Server"

	DIM _nMsg

	PROCEDURE IeObject
		_nMsg = RegisterWindowMessageA("WM_HTML_GETOBJECT")
	FEND

	FUNCTION GetIEServerHND(wid)
		RESULT = 0
		IFB STATUS(wid, ST_CLASS) = CLASS_NAME THEN
			RESULT = IDTOHND(wid)
		ELSE
			DIM wids = -1, i
			FOR i = 0 TO GETALLWIN(wid) - 1
				IFB STATUS(ALL_WIN_ID[i], ST_CLASS) = CLASS_NAME THEN
					wids = ALL_WIN_ID[i]
					BREAK
				ENDIF
			NEXT
			IF wids > -1 THEN RESULT = IDTOHND(wids)
		ENDIF
	FEND

	FUNCTION Get(wid)
		RESULT = 0
		DIM lRes = 0
		IFB SendMessageTimeoutA(GetIEServerHnd(wid), _nMsg, 0, 0, 2, 1000, lRes) THEN
			DIM ptr = 0
			// EXTERN_C const IID IID_IHTMLDocument2 = {0x332C4425,0x26CB,0x11D0,{0xB4,0x83,0x00,0xC0,0x4F,0xD9,0x01,0x19}};
			IFB lRes > 0 AND ObjectFromLresult(lRes, $332C4425, $11D026CB, $C00083B4, $1901D94F, 0, ptr) >= 0 THEN
				IFB ptr > 0 THEN
					DIM htdoc = VARTYPE(ptr, VAR_DISPATCH)
					COM_ERR_IGN
						RESULT = htdoc.parentWindow
					COM_ERR_RET
				ENDIF
			ENDIF
		ENDIF
	FEND

ENDMODULE


IID_IHTMLDocument2があれであっているのかは不明。
手元のXP環境では動作する。
IHTMLDocument2からIWebBrowser2の取得方法はQueryServiceとかするらしいのだけど、親でいいか、と適当に判断。
VARTYPEの型変換を初めて有効に使った気がする。


でも、肝心の別ユーザーのIEオブジェクトは取れなかった、、、。
多分、権限関連の処理が不足しているんじゃないか、とは思うのだけど、、、。
今のところは、以下のような関係。

ログインユーザー IE起動ユーザー UWSC起動ユーザー GetActiveOleObj スクリプト
ユーザーA ユーザーA ユーザーA
ユーザーA ユーザーB ユーザーA × ×
ユーザーA ユーザーB ユーザーB ×
ユーザーA ユーザーA ユーザーB × ×

このスクリプトが優位なのは、IEUWSCが別ユーザーの場合に、オブジェクトが取れる、ということでしょうか。


あんまり役に立たない、、、。