仮面's profile宇宙仮面の C# 研究室.Live SpacePhotosBlogListsMore Tools Help

宇宙仮面の C# 研究室.Live Space

C#, Windows Mobile, X-Box360などに関連したブログです。
May 25

Codeseek 勉強会のWinRing0の資料をアップしました。

第40回codeseek勉強会
「宇宙仮面のWinRing0」
(共催:tk-engineeringこみゅぷらすeパウダ~.Net/C# Group)

開催日:2009年5月19日(火) 19:00~21:00 18:55に6F受付集合
場所:マイクロソフト社新宿オフィス6F会議室
募集締め切り:2009年5月16(土)23時59分59秒
20名まで
参加費無料

Codeseek 勉強会のWinRing0の資料を
http://uchukamen.com/wpf/WinRing0/
にアップしました。
May 19

削除できなくなった Gadget を強制的に削除する

いろいろ悪さをしていて、Gadget が消せなくなった場合の対処方法 w

  1. タスクトレイの [Windows サイドバー]を右クリック→終了。
  2. %USERPROFILE%\AppData\Local\Microsoft\Windows SidebarのSettings.ini を削除
  3. スタートメニュー→アクセサリ→Windows サイドバー で再起動。

なお、この場合、サイドバーの設定がすべてリセットされます。

May 18

XML Web Service の呼び出し

CPUの温度を取得する際、WebClient を使用した、非同期呼び出し。

なお、Silverlight 3 Beta では、linq がサポートされていないので動かない。

///////////

WebClient client = new WebClient();

string request = "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"  xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">  <soap:Body><CPUTemperatureStringResponse xmlns=\"http://tempuri.org/\">      <CPUTemperatureStringResult>float</CPUTemperatureStringResult>    </CPUTemperatureStringResponse></soap:Body></soap:Envelope>";

client.Headers.Add(HttpRequestHeader.ContentType, "text/xml");

client.Headers.Add("SOAPAction", "http://tempuri.org/CPUTemperature");

client.UploadStringCompleted += delegate(Object sender2, UploadStringCompletedEventArgs ev)
{
    XNamespace soap="http://schemas.xmlsoap.org/soap/envelope/";
    XNamespace xsi="http://www.w3.org/2001/XMLSchema-instance";
    XNamespace xsd="http://www.w3.org/2001/XMLSchema";
    XNamespace xst = "http://tempuri.org/";

    XDocument xmlHeadlines = XDocument.Parse(ev.Result);
    var headlines = from story in xmlHeadlines.Descendants(xst + "CPUTemperatureResult") select story;

    string temp = headlines.First().Value;

    TextBox1.Text = temp;
};

client.UploadStringAsync(new Uri("http://localhost/SystemTemperature/Temperature.asmx"), request);

May 06

CPUの温度取得に関するメモ6

WinRing0 を利用した Web Service のビルド環境の構築まとめ (Vista 32bit版)

  1. Visual Studio 2008 を管理者モードで起動
  2. ASP.NET Web サービスアプリケーションのプロジェクトを作成
  3. OpenLibSys.cs を追加
  4. WinRing0 は管理者で実行する必要があるため、Web.Config で Administrator に偽装するためのコードを追加
    <configuration>
      <system.web>
        <identity impersonate="true" userName="ホスト名\Administrator" password="パスワード" />
  5. デバッグ環境時の DLL 参照パス C:\Program Files\Common Files\Microsoft Shared\DevServer\9.0 に WinRing0.sys と WinRing0.dll をコピーする。
  6. IIS実行環境時の DLL 参照パス c:\windows\system32\inetsrv に WinRing0.sys と WinRing0.dll をコピーする。

CPUの温度取得に関するメモ5

Web Service から OpenLibSys を呼び出すと、InitializeOls(); を呼ぶところでOLS_DLL_DRIVER_NOT_FOUND エラーになってしまう。

この原因は、WinRing0.sys を Visual Studio のデバッグ環境で、Web Service から呼び出すときに、OlsDll.cpp の Initialize()関数の中で、ドライバーを呼び出すときのパスが、 “C:\Program Files\Common Files\Microsoft Shared\DevServer\9.0\WinRing0.sys” になってしまうためであることが判明した。暫定で、その場所に WinRing0.sys をコピーして先に進んでみる。

次に、Web Service をローカルの IIS に発行してみると、ドライバーを呼び出すときのパスが今度は、 “c:\windows\system32\inetsrv\WinRing0.sys” になってしまい、ドライバーを探しに行ってエラーになってしまう。そこに、WinRing0.sys をコピーすることで、Web Service から OpenLibSys を呼び出せるようになった。

image 

はまったメモ:

WinRing0が LoadLibrary で呼ばれていて、Web Service からデバッグできないので、ビルド環境を作って、メッセージを埋め込んでデバッグするしかなかった。もう少しいい方法があるのかな・・・

そこで、WinRin0\dll をビルドしてたら、DEF ファイルが外出しになっていて、リンカオプションに def ファイルを追加する必要があった。

/DEF:"C:\Users\uchukamen\Desktop\WinRing0_1_3_0\source\dll\OlsApi.def"

そこで、fprintf (stderr でと思ったが、出力先がないので、エラーを出せない。イベントログも面倒なので、とりあえず、ファイルにエラーメッセージを書き出した。

やっぱりワナがあった w

ここまでくれば、あとは OpenLibSys も気にせず、管理者モードに移行する必要もなく、簡単にアプリができる。ただ、OpenLibSys 強力な分、セキュリティ上注意が必要。

ASP.NET で偽装する

温度計を Web Service にしてなんてことを考えて、Administrator 権限が必要な OpenLibSys を Web Service 化するには、偽装しなければならない。その他、きっとはまるだろうと思いつつ、やっぱり引っかかりますね。

Web.config で

<configuration>
  <system.web>
    <identity impersonate="true" userName="ホスト名\Administrator" password="パスワード" />
   …

と追加して、実行すると、

'/' アプリケーションでサーバー エラーが発生しました。 構成にエラーがあります。

説明: この要求を処理するために必要な構成ファイルの処理中にエラーが発生しました。以下のエラーの詳細を確認し、構成ファイルに変更を加えてください。
パーサー エラー メッセージ: 構成ファイルで指定された資格情報から Windows ユーザー トークンを作成できません。オペレーティング システム 'ログオン失敗: アカウントは現在無効に設定されています。
' のエラーです。

というエラーが発生。Vista では、Administrator アカウントが無効になっているので、

[管理ツール] → [ローカル セキュリティ ポリシー]

image

これを有効にしてみた。すると、このエラーは、無事解決。

しかし、InitializeOls(); を呼ぶところで引っかかっている。サービス側なので、デバッグが厄介だな・・・

この原因は、WinRing0.sys を Visual Studio のデバッグ環境で、Web Service から呼び出すときに、OlsDll.cpp の Initialize()関数の中で、ドライバーを呼び出すときにディレクトリが、 “C:\Program Files\Common Files\Microsoft Shared\DevServer\9.0\WinRing0.sys” になってしまい、OLS_DLL_DRIVER_NOT_FOUND エラーになってしまう。暫定で、その場所に WinRing0.sys をコピーして先に進んでみる。

次に、Web Service をローカルの IIS に発行してみると、こんどは “c:\windows\system32\inetsrv\WinRing0.sys” を探しに行ってエラーになる。そこに、WinRing0.sys をコピーすることで、Web Service から OpenLibSys を呼び出せるようになった。

May 05

あれ? Vista IIS 7 で Web Service が動かない・・・

温度計をWeb Serviceにしてしまおうかと思って、久々にWeb Service を作って、ローカルの Vista に発行してみたら、

「IIS 7.0 でホストされている Web サイトにアクセスすると、エラー メッセージ:"HTTP エラー 500.19-内部サーバー エラー"」 というエラーで Web Service が動かない。

http://support.microsoft.com/kb/942055/ja

に対処方法が書かれていたので、その通りにしてみたが症状は変わらず。

あれれ? ということで、いろいろ調べていたら、[コントロール パネル] → [プログラムと機能] → [Windows の機能を有効化または無効化] → [アプリケーション開発機能] の ASP.NET のチェックがされていなかった。

VISTA を入れて、Visual Studio 2008 を標準インストールしただけで特に何もしていないはずなので、標準インストールでは ASP.NETは ON にならないのかな?

image

このチェックを入れたら、無事動いた。

Windows Vista IIS で ASP.NET を動かすための設定は、

http://msdn.microsoft.com/ja-jp/library/aa964620.aspx

に書かれています。
エラーメッセージからサポートオンラインの情報を引いたのだけれど、その情報に惑わされてしまった。というわけで、またはまりそうなので、一応メモっておこう。

CPUの温度取得に関するメモ4

Intel® 64 and IA-32 Architectures Software Developer’s Manual によると、今使用中の ASUS P5LD2-V + Pentium 4 D では、MSR から CPU の温度が取れないことが判明した。

で、http://kariunten.homeip.net/programming/winring0.html

にマザーボードのI/Oコントローラからデータを取得する方法が載っていたので、OpenLibSys で試してみた。

ASUS P5LD2-Vのマニュアルを調べてみると、コントローラは W83627EHF だったので、そのマニュアル

http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83627EHF_W83627EHG.pdf

を調べてみた。それによると、このチップには温度センサーが3つ搭載されている。ただし、マザーボード上で使用されているのは、CPUTIN Temperature、SYSTIN Temperature の2つのみで、AUXTIN Temperatureは使用されていない模様。

このコントローラーからデータを取得するには、IO ポートからデータを取得すればよい。

取得する方法は、0x295 ポートにレジスタを指定、0x296 ポートからデータを取得するという手順。

ただし、バンクが 0, 1, 2, 3, 4 とあり、0x50 以上のレジスターにアクセスするには、バンクを切り替える必要がある。バンクの切り替え方法は、0x4E ポートの下位3ビットで指定する。

CPUTIN (CPUの温度)は、

バンク1、0x50 レジスタにハイビット(温度 ℃)

バンク1、0x51 レジスタにロービット(温度 7ビット目が立っていれば +0.5℃)

となっているので、次のようなコードになる。

//=======================================
// CPUTIN Temperature
//=======================================
// バンク1
ols.WriteIoPortByte(0x295, 0x4E);
ols.WriteIoPortByte(0x296, 0x81);
// データ読出し(50h Bank1)
ols.WriteIoPortByte(0x295, 0x50);
hi = ols.ReadIoPortByte(0x296);

// バンク1
ols.WriteIoPortByte(0x295, 0x4E);
ols.WriteIoPortByte(0x296, 0x81);
// データ読出し(10h Bank1)
ols.WriteIoPortByte(0x295, 0x51);
lo = ols.ReadIoPortByte(0x296);

Console.WriteLine("CPUTIN Temperature Low : ...." + lo.ToString("X") + "\r\n");
Console.WriteLine("CPUTIN Temperature High: ...." + hi.ToString("X") + "\r\n");

float CPUTIN = hi + ((lo & 0x80) != 0 ? 0.5f : 0);

Console.WriteLine("CPUTIN Temperature: ...." + CPUTIN.ToString() + "\r\n");

同様に、SYSTIN (マザーボードの温度)は、バンク0、0x27 レジスタなので、

//=======================================
// SYSTIN Temperature
//=======================================

// バンク0 を指定
ols.WriteIoPortByte(0x295, 0x4E);
ols.WriteIoPortByte(0x296, 0x81);
// データ読出し(27h Bank0)
ols.WriteIoPortByte(0x295, 0x27);
hi = ols.ReadIoPortByte(0x296);

Console.WriteLine ("SYSTIN Temperature: ...." + hi.ToString() + "\r\n");

なお、SYSTINでは、0.5℃単位の測定はできない仕様になっている。

結果は次の通り。

[CPUTIN Temperature]
CPUTIN Temperature Low : ....80
CPUTIN Temperature High: ....21
CPUTIN Temperature: ....33.5

[SYSTIN Temperature]
SYSTIN Temperature: ....24

下は、ASUS のおまけアプリの Probe II のデータ

image

image

おおおおっ、ちゃんと取れるじゃないですか。OpenLibSys 偉大だ。

というか、Core2にアップしてしまえば、MSRで取れるので、こんなことしないですむんだけどなぁ・・・

というか、こんなハード固有の実装させないように頑張ってよ >> MS

というか、温度を気にしないといけないような CPU 勘弁してよ >> Intel, AMD

CPUの温度取得に関するメモ3

MSR(Model Specific Register) 0x19C Bits [22:16] で温度が取得できることは確認できたが、このセンサーの値は、Tjmax への相対値であることがマニュアルに書かれている。しかし、そのTjmaxの値をMSRから取得する方法がマニュアルに書かれていない。

いろいろ探していたらば、

http://software.intel.com/en-us/forums/deleted-posts/topic/51574/page/1/

で、MSR 0xEE で取得が可能なようだが、undocumented だそうだ。ちょっと古い資料なので、85度か100度と書かれている。

http://www.xtremesystems.org/forums/showthread.php?t=179044&page=23

によると、0xEE の bit:30 で、0=100 1=85 といううわさもある。

一方、Q6600 では、95度らしいという書き込みもある。

http://www.xtremesystems.org/forums/showthread.php?t=179044&page=27

Atom の場合、20度室温で 0x19C Bits [22:16] から88前後が返されているので、100度にしても合わない。

http://download.intel.com/design/processor/datashts/320032.pdf

によると、a catastrophic processor temperature of 125°C (maximum), or if the THERMTRIP#
signal is asserted, ということで、125度とすると、ちょうど37度となり、それらしい値になる。

MSR 0xEE で取得してみると、

000000EE: 00000000 02F90002

となり、仕様が分からない。

http://www.bugtrack.almico.com/view.php?id=1150

によると、

if bit 30 of MSR(0x00EE) is 1 then
  Tjmax=85
else
  Tjmax=100
endif
if CPUID=0x06F2 then Tjmax=100
if CPUID=0x06FB then Tjmax=100
if CPUID=0x10676 then Tjmax=Tjmax+5

こんな情報もある。

それにしても、xtremesystems.org のスレッドがものすごいことになっているのには、驚いた。

いずれにしても、インテルが仕様をはっきり書いていない(NDAを結ばないともらえないらしい)のが悪いということがよくわかった。

May 04

CPUの温度取得に関するメモ2

石坂さん、渋木さんに教えていただいたサイドバーガジェットを Windows 7 Beta on Atom N280で動かしてみました。こんな感じ。

image 

原理はデバイスドライバーで、Ring0のカーネルモードに移行して、そこでアセンブラでRDMSRにより、Model Specific Register を叩いて、直接モードスペシフィックレジスターからデータを読み取っていますね。そのためのライブラリがOpenLibSysから提供されている。なるほど、それなら早いはずだ。それにしても、OpenLibSysを作った人は偉いなぁ・・・とひとしきり感動しました。

なお、Vista on Pentium4 Dでは、温度が取得できない。orz。MSR的には、0x19C の 22:16 で同じ仕様に見えるんだけど、どこか細かいところで違うのかな・・・

image

なお、MSRは、文字通りモデル固有のレジスタであるため、プロセッサのモデルごとに仕様が異なっている。Intel のIntel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3Bによると、Core2、Atom、P4 and Xeon、Core Solor and Core Duo、Pentium M、P6、Pentiumとファミリーごとに説明が分かれています。

April 29

CPU 温度の取得に関するメモ

だんだんと暑い季節になってきて、Core2ではない Pentium 4 Dにとっては、辛い季節になってきました。室温が上がると、調子が悪くなるので、まじめに深刻な問題です。そこで、先日ケースにファンを増設したら、だいぶ効果があるようで、35度ぐらいでおちついていますが、CPUの温度のモニタリングしたいと思って、ちょっと調べてみました。

WMI の “Win32_TemperatureProbe” が一番まともな方法のようだが、現在のPC “ASUS P5LD2-V”, eee PC 1000 HE では、このインターフェースがサポートされていない模様。

いろいろ調べてみると、MSAcpi_ThermalZoneTemperature を使った記事がいくつかある

http://groups.google.co.jp/group/microsoft.public.win32.programmer.wmi/browse_thread/thread/d462fd6d271cc98d

が、そもそもそんな I/F の情報は MSDNに載っていない。もう使われていないということか?

さらに調べてみると、

http://kariunten.homeip.net/programming/winring0.html

にマザーボードのコントローラを直接操作する方法が載っていた。そうきますか~~~w。

と思って、そのコードを見てみると、

http://openlibsys.org/

で、Windowsからハードウェア(I/O port, MSR, PCI bus, and etc...)へのアクセスを可能とする WinRing0 が提供されているコードを利用している。

さらに、そこから

http://www.techpowerup.com/realtemp/

で、all Intel single Core, Dual Core, Quad Core and Core i7、さらにはNvidia のGPUの温度まで取得できるプロジェクトを発見。

試してみたが、Pentium 4 Dは、サポートされていない;;

image

eee PC 1000 HE の Atom N280だと? 1℃  !  すばらしい CPUだ w

image

ASUS からProbe II というモニターツールがあるから問題ないんだけどね。

image

温度、ファン回転数ぐらい WMI でちゃんと取れるようにしてよね。>> MS

それより、せめてCore2にしろよという突っ込みは却下。

April 04

eee PC 1000HE 届いて、速攻で Windows 7に化けた

注文していた eee PC 1000HE が今日の夕方届きました。

20090404 eeePC 002

PC DEPOT で 2GB メモリ、16GB SD カード付きで 47700円。

20090404 eeePC 003

意外と大きい。

バッテリーも9時間もつ6セルなので、1.5Kgぐらいで、かなりずっしりくる。

20090404 eeePC 004

Windows XP が標準で載っています。

20090404 eeePC 005

裏側はこんな感じ。すぐさま、1GBメモリを取り出して、2GBに交換。

20090404 eeePC 006

D: ドライブに Windows 7 Build 7000 をインストール。

一応、安全のため、C: ドライブの XPは残して、デュアルブート。

20090404 eeePC 007

風呂からあがってみると、もうWindows 7 の設定画面になっている。早っ!

20090404 eeePC 009

設定はすぐ終わり、あっさり Windows 7 が動いてしまった。

20090404 eeePC 010

インテルのチップセットは、Aeroにも対応。

20090404 eeePC 011

ハイパースレッド。

20090404 eeePC 012

無線LANも、デフォルトのインストールで問題なし。

ただし、デフォルトではイーサーコントローラーと、ACPIのドライバーが未対応。

20090404 eeePC 016 20090404 eeePC 021

イーサネットは、ASUSからVista用をダウンロードして、問題なく動く。

意外と、早いじゃん!いい感じ。

March 15

Visual Studio 2008 で、ASP.NET 開発サーバーが動かない原因判明

http://blogs.msdn.com/webdevtools/archive/2009/03/13/asp-net-web-development-server-stops-working.aspx

Visual Studio Web Developer Team Blog より、ASP.NET Web Development Server Stops Workingという記事を発見。

Windows Defender and Microsoft Forefront Client Security signature file (1.53.256.0) に対応するために、2009年3月9日 8:45 PM (PST) の対応で、ホストファイルから localhostが削除されている。

解決するためには、 C:\Windows\System32\drivers\etc\hosts

のエントリを次のように修正すればよい。

127.0.0.1       localhost

1.53.288.0での修正版がその直後の March 9, 2009  8:57 PM に出ているということで、それ以降は大丈夫みたいだけど。

で、hosts ファイルをみてみたら、

::1             localhost

となっている。IPV6?

とりあええず、これを

127.0.0.1       localhost

と修正して、無事復旧。

Visual Studio 2008 Pro を再インストールしたが

フルにアンインストールして、VS 2008 Pro を再インストール

ASP.NET アプリのプロジェクトを作成して実行すると、

Internet Explorer ではこのページは表示できません

可能性のある原因:
  • インターネットに接続されていない。
  • Web サイトに問題が発生している。
  • アドレスに入力の間違いがある可能性がある。

というエラー。

Gushwell さんも同じような状況

http://blog.livedoor.jp/gushwell/archives/51341969.html

こちらでも、

http://social.msdn.microsoft.com/forums/ja-JP/vwdexpressja/thread/27747fb7-b12f-422a-9800-8f0d28334042/

にも同じような人が・・・

どうも ASP.NET 開発用サーバーに接続できていないようだが、原因が分からない。

March 14

VS2008でASP.NETプロジェクトを作ると落ちる

image

イベントビューアーで調べると・・・

障害が発生しているアプリケーション devenv.exe、
バージョン 9.0.21022.8、タイム スタンプ 0x47317b3d、
障害が発生しているモジュール mswebprj.dll、
バージョン 9.0.21022.8、
タイム スタンプ 0x4731806d、例外コード 0xc0000005、障害オフセット 0x00018fba、
プロセス ID 0x179c、アプリケーションの開始時刻 0x01c9a468c04aeb50。

ふむううう。

イベントビューアーで調べたら、直前に警告で

テンプレート (C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\Windows\1041\WPFBrowserApplication.zip)、ファイル (csWPFBrowserApplication.vstemplate) にエラーがあります。不明な要素 (EnableEditOfLocationField) です。解析で修復を試行します。

と出ている。ファイルがおかしくなっているせいか?

くそっ、C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\Windows\1041 以下を消して、再インストールしてみる。

そうしたら、また修復も、アンインストールもできない罠。orz

image

Visual Studio 2008 の修復インストール、アンインストールができない

Visual Studio 2008の調子が悪く、ASP.NETの開発ができなくなってしまった。特に何もしていないのに突然の症状。原因不明。しかたないので、修復セットアップしようとしたら、セットアップもできなくなっている。

image

アンインストールもできない。困ったと思っていたら、

もりさんのページで、

Visual Studio 2008 自動アンインストールツールが公開されています。

が紹介されていた。

Visual Studio 2008 をアンインストールする

http://msdn.microsoft.com/ja-jp/vstudio/bb968856.aspx

無事安易ストール完了。

さて、インストールしますか。

・・・1時間後、インストール無事終了。起動してみると、ブルースクリーンでVista 落ちた。

再起動後、WebApplication を作ってみただけで、

image

ということで、なんかすごくおかしくなっている。

WinForm は問題なくプロジェクトの作成、実行ができる。

IISがらみか?

February 03

RDF を LINQ で読む

string gooRankingUrl = "http://ranking.goo.ne.jp/rss/keyword/keyrank_all1/index.rdf";
XDocument feedXML = XDocument.Load(gooRankingUrl);

XNamespace d = "http://purl.org/rss/1.0/";
XNamespace dc = "http://purl.org/dc/elements/1.1/";

var res = from item in feedXML.Descendants(d + "item")
          select new
          {
              Title = item.Element(d + "title").Value,
              Link = item.Element(d + "link").Value,
              PubDate = (item.Element(dc + "date").Value ?? ""),
              Publisher = (item.Element(dc + "publisher").Value ?? ""),
              Rank = (item.Element(dc + "rank").Value ?? ""),
              Point = (item.Element(dc + "point").Value ?? ""),
              Arrow = (item.Element(dc + "arrow").Value ?? ""),
              Description = (item.Element(d + "description").Value ?? ""),
              Guid = item.Element(d + "link").Value
          };

GridView1.DataSource = res;
GridView1.DataBind();

結果は、こんな感じ。image

January 26

ASP.NET ルーティング 続き on 2003 Server

この前の ASP.NET ルーティングは、VS2008 + Vista ASP.NET開発サーバーであっさり動きました。

ところが、2003 Server で試してみると動かない。

???ということで調べてみると、

IIS の Web サイトのプロパティ → ホームディレクトリ タブ → 構成ボタンを押し下げます。

image

すると、アプリケーションの構成ダイアログが表示されます。

image 

ここで、ワイルドカード アプリケーション マップで、挿入ボンタンを押す。

image

c:\windows\microsoft.net\framework\v2.0.50727\aspnet_isapi.dll を指定し、

ファイルの存在を確認する チェックボックスを外す。

これにより該当しないファイル拡張子の場合、aspnet_isapi.dll で、ルーティングが追加されていないかどうか確認するようになりました。

Culminis : 1/22/2009 Announcing the APAC Regional Board

シアトルでルームシェアしたインド人の Ashwin からのチャットで、次のお知らせをもらった。

http://thevoice.culminis.com/APAC/Lists/Posts/Post.aspx?ID=4

北端さんが DAL (Director-at-Large): で日本代表として参加されているとのこと。

プロファイルは

http://new.culminisconnections.com/BOD/APAC.aspx?PageView=Shared

January 06

ASP.NET ルーティング

MSDN を読んでいたら、ASP.NET ルーティングということで、URLの書き換え方法が載っていた。

http://msdn.microsoft.com/ja-jp/library/cc668201.aspx

昔調べた方法から、IIS7 対応もあり、だいぶ変わっているようなので調べてみた。そうしたら、ええ~~、こんな簡単にできようになっちゃたんだー!と感動して、ためしに動かしてみようとしました。すると、CategoryRouteHandler がありませんと怒られる。そりゃそうだ、どこにもそんなコードがない。あれ??ということで調べてみると、どっとねっとふぁんBlog の小野さんが

ASP.NET ルーティングを実装する

で丁寧に解説してあった。さすが師匠wと感動する一方、やっぱりハンドラ書かないといけないのね。orz

LinqDataSource によるメモリ内コレクションのデータへの接続

http://msdn.microsoft.com/ja-jp/library/bb547113.aspx

Default.aspx.cs にMoviewLibraryクラスを追加。

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

namespace LinqDataSource
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }
    }

    public class MovieLibrary
    {
        string[] _availableGenres = { "Comedy", "Drama", "Romance" };

        public MovieLibrary()
        {
        }

        public string[] AvailableGenres
        {
            get
            {
                return _availableGenres;
            }
        }
    }
}

GridViewを追加。新しいデータソースを選択。

image

LINQを選択。

image

データソースの構成ダイアログで、MoviewLibraryを選択。

image

データの選択の構成ダイアログで、テーブル、Select, GroupBy, Where, OrderBy を指定可能。

image

実行すればこのとおり。

image

生成されたWPFコードは、

<asp:GridView ID="GridView1" runat="server" DataSourceID="LinqDataSource1">
</asp:GridView>
<asp:LinqDataSource ID="LinqDataSource1" runat="server"
    ContextTypeName="LinqDataSource.MovieLibrary" TableName="AvailableGenres">
</asp:LinqDataSource>

列名までしっかり処理されている。もう少し複雑なテーブルで試してみると、これがずいぶん便利だということに気が付く。

January 05

Linqでファイルを作成日順でソート

MSDNのサンプルそのままだけど、ちょっと便利。
       private void Form1_Load(object sender, EventArgs e)
        {
            string startFolder = @"C:\My Documents\My Pictures\";

            // Take a snapshot of the file system.
            IEnumerable fileList = GetFiles(startFolder);

            //Create the query
            IEnumerable fileQuery =
                from file in fileList
                where file.Extension == ".jpg"
                orderby file.Name
                select file;

            // Create and execute a new query by using the previous 
            // query as a starting point. fileQuery is not 
            // executed again until the call to Last()
            var files =
                (from file in fileQuery
                 orderby file.CreationTime
                 select new { file.FullName, file.CreationTime });
        }

        // This method assumes that the application has discovery 
        // permissions for all folders under the specified path.
        static IEnumerable GetFiles(string path)
        {
            if (!System.IO.Directory.Exists(path))
                throw new System.IO.DirectoryNotFoundException();

            string[] fileNames = null;
            List files = new List();

            fileNames = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);
            foreach (string name in fileNames)
            {
                files.Add(new FileInfo(name));
            }
            return files;
        }

サービス参照の追加(VS2008) と Web参照の追加(VS2005)

VS2005 では、サービス参照の追加から、次のようなサービスを追加することができる。このダイアログの一番下に、参照設定ボタンがある。

image 

この参照設定ボタンをクリックすると、次のようなサービス参照設定の詳細を指定することができる。このダイアログの一番下に、互換性ということで、Web 参照の追加ボタンがある。.NET Framework 2.0 web サービステクノロジーに基づいたコードを生成することができる。

image

Web 参照の追加ボタンを押すと、昔懐かしいWeb 参照ダイアログが表示される。

image

.NET 2.0とそれ以降では、生成されるコードが若干違ってくるので、注意が必要。

January 03

XAML Data Binding

Expression Blend で TextBlockのプロパティ→共通プロパティ→ Text の右側の小さな四角をクリック

image

すると、次のようなメニューが表示されるので、データバインドを選択する。

image

データバインドの作成ダイアログが表示されるので、

要素プロパティタブ→シーン要素から textBox1を選択、プロパティよりTextを選択し、完了。

image

生成されるXAMLコード

<TextBox Name="textBox1" VerticalAlignment="Top" />
<TextBlock x:Name="textBlock1" Text="{Binding Path=Text, ElementName=textBox1, Mode=Default}"/>

Path を指定しない場合、既定でオブジェクト全体にバインドされます。

Mode は、OneWay, TwoWay, OneTime, OneWayToSource, Default

TwoWay
ソース プロパティまたはターゲット プロパティのどちらか一方が変更されると、もう一方も自動的に更新されます。この型のバインディングは、編集可能なフォームや完全対話型の UI シナリオに適しています。

OneWay
バインディング ソース (ソース) の変更時にバインディング ターゲット (ターゲット) プロパティを更新します。この型のバインディングは、バインドされているコントロールが暗黙的な読み取り専用の場合に適しています。たとえば、株価情報などのソースにバインドする場合です。また、ターゲット プロパティには、データ バインドされたテーブルの背景色などの変更用コントロール インターフェイスがない可能性もあります。ターゲット プロパティの変更を監視する必要がない場合は、OneWay バインディング モードを使うことにより、TwoWay バインディング モードのオーバーヘッドを回避できます。

OneTime
アプリケーションの起動時またはデータ コンテキストの変更時にバインディング ターゲットを更新します。この型のバインディングは、現在の状態のスナップショットを使用した方がよい場合や、データが完全に静的である場合に適しています。また、ソース プロパティの値を使用してターゲット プロパティを初期化するときにデータ コンテキストが事前にわからない場合にも、この型のバインディングは便利です。基本的に、この型のバインディングは、ソース値が変わらない場合にパフォーマンスを向上させる OneWay バインディングを簡易化したものです。

OneWayToSource
ターゲット プロパティが変更されると、ソース プロパティを更新します。

Default
バインディング ターゲットの既定の Mode 値を使用します。ただし、既定値は、各依存関係プロパティによって異なります。一般に、ユーザーが編集できる、テキスト ボックスやチェック ボックスなどのコントロール プロパティは既定で双方向のバインディングであり、それ以外のほとんどのプロパティは既定で一方向のバインドになります。依存関係プロパティが既定で一方向と双方向のいずれであるかをプログラムにより決定する 1 つの方法は、GetMetadata を使用してプロパティのプロパティ メタデータを取得してから、BindsTwoWayByDefault プロパティのブール値を確認することです。

TwoWay時のソースの更新時期(UpdateSourceTrigger)は、Default, Explicit, LostFocus, PropertyChanged

<TextBox Name="textBox1" Text="{Binding Path=Text, ElementName=textBox2, Mode=TwoWay, UpdateSourceTrigger=Default}"/>
<TextBox Name="textBox2" VerticalAlignment="Top" />

ZAM3Dが生成するXAMLをC#で実装すると ー リソースモデル

リソースモデルはこんな感じ。

        private void Sample()
        {
            this.viewPort3D1.Name = "ZAM3DViewport3D";
            viewPort3D1.ClipToBounds = true;
            viewPort3D1.Width = 400;
            viewPort3D1.Height = 300;

            ResourceDictionary resourceDictionary = new ResourceDictionary();

            ////
            
            MaterialGroup materialGroup = new MaterialGroup();

            DiffuseMaterial diffuseMaterial = new DiffuseMaterial();
            diffuseMaterial.Brush = new SolidColorBrush(Color.FromRgb(0xd3, 0xc8, 0xad));
            materialGroup.Children.Add(diffuseMaterial);

            SpecularMaterial specularMaterial = new SpecularMaterial();
            specularMaterial.SpecularPower = 93f;
            specularMaterial.Brush = new SolidColorBrush(Color.FromRgb(0x33, 0x33, 0x33));
            materialGroup.Children.Add(specularMaterial);

            resourceDictionary.Add("ER___Default_MaterialMR1", materialGroup);

            ////

            Transform3DGroup transform3DGroup = new Transform3DGroup();

            TranslateTransform3D translateTransform3D = new TranslateTransform3D(0f, 0f, 0f);
            ScaleTransform3D scaleTransform3D = new ScaleTransform3D(1f, 1f, 1f);
            AxisAngleRotation3D axisAngleRotation3D = new AxisAngleRotation3D(new Vector3D(0f, 1f, 0f), 0f);
            RotateTransform3D rotateTransform3D = new RotateTransform3D();
            rotateTransform3D.Rotation = axisAngleRotation3D;
            TranslateTransform3D translateTransform3D2 = new TranslateTransform3D(0f, 0f, 0f);
            
            transform3DGroup.Children.Add(translateTransform3D);
            transform3DGroup.Children.Add(scaleTransform3D);
            transform3DGroup.Children.Add(rotateTransform3D);
            transform3DGroup.Children.Add(translateTransform3D2);

            resourceDictionary.Add("SceneTR7", transform3DGroup);

            ////

            Transform3DGroup transform3DGroupBox = new Transform3DGroup();

            TranslateTransform3D translateTransform3DBox = new TranslateTransform3D(0f, 0f, 0f);
            ScaleTransform3D scaleTransform3DBox = new ScaleTransform3D(1f, 1f, 1f);
            AxisAngleRotation3D axisAngleRotation3DBox = new AxisAngleRotation3D(new Vector3D(0f, 1f, 0f), 0f);
            RotateTransform3D rotateTransform3DBox = new RotateTransform3D();
            rotateTransform3DBox.Rotation = axisAngleRotation3DBox;

            TranslateTransform3D translateTransform3DBox2 = new TranslateTransform3D(0, 0, 0);

            transform3DGroupBox.Children.Add(translateTransform3DBox);
            transform3DGroupBox.Children.Add(scaleTransform3DBox);
            transform3DGroupBox.Children.Add(rotateTransform3DBox);
            transform3DGroupBox.Children.Add(translateTransform3DBox2);

            resourceDictionary.Add("BoxOR9TR8", transform3DGroupBox);

            ////

            MeshGeometry3D meshGeometry3D = new MeshGeometry3D();

            TypeConverter i32ColConv = TypeDescriptor.GetConverter(typeof(Int32Collection));
            meshGeometry3D.TriangleIndices = (Int32Collection)i32ColConv.ConvertFromString("0,1,2 2,3,0 4,5,6 6,7,4 8,9,10 10,11,8 12,13,14 14,15,12 16,17,18 18,19,16 20,21,22 22,23,20");

            TypeConverter vector3DColConv = TypeDescriptor.GetConverter(typeof(Vector3DCollection));
            meshGeometry3D.Normals = (Vector3DCollection)vector3DColConv.ConvertFromString("0,0,-1 0,0,-1 0,0,-1 0,0,-1 0,0,1 0,0,1 0,0,1 0,0,1 0,-1,0 0,-1,0 0,-1,0 0,-1,0 1,0,0 1,0,0 1,0,0 1,0,0 0,1,0 0,1,0 0,1,0 0,1,0 -1,0,0 -1,0,0 -1,0,0 -1,0,0 ");

            TypeConverter point3DColConv = TypeDescriptor.GetConverter(typeof(Point3DCollection));
            meshGeometry3D.Positions = (Point3DCollection)point3DColConv.ConvertFromString("-0.5,-0.5,-0.5 -0.5,0.5,-0.5 0.5,0.5,-0.5 0.5,-0.5,-0.5 -0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,-0.5 0.5,-0.5,-0.5 0.5,-0.5,0.5 -0.5,-0.5,0.5 0.5,-0.5,-0.5 0.5,0.5,-0.5 0.5,0.5,0.5 0.5,-0.5,0.5 0.5,0.5,-0.5 -0.5,0.5,-0.5 -0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,-0.5 -0.5,-0.5,-0.5 -0.5,-0.5,0.5 -0.5,0.5,0.5 ");

            resourceDictionary.Add("BoxOR9GR10", meshGeometry3D);

            ////

            PerspectiveCamera camera = new PerspectiveCamera();
            camera.FarPlaneDistance = 10f;
            camera.LookDirection = new Vector3D(2.05609, -1.21509, -2.52021);
            camera.UpDirection = new Vector3D(0f, 1f, 0f);
            camera.NearPlaneDistance = 2f;
            camera.Position = new Point3D(-2.05609, 1.21509, 2.52021);
            camera.FieldOfView = 39f;
            viewPort3D1.Camera = camera;

            ////


            ModelVisual3D modelVisual3D = new ModelVisual3D();
            Model3DGroup model3DGroup = new Model3DGroup();
            model3DGroup.Transform = (Transform3D)resourceDictionary["SceneTR7"];

            //////
            AmbientLight ambientLight = new AmbientLight(Color.FromRgb(0x33, 0x33, 0x33));
            model3DGroup.Children.Add(ambientLight);
            DirectionalLight directionalLight1 = new DirectionalLight(Colors.White, new Vector3D(-0.6f, -0.5f, -0.6f));
            model3DGroup.Children.Add(directionalLight1);
            DirectionalLight directionalLight2 = new DirectionalLight(Colors.White, new Vector3D(0.6f, -0.5f, -0.6f));
            model3DGroup.Children.Add(directionalLight2);

            ////

            MeshGeometry3D meshGeometry3D2 = (MeshGeometry3D)resourceDictionary["BoxOR9GR10"];
            GeometryModel3D geometryModel3D = new GeometryModel3D();
            geometryModel3D.Geometry = meshGeometry3D2;
            geometryModel3D.Material = resourceDictionary["ER___Default_MaterialMR1"] as Material;
            geometryModel3D.BackMaterial = (Material)resourceDictionary["ER___Default_MaterialMR1"];

            model3DGroup.Children.Add(geometryModel3D);


            modelVisual3D.Content = model3DGroup;

            this.viewPort3D1.Children.Add(modelVisual3D);
        }
 
このスペースにアクセスしていただき、ありがとうございます。
Please wait...
Sorry, the comment you entered is too long. Please shorten it.
You didn't enter anything. Please try again.
Sorry, we can't add your comment right now. Please try again later.
To add a comment, you need permission from your parent. Ask for permission
Your parent has turned off comments.
Sorry, we can't delete your comment right now. Please try again later.
You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
Complete the security check below to finish leaving your comment.
The characters you type in the security check must match the characters in the picture or audio.
こちらでははじめまして。tama_5こと玉上です。
せっかく友人リストにお誘い頂いたのに、ご挨拶が遅れてしまい申し訳ありません。
 
ところで、
私の見ているブログが偏っているためかわかりませんが、ここまでWPFで本格的に
3Dを扱っているところは初めて拝見しました!
しかも、今話題の初音ミクを題材にしていて、3Dに全く明るくない私でもとてもとっつきやすいです。
3D、特に人型のを扱うWPFについて勉強するときにぜひ参考にさせていただきますね。^^
Apr. 1

天気予報

Loading...