2006年03月27日

意義は知らないけれど

某スレ主氏に捧ぐ(でもとても奨められたもんではないので見せられない)コード。

Module FormManager
  Private forms As New Dictionary(Of Type, Form)
  Public Function GetForm(Of TForm As Form)( _
           ParamArray args As Object()) As TForm
    Dim t As Type = GetType(TForm)
    If (Not(forms.ContainsKey(t)) _
        OrElse forms(t).IsDisposed) Then
      Dim form As TForm _
          = DirectCast(Activator.CreateInstance(t, args), _
                       TForm)
      forms(t) = form
      Return form
    End If
    Return DirectCast(forms(t), TForm)
  End Function
End Module
posted by Hongliang at 19:50| Comment(0) | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

動的なDLLインポート

連載が終わった途端放置気味。意味もなく五七五で始めてみました。

コメント欄でちょっと話の出たホットキーの記事を書こうと思っていたのですが、調べれば調べるほど(本筋とは関係のないところで)難しい話になっていったので、後回し。いつになるかは未定義です。こだわりさえ捨てればいいんですが。

今回のネタはまさにネタですが、動的にアンマネージド DLL をインポートするってどうよ、と言う話です。

アンマネージド関数のインポートは通常 DllImport 属性(あるいは VB.NET なら Declare 構文)を使いますが、これを使用してインポートするには DLL 名とエントリポイントを静的に決定しておかなければなりません。これでは例えば統合アーカイバプロジェクトの DLL を使うにも、別の DLL に対しては別の関数を使わざるを得ず、あまり嬉しくない状況です。

続きを読む
posted by Hongliang at 16:00| Comment(8) | TrackBack(1) | .NET | このブログの読者になる | 更新情報をチェックする

2006年03月20日

COM クライアント実装の道程 for TaskScheduler その最終回

さて一連のシリーズもいよいよ最終回。最後は TaskScheduler クラスの使い方をつらつら書いていくことにしましょう。

続きを読む
posted by Hongliang at 22:11| Comment(3) | TrackBack(0) | .NET | このブログの読者になる | 更新情報をチェックする

2006年03月18日

COM クライアント実装の道程 for TaskScheduler その8

いよいよ連載も大詰め。TaskTrigger について解説していきましょう。

その前にまずは大元の TASK_TRIGGER 構造体を解説しなければなりません。TASK_TRIGGER 構造体はこれまで述べたとおりタスクの起動するタイミング(トリガ)を記述する構造体で、この構造体一つであらゆるトリガを表現します。そのため、TASK_TRIGGER は以下のメンバを持ちます。

  • 自身がどの種類の起動タイプなのかを表す TASK_TRIGGER_TYPE 列挙体の値
  • その起動タイプに固有の値を持つ TRIGGER_TYPE_UNION 共用体
続きを読む
posted by Hongliang at 21:03| Comment(2) | TrackBack(1) | .NET | このブログの読者になる | 更新情報をチェックする

2006年03月16日

COM クライアント実装の道程 for TaskScheduler その7

仕様を策定する人って絶対暇人ですよね。

前回の続きと言うことで、ITask に関するいくつかの実装を見ていきましょう。

まずは TaskScheduler クラスと同じく、Task クラスの基礎実装を。まあ ComInterfaceWrapper を継承して、内部で使用するインターフェイスを private プロパティにするだけですから同じですけど。ただ、コンストラクタは構成からして外部に公開する必要はないので、internal/Friend としておきます。ITask は単独で作成できますが、それは認めない方向で。

続きを読む
posted by Hongliang at 22:29| Comment(0) | TrackBack(0) | .NET | このブログの読者になる | 更新情報をチェックする

2006年03月14日

ListView にカラム

引き続きシリーズの外。今回は完全に外。@IT の ネイティブアプリとCLRアプリの違い スレッドより。

スレ主さん曰く、Becky! のリストビューは第一カラムが幅固定であると。.NET のプロパティにはそう設定できるプロパティがないと。まあそういうことらしいです。しかし考えてみれば生 API 使うのならもともとプロパティだのなんて存在しませんし、MFC の CListView クラスなどにもそんなのありません。あるのはただ WM_NOTIFY と いくつかのメッセージのみ。別にこの辺がアンマネージドというわけでは、まあありますが、幸いメモリのことは一切勘案することなく、unsafe にもしないで、Marshal クラスも使わず書ける部分です。

WndProc のオーバーライドだって普通に存在しているんだから使わなければ損損。と言う比較的現実主義な私としては早速実装してみるのでした。

続きを読む
posted by Hongliang at 05:56| Comment(0) | TrackBack(0) | C# | このブログの読者になる | 更新情報をチェックする

2006年03月13日

CInt とオーバーフロー

今回はちょっとシリーズを離れてオーバーフローのお話です。なんか似た話題を以前にやった気もしますが。

アンマネージドとやりとりしていると、異なる数値型間の変換が必要になる場面が出てきます。今回 Task クラスの実装を書いている場面でも、それが必要になる場面がありました。

アンマネージドとは DWORD つまり UInt32 でやりとりしますが、そのままでは意味を取りづらいので TimeSpan 型としてプロパティを定義し、内部で Int32 に変換するというやり方です。DWORD を あえて Int32 で書くのはまあ CLS 準拠を目指すための癖みたいなもんです。今考えるとこれが悩みの元になったわけなんですが。

そのアンマネージドのメソッドは 0 から 0xFFFFFFFFL まで受け入れるため、TimeSpan.TotalMilliseconds を 一旦 Int64 にキャストし、最大値チェックを行った後 Int32 にキャストし直そうという算段でした。

unchecked を使える C# はともかく、VB.NET での Int64 から Int32 へのキャストは CInt か Convert.ToInt32 になりますが、この二つはいずれもオーバーフローを抑止するオプションが存在しないため、変換元の値を確認して &H80000000L 以上だったら &H100000000L を引く、そして変換ってのがわかりやすい手段です。

この過程で、何を思ったか Int64 に And &HFFFFFFFFL の演算をしてやればどうだろう? という思考にたどり着きました。確かに 32bit にはなりますがだからって CInt したときオーバーフローするのには変わらないのに。

ところがどっこい、これが何故かエラーが出なかったのです。もとの Int64 に &HFFFFFFFEL が入っていた場合、CInt した結果普通に -2 になります。気持ち悪。ちなみに C# でも checked ステートメント内で同じ結果になります。

IL レベルでも問題なく conv.ovf.i4 が発行されているため、さっぱり原因がつかめません。いい加減煮詰まったので 2ch で聞いてみたら、いくつかやりとりがあった末に こういう結論に。つまり定数が 32bit で収まること、また And 演算のため計算結果も必ず 32 bit 以下になることから、定数の下位 32bit で演算するように最適化する。そのとき正しくは通るべきオーバーフローチェックがパスされてしまう、と。また Mono では普通にオーバーフローするらしいです。つきあってくださった方々、改めてありがとうございました。

And &HFFFFFFFFL 後の CInt が決してオーバーフローしないのなら利用価値はありますが、x64 版でどうなるか知れたものじゃないし Mono でも普通にオーバーフローするとなると使ってもバグの元になるだけですので封印封印。

まあそう言う顛末の話でした。

しかし VB.NET にもオーバーフローの制御とか三項演算子とか欲しいんですが。IIf は Object でのやりとりになるから IIf(Of T) があればいいんだけどなー。

posted by Hongliang at 21:55| Comment(0) | TrackBack(1) | VB.NET | このブログの読者になる | 更新情報をチェックする

2006年03月12日

COM クライアント実装の道程 for TaskScheduler その6

死亡フラグって言いますよね。「この戦争が終わったら、俺、結婚するんだ」とか言うの。これ、死にフラグって表現もあると言うことを最近知りました。しかし死にフラグってのは、まるで上げ下げはしてるんだけどだれもそのフラグを参照してない孤独なフラグってイメージが。いやどうでも良いんですが。

今回から Task と TaskTrigger の解説に入るわけですが、いきなりクラスの解説をし出しても理解しにくいでしょうから、まずその下準備として ITask インターフェイスを中心にタスクアイテムの構造を述べていくことにします。

と切り出しておいて何ですが、実のところタスクアイテムの構成ってのはタスクのプロパティダイアログに表示されている奴ほぼそのままなんですよね。

続きを読む
posted by Hongliang at 17:38| Comment(0) | TrackBack(0) | .NET | このブログの読者になる | 更新情報をチェックする

2006年03月11日

COM クライアント実装の道程 for TaskScheduler その5

ID3タグってーのは調べれば調べるほど混沌としてきますね。あと v2.4 が出てもう5年以上立ってるけど結局 v2.3 の方が使われているような。WMP も v2.3 みたいだし。

さて、今回は前回の資産を生かして ITaskScheduler を .NET に相応しいクラスにラッピングします。まずは改めて ITaskScheduler のメンバを一覧しましょう。

メソッド 機能
SetTargetComputerこのインスタンスが操作の対象とするコンピュータの名前を設定する。
GetTargetComputerこのインスタンスが操作の対象とするコンピュータの名前を取得する。
Enum 現在のタスクフォルダに入っているタスクを列挙する。
Activate 操作するタスクを取得する。
Delete タスクを削除する。
NewWorkItem 新しいタスクアイテムをメモリに作成する。
AddWorkItem 新しいタスクアイテムのファイルを作成する。
IsOfType 指定したタスクアイテムが特定のインターフェイスをサポートしているかどうかを確認する。
続きを読む
posted by Hongliang at 18:08| Comment(0) | TrackBack(0) | .NET | このブログの読者になる | 更新情報をチェックする

2006年03月10日

COM クライアント実装の道程 for TaskScheduler その番外編2 〜 COM オブジェクトと GC とファイナライザ

ノートの方には MSDN の Platform SDK 部分は入れていなかったので、この記事を書くのにオンラインの MSDN を参照することもあります。で、気づいたんですが、なんか TaskScheduler の関連インターフェイスが増殖してる……。え嘘マジ? と大慌てで調べてみたら、その辺全部 Vista で追加されるインターフェイスのようです。…………。ふ、今やってるのも Vista までの寿命か……。いや後方互換性は残されるみたいですけど。Vista では ITaskScheduler の代わりに ITaskService を使って操作するスタイルになるようですね。増えたインターフェイスは ITaskScheduler では構造体として扱っていた部分みたいです。あるいはそもそも WinFX でサポートされるようになるのかしらん。

さて、今回のお題は COM オブジェクトの面倒くささについてです。知っている人は知っている、というか最近特にクローズアップされだしているような気がしますが(というか私がそう言う情報に敏感になっただけかも)、CLI の基礎でもあるガベージコレクタと COM オブジェクトとは、ひたすら食い合わせが悪いのです。

続きを読む
posted by Hongliang at 03:09| Comment(1) | TrackBack(1) | .NET | このブログの読者になる | 更新情報をチェックする

2006年03月08日

COM クライアント実装の道程 for TaskScheduler その4

いつまでもデスクトップを使っているのは電気代にも優しくないので、そう言えば、と初代ノート PC を引っ張り出してきました。液晶モニタが割れたので新しいのに買い換えたんですが、逆に言えば液晶モニタの問題だけでしたので、デスクトップで使っているモニタが二系統の入力を受け付けているのに目を付け、バルクのモニタケーブルを調達してきてでかいモニタでノートです。操作感的には大して不都合もないのですが(意外に液晶部分もそんな気になりません)、難点は致命的に重いってこと。やたら HDD へのアクセスが発生してるところからみてスワップしまくってんでしょうね。HDD も 4200rpm と旧式ですし。メモリが 240 MB( 16 MB はビデオメモリに割り当て)ってのはやはり厳しいものがあるようです。特に開発に使うものじゃありません。あまつさえ .NET となるともう、OpenFileDialog 開けるだけでなんか 30 秒とか待たされたり、ってなんかほかの要因もあるような気が。

さて、前回の続き。今回はインターフェイスの残りをまとめてやってしまいましょう。TaskScheduler の項目にある六つのインターフェイスのうち、一つは無視すると初めに宣言しました。さらに IScheduledWorkItem は完全に ITask に吸収させることにしました。ので、残りは二つ。いずれも小さい単純なインターフェイスです。

続きを読む
posted by Hongliang at 03:43| Comment(0) | TrackBack(0) | .NET | このブログの読者になる | 更新情報をチェックする

2006年03月07日

COM クライアント実装の道程 for TaskScheduler その3

何故か ID3 タグの仕様を調べています。id3v2 には .NET のライブラリとして UltraID3 と言うのが紹介されていて、初めはこれ使えばいいやと思ったのですが、なんとエンコーディングが Unicode と ISO-8859-1 のどちらかしか選べないと言う致命的な問題点があることが判明。これじゃ大抵 Shift_jis 使ってる日本では使えません……。他にこれほどの柔軟性があるのも見当たらないし。

さて、そんなのは置いておいて、COM インターフェイスの実装の続きと参りましょう。

二回連続で脇道に入っていたこともあって些か記憶が曖昧ですが、確か前回は ITaskScheduler インターフェイスの定義とそのメソッド一つの実行に成功したところだったはずです。今回はタスクスケジューラの中心的インターフェイスである、ITask インターフェイスについて話を進めていきましょう。

このインターフェイスの特徴に、IUnknown から直接派生しているわけではなく、IScheduledWorkItem から派生している点があります。.NET において、このインターフェイスの継承というのはどう扱うべきでしょうか?

続きを読む
posted by Hongliang at 05:33| Comment(0) | TrackBack(0) | .NET | このブログの読者になる | 更新情報をチェックする

2006年03月05日

アンマネージドメモリへの手抜き VB.NET編

もっと早く更新するつもりがいつのまにやら。

では前回のコードの VB.NET 編です。キーワードの色つけはやってません(甚だしい手抜き)。

それと同時に、XML コメント付きの C# ソースへのリンクも。但しこちらは名前空間付いてますのでちょこっとだけ注意。

続きを読む
posted by Hongliang at 10:33| Comment(2) | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

2006年03月03日

COM クライアント実装の道程 for TaskScheduler その番外編1 〜アンマネージドメモリへの手抜き

予告通り、三回目にして速攻で脇道に入ります。

アンマネージドとの相互運用において、面倒なものの一つにアンマネージドメモリの管理があります。.NET ではアンマネージドメモリを扱う場合 System.Runtime.InteropServices.Marshal クラスを使用してアクセスしますが、問題の一つに、解放忘れ即メモリリークにつながるため try-finally が欠かせない、と言うのがあります。面倒です。他にも、バイト配列との相互コピーも事前にバイト配列を確保する必要があったり、文字列を書き込んでも結局何バイト書き込んだのか分からなかったりとか、色々扱いづらい点があります。そこで今回、この辺をクラス化して、多少便利に扱えるようにしたいと思います。もちろん、便利さと速度はプログラミングにおいて大抵は相反するものでして、今回作るのも実行速度に対するパフォーマンスという点は目を瞑っています。ボトルネックになる部分では使用するのも少し考えた方が良いかもしれません。逆に言えばボトルネックでないのなら(私は)気にせず使います。もっとも一回の呼び出しで何秒も使うようなものでもないですから、これの使用そのものがボトルネックになることはあまり考えられませんけど。

ところでこのコンセプトで以前記事を書いたことがあります。05/10/22 の 多少は使いやすい共有メモリクラス、とその VB.NET 向け記事 共有メモリクラス for VB.NET です。今回作るクラスはこれを踏まえて、更に改良を加えて(ると思いますけど)作成しています。この共有メモリクラスも今回作ったクラスに応じて書き換え……は今回の記事にするには容量がはみ出るかな。

続きを読む
posted by Hongliang at 01:34| Comment(0) | TrackBack(0) | C# | このブログの読者になる | 更新情報をチェックする

2006年03月02日

COM クライアント実装の道程 for TaskScheduler その2

では、第二回目です。

第一回では、コクラスは作れましたけど独自のメソッドも何もない、ただ本当に作っただけでした。これを何とか使えるように持っていきましょう。

COM においては、主役はインターフェイスです。インターフェイスを通すことで異言語間などでも問題なく相互運用できるようにし、内部の実装に関わる必要が無くなるわけです。この辺はオブジェクト指向の考えと同じですね。

続きを読む
posted by Hongliang at 14:23| Comment(2) | TrackBack(0) | C# | このブログの読者になる | 更新情報をチェックする

2006年03月01日

COM クライアント実装の道程 for TaskScheduler その1

今回から数回にわたって、シリーズとしてお送りしたいと思います。題して、……この記事のタイトルに出てますね。コードは(ほぼ)完成しているので、あとは記事を書くのみ(いやまあそれも骨なんですけど)。

ちなみに、こんなタイトルですが、実際に COM の部分はそう大した量ではないと思います。.NET とのギャップのマッチング部分が私の作成した実装の肝ですし、COM インターフェイスやアンマネージドメモリを便利に扱うためのラッピングクラスにもそれなりに気を配ったり。

いや、一番疲れたのは XML ドキュメント作成部分でしたけどね。

続きを読む
posted by Hongliang at 06:36| Comment(0) | TrackBack(0) | C# | このブログの読者になる | 更新情報をチェックする

ここ(hongliang.seesaa.net)で公開しているものについて、利用は自由に行って頂いて構いません。改変、再頒布もお好きになさって下さい。利用に対しこちらが何かを要求することはありません。

ただし、公開するものを使用、または参考したことによって何らかの損害等が生じた場合でも、私はいかなる責任も負いません。

あ、こんなのに使ったってコメントを頂ければ嬉しいです。

×

この広告は1年以上新しい記事の投稿がないブログに表示されております。