ぐらめぬ・ぜぷつぇんのはてダ(2007 to 2011)

2007年~2011年ごろまで はてなダイアリー に書いてた記事を引っ越してきました。

WinInetのInternetGetCookie()で何度ブラウザで取れているのを確認してもERROR_NO_MORE_ITEMSが返されてしまう件


お仕事でVB6でActiveXでユーザーコントロール作ってHTMLに埋め込んでHTTP(S)通信させるまぁよくあるプログラムを組んでいるわけです。一昔前ならともかく、もはや組み合わせとしては「枯れた」感のある技術群だけあって、Googleに片端から目に付いたAPI名とか放り込んでいくだけで出来上がっちゃうご時世に感動と感謝を。

えっと、セッションCookieと普通のCookieを送出する簡単なPHPIEで表示させて、Wiresharkでパケットキャプチャして何度も「うん、ちゃんとIECookieを送出してるよな。」と確認するわけですが。

http://support.microsoft.com/kb/196062/en-us/
http://msdn.microsoft.com/en-us/library/aa384710(VS.85).aspx
http://yamamoto56.blogtribe.org/entry-2eaf3906ca43587c101c12477e9ef51c.html

ここら辺みてVBで作ったスタンドアロンのフォームから InternetGetCookie() やっても、ずーっと ERROR_NO_MORE_ITEMS で、「そんなURLに結びついたCookieなんてねぇよ。」と怒られ続けてました。
「そんな馬鹿な・・・。第二引数にはちゃんとvbNullを指定してるしで、指定したURLの全Cookieを引っ張ってくるはずだ・・・。Cookieの値をコピーする第三引数にもvbNullを指定したから、単純に第四引数のlong型バッファにCookie値のサイズだけが入ってくるはずなのに・・・。」
と30分ほど悩んで、ふとパケットキャプチャでPHPがSet-Cookieして、IECookieで送っているところを見たら。
「・・・あ? expire指定してない・・・ということはブラウザ閉じたら終わり・・・これ?」

ということでexpireを設定し直して・・・ません。すみません、ここ実験してないです。一応多分これっぽいと目処は付いたので、とっとと方向を変える事にしました。
ActiveXからブラウザのCookieを取得する方法でGoogleにいろいろ放り込んでいる内に、VBの場合ユーザーコントロールのParentプロパティが、HTMLに埋め込んで実行している場合はHTMLDocumentのオブジェクトになるので、

Parent.Script.document.cookie

で取れるよ!というのをどこかで目にして試してみたらオッケー。VCのOLEコンテナであれば、IHTMLほげほげとかいうインターフェイス経由で取得できるオブジェクトで、同様の事が可能だそうです。
もともとWebページに埋め込まれたActiveXが、HTMLのDOMノードを操作する為の機能みたいですね。

というわけで、最終的にユーザコントロールのPublicメソッド内でこんな感じで"Cookie"プロパティに設定する事で成功!

If "HTMLDocument" = TypeName(Me.Parent) Then
    Me.Cookie = Me.Parent.Script.document.cookie
End If

なんでわざわざ条件分岐させたかというと、動作確認用のスタブ(VBのフォームアプリ)からも叩くので、ユーザコントロールのParentが常にHTMLDocumentになるとは限らないからです。つまりフォームに貼り付けて使う時は、Cookieプロパティを任意に設定することができるという感じですね。本物はもうちょっと肉付けしてますが。

・・・が、まだ嵌りどころがありました。タイトル変えて続きます。