.NET Framework 2.0 と C#での開発ブログ -2ページ目

.NET 2.0 axWebBrowserのNewWindow2イベントでURLを取得する

今回もまた.NET 2.0 axWebBrowserについてですが、NewWindow2イベントでのURL取得方法です。

.Net2.0ではNewWindow3があるので簡単にURLが取得できるのですが、確かこれはXP SP2以降でしかイベント発生しないので、今一頼れません。
(関係ないですがイベントの発生を英語でFireっていうのはカッコいい、、、発生っていうか発射?撃て!って感じ)

なので、もちろんNewWindow3も使うのですが、NewWindow2でもURLが取得できれば色々できますね、あんなことやこんなことも、、、、

ただ、これは結構面倒?(うざい)ことやりました。
なにかというと、普通ではNewWindow2ではURL情報取得できないので、実際に一回ウィンドウを新たに開いてからそのURLを取得して、情報を戻す。っていうもう無駄なことだらけなことやります。

私の場合では
axWebBrowserを2つ用意して、ひとつは通常に使うよう、もうひとつはサイズ0で非表示、サイレントなものです。この後者のブラウザをつかってURLを取得するようにしました。

あとはメインのaxWebBrowserのNewWindow2で下記のようにします。

-----------------------------------------------------------
private void axWebBrowser_NewWindow2(object sender, AxSHDocVw.DWebBrowserEvents2_NewWindow2Event e)
{
this.SecondBrowser.RegisterAsBrowser = true;
e.ppDisp = this.SecondBrowser.Application;
}
-----------------------------------------------------------
(SeccondBrowserはサイズ0で非表示、サイレントのやつです)

こんな感じでe.ppDispをつかって新しく開いてあげます。

次に

-----------------------------------------------------------
private void SecondBrowser_BeforeNavigate2(object sender, AxSHDocVw.DWebBrowserEvents2_BeforeNavigate2Event e)
{
e.cancel = true;
URL = e.uRL
}
-----------------------------------------------------------

SeccondBrowserのBeforeNavigate2でさっそくキャンセル+URLの取得をしてます。
実際にはURLを取得っていうかここで色々処理してあげれば良いですね。

以上、こんな感じでURLを取得できます。

.NET 2.0 axWebBrowserで表示しているページにJavascriptを挿入する

以前に.NET 2.0 WebBrowserで表示しているページにJavascriptを挿入する方法を取り上げましたが、今回は私がaxWebbrowserでの開発に切り替えたこともあり、.NET 2.0 axWebBrowserで表示しているページにJavascriptを挿入する私なりの方法をご紹介します。


はじめに、どうもVS2005でのaxWebbrowserはAxSHDocVw, SHDocVwのバージョンが違うらしく(当たり前か)ググって見ても、情報はあるのですが、そのまま使えるって情報は今はあまりなかったです。
ああ、それと、当然mshtml.dllは使わない方法でのご紹介です。配布を考えたらmshtml.dllのサイズはありえないですからね。

まずはじめに、サンプルソースです。(あんまり参考にしないようにW)

------------------------------------------------
// ↓ <wbr>は意味無いけどなんかないとinsert出来ないので適当に入れてる。問題あるかも
string jsstr = "<wbr>\n";
jsstr = jsstr + "<SCRIPT DEFER language='JavaScript' type='text/JavaScript'>\n";
jsstr = jsstr + "<!-- \n";
jsstr = jsstr + " [ ここにJSを記述する ] \n";
jsstr = jsstr + "// -->\n";
jsstr = jsstr + "</SCRIPT>\n";

Type typ = Type.GetTypeFromCLSID(new System.Guid("{3050F4E7-98B5-11CF-BB82-00AA00BDCE0B}"));
object html_body = typ.InvokeMember("body", BindingFlags.GetProperty, null, axWebBrowser1.Document, null);

object[] args;
args = new object[] { "AfterBegin", jsstr };
typ.InvokeMember("insertAdjacentHTML", BindingFlags.InvokeMethod, null, html_body, args);
------------------------------------------------
(こうやってまとめると少ないな、、、時間かかったのに、、、)

さて、簡単に解説ですが、まず初めにScriptタグと実スクリプトをStringで作ります。
ここでの注意は見た人は必ず???ってなる <wbr> これですが、、、私も良くわかってないのですが、SCRIPTタグの前にスペースでもなんでもいいのでなにかがないと[insertAdjacentHTML]が私の場合出来なかったのです。これの理由はさっぱりで、これに気がつかなかったため、どんなに[insertAdjacentHTML]しても追加されないで長い間悩まされました。
たとえば、"<SCRIPT></SCRIPT>"を追加しても、実際にはなにも追加されません。次に"<div></div>"これはちゃんと追加されます。あと普通に"テスト"も問題なく追加されます。では、"<div><SCRIPT></SCRIPT></div>"とやるとどうなるでしょう?なんと "<div></div>" だけが追加されます。
 ふぬー意味わからんが[insertAdjacentHTML]はなんかやってるみたいですね。なので、色々実験した結果、たとえば"<br><SCRIPT></SCRIPT>"ってやるとちゃんとSCRIPTの部分も追加されることを発見しました。ってことは閉じるタグ無しのタグだったらいいのか、、、なんか抜け道っぽいっすね。
ただ、"<BR>"だと改行されてしまいますし、Headに入れるのも問題ですので、閉じるタグがいらない意味の無いタグを探して<wbr>にして見ました。<WBR>はNetscape Navigatorが独自に追加したタグで、<NOBR> - </NOBR>で自動改行をさせないようにした箇所の中で、改行しても良い位置を指定するために使われるそうです。まずめったなことでは使われないタグですね。IE系ではちゃんと無視されてるぽいですし、<NOBR>の中に無い限り無意味なのでこれにしました。これを<body>の直ぐあとにいれれば<NOBR>の中に入る可能性0ですね。
本来ならinsertAdjacentElementとかあればこんなことしなくてもいいのですが、これが見つからないんですねぇ~絶対あると思うのに。

つぎにmshtml.dllを使わない body の取得ですが、これはググれば情報あるので、完結に。
ようはaxWebBrowserのDocumentに対しInvokeMemberでbodyのプロパティを取得するってことっすね。

object html_body = typ.InvokeMember("body", BindingFlags.GetProperty, null, axWebBrowser1.Document, null);

↓objectの入れ物に
object html_body =

↓InvokeMemberを使って
typ.InvokeMember

↓bodyの要素を指定して
("body"

↓プロパティを取得
, BindingFlags.GetProperty

↓とりあえず無視
, null

↓axWebBrowserのDocumentから
, axWebBrowser1.Document

↓引数は無しよ
, null);

こんな感じ?

んでもって今度はInvokeMemberを使って[insertAdjacentHTML](追加)します。
今回は引数が必要なメソッドなのでまず、引数を指定します。
上記のサンプルでは 場所は"AfterBegin"で入れるのはjsstr(最初に作成したSCRIPTタグ)ですよ。って感じに。
んで、実際の処理ですが

typ.InvokeMember("insertAdjacentHTML", BindingFlags.InvokeMethod, null, html_body, args);

↓InvokeMemberを使って
typ.InvokeMember

↓利用したい名前を指定して
("insertAdjacentHTML",

↓メソッドを実行して
BindingFlags.InvokeMethod

↓とりあえず無視して
, null

↓bodyエレメントに対して
, html_body

↓この引数でお願いね
, args);

以上、これでちゃんと動きました。
以前のとちがって外部JSじゃなくていいので安心だし、無駄なファイルがなくていいですね。


.NET Framework 2.0 WebBrowserコントロールの利用を断念

今までなんとか.NET Framework 2.0 のWebBrowserコントロールでブラウザを作ってきたのですが、前の記事でも愚痴ったとおり、どうしてもFlash問題とWindowClosingの問題が回避できず、ついにAxWebBrowserを使って作り直すことにしました。
さすがにFlashも
WindowClosingも正常に動きますね(当然?W)

ただ、折角つくったPOPUP BlockやJS処理、ステータスバー等々諸々がやり直しなのはとっても気力がそがれます、、、でも、これはやれば終わるから、、、がんばればいつかは幸せになれるさ、、、

はぁ~~なんか悪いこと続き。

C#でMecabのDLLを利用する 2

前回MecabのDLLをC#で利用する方法をご紹介しましたが、確かに問題なく動作するのですが、開発PC以外での環境(私の場合はノートPC)で動作させてみたら、なぜか強制終了が頻発したので泣く泣くEXE版に戻しました。 まだ1台でしかテストしてないので実際には他の環境でどのようになるかわかりませんので後ほど余裕ができたらもっと煮詰めて調査したいと思います。

あー残念。

.NET Framework 2.0 WebBrowserでFlashが正しく動作しない 2

前回の.NET Framework 2.0 WebBrowserでFlashが正しく動作しないの続編、、、って行きたいのですが、





駄目だ、、、MSのバグってのはわかったんだが、だからってどうしろと!?
待てと?待つのか?ありえない!

ここのところ、この問題ばっかり調べててなんにも進まないので気が狂いそうです。

あ~も~いやだ~。
もう、直接axWebBrowser使おうかとも思ってますが、そうすると今までの開発のかなりの部分がやり直し、、、
しかもなんか.net frameworkの意味ないしなぁ~。

だれかた~す~け~て~

以上、愚痴でした。

.NET 2.0 WebBrowserで表示しているページにJavascriptを挿入する

今回は.NET 2.0 WebBrowserで表示しているページにJavascriptを挿入する方法のご紹介です。
(ご紹介できるほどのものかどうかはおいといて、、、自分のメモのために)

これを実現するにはHtmlDocumentオブジェクトに対して
[CreateElement][SetAttribute][InsertAdjacentElement]の3つの処理を行います。
([InsertAdjacentElement]の代わりに[AppendChild]でもOKです)

まず、InsertAdjacentElementをするにはWebBrowserコントロールの DocumentCompleted イベントが発生した後である必要があります。

なので、例えばDocumentCompletedイベントハンドラに下記のような処理をします。

[例]
---------------------------------------------------------
HtmlDocument doc = webBrowser1.Document;
if(doc == null) return;

HtmlElement jsElem = doc.CreateElement("SCRIPT");
jsElem.SetAttribute("language", @"JavaScript");
jsElem.SetAttribute("type", @"text/JavaScript");
jsElem.SetAttribute("src", "外部JSファイルへのパス");

if (doc.Body == null) return;
doc.Body.InsertAdjacentElement(HtmlElementInsertionOrientation.BeforeEnd, jsElem);
---------------------------------------------------------
(あくまでも例ですので、、、)

本来なら、CreateElementでHtmlElementを作ったら、それのInnerHtml(or InnerText)にスクリプトを記述すれば良いはずなのですが、なぜか出来ません、、、説明によればSCRIPTのHtmlElementは子要素が持てないからだそうです。
でも生成されたHtmlElementをみるとちゃんと<SCRIPT></SCRIPT>ってなります。でも子要素が持てない、、、んなばかな!
かなりぶーぶー文句たれながらドキュメントを読んでたのですが、、、どうにもならないので、まあ、これは外部JS使えよって規制があるもんだと思って前に進めます。

次に作成したHtmlElementに[SetAttribute]を使ってSCRIPTタグを完成させます。
最後に[InsertAdjacentElement]を使って作成したHtmlElementを適応します。
ここで注意がHtmlElementInsertionOrientationを使ってどこに挿入するかってことですね。
この例ではBody要素の"BeforeEnd"に入れてます。なので</body>の直前ってことです。

私が何故ここに入れたかというと、framesetのページを開いた場合、この場所じゃないとリロードした場合や戻った場合にページが壊れることがあったからです。これは多分キャッシュまわりの問題っぽいですが、上記の場所だけが唯一問題なかったのでここにしました。<- 理由は謎なんですけどね、、、っていうか、なんでOKなのか余計に混乱。
(私の実コードではframesetを判断して挿入場所を変えています。また、あまり意味無いですがフレーム内の全ページにこれを挿入するようにしてます。)
framesetを気にしないで良い場合にはframesetの時は挿入しないとかにすれば良いと思います。
(例: if(doc.Body.DomElement.ToString() == "mshtml.HTMLFrameSetSiteClass"){})
私の場合には window.parentとかtopとかされると困るのでこのようにしてます。

こんな感じでとりあえず動作しています。
もっとスマートな方法を知ってる人がいましたら情報お待ちしております。

最後に、これをやってて、MSはどんどん簡単にしてくださってはいるが、やはり同じ分だけ不便になってくなぁって実感しました。TT

C#でMecabのDLLを利用する

MeCab (和布蕪)というオープンソース形態素解析エンジンがあるのですが、これはとっても楽しいおすすめソフトです。
オープンソース形態素解析エンジンにはChaSen, Juman, KAKASI等あるのですが、私はMeCabを利用しています。

MeCab: Yet Another Part-of-Speech and Morphological Analyzer
http://mecab.sourceforge.jp/

形態素解析エンジンでなにが出来るかというと、まぁ色々できるのですが、日本語をわかち書きしてみたり、文書を単語単位にわけて品詞を取得してみたりとあるのですが、私は漢字によみがなを振る為に利用しています。

形態素解析について 出典: フリー百科事典『ウィキペディア(Wikipedia)』http://ja.wikipedia.org/wiki/%E5%BD%A2%E6%85%8B%E7%B4%A0%E8%A7%A3%E6%9E%90

さて、本題ですが、私は今までMecabはBinary package for MS-Windowsに入っている[mecab.exe]にオプションを渡して結果をファイルに出力するようにし、C#で作ったプログラムから叩いて、結果ファイルを読込むといったスマートじゃない使い方をしてたのですが、下記のサイトを参考にしたらさくっとDLLが利用出来ちゃいました。

ぽぷら日記 「MecabをC#で使ってみるテスト」
http://www.doblog.com/weblog/myblog/10356/1754054#1754054

(Thanks!)

もう本当にここに書いてあるとおりDllImportしただけですぐ出来ます。

(↓自分のメモのためにも一応乗せときます)
#################################################################
[DllImport("libmecab.dll")]
extern static int mecab_new2(string arg);
[DllImport("libmecab.dll")]
extern static string mecab_sparse_tostr(int m, string str);
[DllImport("libmecab.dll")]
extern static void mecab_destroy(int m);

private string MecabTest(string str)
{
int p = mecab_new2(@" -d mecab\dic\ipadic -O ruby");
string s = mecab_sparse_tostr(p, str.Replace("\n", ""));
mecab_destroy(p);
s = s.Replace("\n", System.Environment.NewLine);
return s;
}
#################################################################

こんな感じでmecab_new2するときにオプションを渡せます。
この例では辞書のディレクトリの指定と出力フォーマットを指定してます。

ちなみにMecabはかなり高速に動作しますが、私はやはりBackgroundWorkerでこの処理は行っています。(まあ、当然ですね)

しかし、私だけかもしれませんが、形態素解析ってなんか研究者さま達のすっごくディープな世界で値段にするとすごいことになるイメージだったのですが、、、オープンソースなんすねぇ~。びっくりです。自分にとって今まで出来なかったことが出来るようにしてくれるソフトなので、テストしてるだけでもうひょうひょ言っちゃいます。

オープンソース形態素解析エンジンに携わっておられる方全てに多謝!

.NET Framework 2.0 WebBrowserでwindow.close()

これも今困ってる問題です。

.NET Framework 2.0 のWebBrowserコントロールで表示されているページでJavaScriptのwindow.close()イベントが発生するとフリーズしたみたいになります。

実際にはWebBrowserコントロールが半端に終了している+Formは終了しないという、なんともいい加減な状態みたいなのですが、、、それじゃ困るだろう!

とりあえず、先人の知恵でFormを終了してあげることが出来るのはわかった。

[参考]
[Extended .NET 2.0 WebBrowser Control]
http://www.codeproject.com/csharp/ExtendedWebBrowser.asp
↑これはとっても便利。複数の問題点やソリューションがまとめてあるので、そーいうの大好き。

でもですね、私はFormを終了しないで、window.closeが発生したら一つ前に戻りたいんですよ。
それは上記のやつじゃやっぱり出来ないんです。ってか上記の作者さんもそれで困っているのです。
WindowClosingイベントさえちゃんと動いていればな~んの問題もないのですが、、、動かない。
もしくは、JSのイベントを全部ハンドルできるとか、そんな夢のような仕組みが欲しいです。

ドキュメントがダウンロード完了したらwindow.closeをオーバーライドするJSスクリプトを差し込むって作戦も考えてはいるのですが、なんかどうもスマートじゃないなぁ、、DL完了する前とかも怖いし。

なんか良い解決方法はないもんですかねぇ、、、本当に。

なんかなぁ、ちゃんとしてほしいなぁWebBrowserコントロール。

どなたか情報ありましたら、是非ヒントください。お願いします。


.NET Framework 2.0 WebBrowserで表示したFlashが正しく動作しない

.Net Framework 2.0 WebBrowserをつかったブラウザを作成しているのですが、、、色々と問題ありますね。

今日困っているのはタイトルの通り、Flashが正常に動作しない問題です。

これは何かと言うと、
.Net Framework 2.0 WebBrowserをつかったブラウザでFlash のページ(例えばフルFlashのサイトやFlashゲーム等)を表示したときに、一回目のクリックは動作しますが、2回目のクリックは動作せず、その場 合には一回フォーカスをFlashから移動させて(Flash以外の場所を一回クリック)して再度Flash内の操作をすればちゃんと動きます。毎回これ をおこなえば、ちゃんと操作は可能です。
例えば http://contents.kids.yahoo.co.jp/studygame/gakugei/suki1/start.html の
Flashゲームとかで試すとすぐわかると思います。(連続でクリックできないのでゲームを進めるのが辛いです 笑)

色々検索して情報を探してはいるのですが、あまり情報ないようですね、、、
この症状はもしかして条件があるのかもしれないとはおもいますが、
サンプルで
Microsoft.NET Framework 2.0 WebBrowserだけを実装した
プログラムを新規で作っても同じ症状なので、、、特別な条件もないような気が、、、
.NET Framework 2.0 WebBrowserを利用してまともにブラウザを作ろうと思ったら、直ぐに気が付きそうなんですけどね、、、一部の人だけなの症状なのかな。

参考:http://www.eggheadcafe.com/aspnet_answers/NETFrameworkNETWindowsForms/Apr2006/post26457510.asp
(この解決方法ではちょっと、、、って感じなんですけどね 笑)

上記の内容をMSDNフォーラムに似た内容の投稿がありましたので、私も便乗で投稿してみました。
なにか情報があるとうれしいなぁ。

しっかし、なんでこの症状の情報はすくないんだろう、、、なんか自分が簡単なミスをしてそうな予感。