トップ回答者
WebBrowserのデータが更新できません。

質問
-
Formベースのアプリにおいて、ボタンを押すことにより、Web上の絶えず変化しているデータを取得します。
取得方法は、WebBrowserを用いてあるHPにログインし、データのあるpageに移動した後、Htmlを取得し、にこのHtmlからデータを抽出します。
困っているのは、データが変化している(IEで確認)のに、ボタンを繰り返し押しても同じ値にしかならないことです。調べてみるとHtml自身が変化していません。但し一度アプリを再起動すると、ボタンを押した最初の時のみデータが更新されます。
よろしくお願いいたします。
データが存在するpageのUrlは同じなので、WebBrowserが一度取得したpageを繰り返し見せているみたいです。
このため、ボタンを押す度にWebBrowserの新しいインスタンスを作成しても変わりません。
但し一度
回答
-
WebBrowser のキャッシュ関連でよく似たスレッドです。
WebBrowserのページキャッシュ寿命
http://social.msdn.microsoft.com/Forums/ja-JP/csharpexpressja/thread/817d2004-f3dd-4d51-a056-2f84f958bb7e
ちなみに、ボタンを押すとどのようなコードが動くのでしょうか?- 回答としてマーク C-sharp 勉強中です 2011年1月1日 12:36
- 回答としてマークされていない C-sharp 勉強中です 2011年1月1日 12:36
- 回答としてマーク 山本春海 2011年1月11日 2:10
-
Web上の絶えず変化しているデータを取得するとのことですから、キャッシュ機能自体が無効になってもかまわないですよね? であれば、以下のページに書かれているWebBrowserコントロールを使用して、RESYNCHRONIZEのビットを立てればキャッシュを行わなくなるようです。
WebBrowserコントロールを制御する
http://jumbofoot.cocolog-nifty.com/yass_vbnet_tips/2006/09/webbrowser_1de3.html
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/- 回答としてマーク 山本春海 2011年1月11日 2:06
すべての返信
-
WebBrowser のキャッシュ関連でよく似たスレッドです。
WebBrowserのページキャッシュ寿命
http://social.msdn.microsoft.com/Forums/ja-JP/csharpexpressja/thread/817d2004-f3dd-4d51-a056-2f84f958bb7e
ちなみに、ボタンを押すとどのようなコードが動くのでしょうか?- 回答としてマーク C-sharp 勉強中です 2011年1月1日 12:36
- 回答としてマークされていない C-sharp 勉強中です 2011年1月1日 12:36
- 回答としてマーク 山本春海 2011年1月11日 2:10
-
Web上の絶えず変化しているデータを取得するとのことですから、キャッシュ機能自体が無効になってもかまわないですよね? であれば、以下のページに書かれているWebBrowserコントロールを使用して、RESYNCHRONIZEのビットを立てればキャッシュを行わなくなるようです。
WebBrowserコントロールを制御する
http://jumbofoot.cocolog-nifty.com/yass_vbnet_tips/2006/09/webbrowser_1de3.html
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/- 回答としてマーク 山本春海 2011年1月11日 2:06
-
RESYNCHRONIZE = &H2000
というのは、キャシュ寿命を2000msにするという意味と理解しました。試してみます。
いえ、そういう意味ではなくて、&Hを付けると16進数を表します。つまり、16進数の2000です。C#ですと0x2000という表現になります。ビット演算を行ない、そのビットの位置(0x2000の位置)を1にすることにより、キャッシュを行なわなくなります。良い例を見つけましたのでご紹介しておきます。
WebBrowser コントロールの Navigate と Refresh を
使うと更新完了のタイミングが掴めない
http://ap.atmarkit.co.jp/bbs/core/fdotnet/19040C#でビット演算などで調べられると良いと思います。
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/ -
どのようなコードということですが、結構複雑なので、Refresh等を試して上手くいかなければ相談します。
データ更新の際に WebBrowser コントロールをどのように呼び出しているかが気になっただけですので、あまり気にしないでください。(Refresh だとは思ったのですが、Navigate だったりするかもしれませんので、念のために。)
実は、HPが証券会社で、対象とするデータは取引時間しか変化しないため、今はテストできません。
直接は関係ないのですが、テストやデバッグのことを考えると、直接実データを参照しないでも動作する口を用意しておいた方がいいと思います。テスト用の Web サーバーを用意しておいて設定で本物サーバーと切り替えるとか、Fiddler のような類のツールを使ってあらかじめ用意しておいたレスポンスを返すとか。 -
レスが遅れて申し訳ありません。
皆さんのアドバイスは、私の知識レベルを超えていたため、教えていただいた文献の理解に時間がかかりました。
今も理解は不十分ですが、目的を達成することはできました。
本来アドバイスを頂いたコメントごとにレスを付けることが望ましいでしょうが、まとめて述べることをお許しください。
(1)totojoさん紹介の
http://social.msdn.microsoft.com/Forums/ja-JP/csharpexpressja/thread/817d2004-f3dd-4d51-a056-2f84f958bb7e
にあるキャッシュ寿命については、Refresh()がうまくいかなかったので、深くは検討しませんでした。(2)trapemiyaさん紹介の
http://jumbofoot.cocolog-nifty.com/yass_vbnet_tips/2006/09/webbrowser_1de3.html
には、Yas'sさん作成の、WebBrowserControlerクラスがあり、RESYNCHRONIZE = &H2000 を使っています。
しかしこれはVBなので(私はC#)参考程度にしました。
なおこの文献は、VBでWebBrowserコントロールを制御するという意味では、よく引用されているようです。(3)結局C#でWebBrowserコントロールを制御する方法として、trapemiyaさん紹介の
http://ap.atmarkit.co.jp/bbs/core/fdotnet/19040
の後の方にある引用文献である
http://slingkid.blogsome.com/2006/05/26/blocking-images-similar-to-outlook
を参考にして目的を達しました。下記コードは、(3)の文献からコードをダウンロードし、私の目的の確認用に簡略化したものです。
(a)オリジナルのコードは、urlを入力するTextBox、対象とするWebページへ飛ぶButton、WebPageのイメージをダウンロードするか否かを切り替えるLabelなどがありますが、下記コードではButtonを押すごとに(b)に記載のページを表示(異なる時間が表示)されるようにしています。
(b)webページは、totojoさんご指摘の常時使用可能なサーバーということで、
http://www2.nict.go.jp/w/w114/tsp/PubNtp/clients.html
(日本標準時プロジェクト)にある、現在時間を表示するurl
http://ntp-a1.nict.go.jp/cgi-bin/time
を使っています。(b)コードは、Webページを繰り返し訪問しても、キャッシュを使用しないようにする機能のみに限定して簡略化しています。例えば、enum BrowserOptions内多くのフィールド、大部分のイベントハンドラーなどを削除しています。従って元コードを下記のコードで置き換えてビルドすると、イベントハンドラーが無いなどのエラーがでます。
(c)VBのRESYNCHRONIZEビットをたてることに相当するのが下記コードの
IgnoreCache = 0x00002000
だということはすぐ分かりましたが、これはWebBrowserのプロパティーを設定することとは違うので、このIgnoreCache を利用している仕組みがわかりませんでした。
色々調べたのですが、COMの運用に関係してるらしく、結局今も分かっておりません。そこで他の文献などを参考にし、オリジナルのコード修正していき、結局下記になりました。
但し下記コードにおいて、
#region COM Interfaces
#endregion COM Interfaces
と
#region IOleClientSite Members
#endregion
の各々内容は省略していますが、オリジナルと同じです。
まだ当面の目的には不要なものがあるかもしれません。
public enum BrowserOptions : uint
{
/// <summary>
/// Specifies that the browser should fetch the content from the server. If the server's
/// content is the same as the cache, the cache is used.Equivalent to DLCTL_RESYNCHRONIZE.
/// </summary>
IgnoreCache = 0x00002000,
}#region COM Interfaces
#endregion COM Interfaces[ComVisible(true)]
public partial class Form1 : Form, IOleClientSite
{
string _timeUrl = "http://ntp-a1.nict.go.jp/cgi-bin/time";
BrowserOptions _options = BrowserOptions.IgnoreCache;public Form1()
{
InitializeComponent();webBrowser1.DocumentCompleted += delegate(object sender, WebBrowserDocumentCompletedEventArgs e)
{
};
}[DispId(-5512)]
public virtual int IDispatch_Invoke_Handler()
{
return (int)_options;
}#region IOleClientSite Members
#endregionprivate void Form1_Activated(object sender, EventArgs e)
{
IOleObject obj = (IOleObject)this.webBrowser1.ActiveXInstance;
obj.SetClientSite(this);
this.webBrowser1.Navigate(_timeUrl);
}private void GoButton_Click(object sender, EventArgs e)
{
_options |= BrowserOptions.IgnoreCache;IOleControl obj = (IOleControl)this.webBrowser1.ActiveXInstance;
//notify browser of change
obj.OnAmbientPropertyChange(-5512);this.webBrowser1.Navigate(this.webBrowser1.Url);
while (this.webBrowser1.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}this._options &= ~BrowserOptions.IgnoreCache;
obj.OnAmbientPropertyChange(-5512);}
}今開発中のアプリに適用するには、上記コードをさらに簡略化したほうが良いように思いますが、何れにしてもここまで到達できたのは皆さんのアドバイスのおかげです。
大変感謝しております。 -