2008年8月4日月曜日

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Diagnostics;

using System.Drawing.Design;

using System.IO;

using System.Reflection;

using System.Reflection.Emit;

using System.Text;

using System.Windows.Forms;

using GeoLibrary;

using GeoLibrary.Design;

using GeoLibrary.Interfaces;

using GeoLibrary.Delegates;

using GeoLibrary.Properties;



namespace GeoLibrary.Components

{

///

/// イベント監視コンポーネントクラス

///


///

///


#if !DEBUG

[DebuggerStepThrough()]

#endif

[Designer(typeof(GuardianComponentDesigner))]

[ProvideProperty("EventList", typeof(Component))]

[ResourceDescription("CTL_DSC_SEASER")]

public class Guardian

: Component, IExtenderProvider

{

///

/// コンポーネント別のイベントリストホルダを保持します

///


private Dictionary m_eventDictionary;



///

/// ログ用ディレクトリ情報オブジェクトを保持します

///


private LogDirectoryInfo m_logDirectoryInfo;



///

/// ログ用ディレクトリ情報オブジェクト設定済フラグを保持します

///


private bool m_setDirectoryFlg;



///

/// コンポーネントプールを保持します

///


private List m_componetPool;



///

/// 同期用オブジェクト

///


private object m_lockObject;



///

/// デザイナオブジェクト用プロパティ

/// コンポーネント別のイベントリストホルダを取得設定します

/// デザイン時のみのプロパティ

///


/// イベントリストホルダディクショナリ

[Browsable(false)]

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]

public Dictionary EventDictionary

{

set

{

// セットはデザイン時のみです

if (!this.DesignMode)

{

throw new InvalidOperationException(Resources.ERR_MES_INVALID_OPE);

}

// 引数をチェック

else if (value == null)

{

throw new NullReferenceException(Resources.ERR_MES_ARG_NULL);

}



this.m_eventDictionary = value;

}

get

{

return this.m_eventDictionary;

}

}



///

/// デザイナ用メソッド

/// ログ用ディレクトリの変更を検知するために必要です

///


///

private bool ShouldSerializeLogDirectory()

{

return true;

}



///

/// デザイナ用メソッド

/// ログ用ディレクトリを初期化するために必要です

///


private void ResetLogDirectory()

{

this.m_logDirectoryInfo = new LogDirectoryInfo();

}



///

/// ログ用ディレクトリを設定します

///


/// ログ用ディレクトリ

[Category(Grobal.C_CATEGORY)]

[ResourceDescription("PRO_DSC_LOGDIRECTORYINFO")]

[TypeConverter(typeof(LogDirectoryInfoTypeConverter))]

public LogDirectoryInfo LogDirectory

{

set

{

// 引数をチェック

if (value == null)

{

value = new LogDirectoryInfo();

}



this.m_logDirectoryInfo = value;



// デザインモードならここまで

if (this.DesignMode)

{

return;

}



// クリティカルセクション

lock (this.m_lockObject)

{

// フラグをセット

this.m_setDirectoryFlg = true;



// コンポーネントプールをチェック

if (this.m_componetPool != null)

{

foreach (Component component in this.m_componetPool)

{

this.CoreTask(component);

}

}



// コンポーネントプールを削除

this.m_componetPool = null;

}

}

get

{

return this.m_logDirectoryInfo;

}

}



///

/// デザイナ用メソッド

/// コンポーネント別のイベントリストホルダの変更を検知するために必要です

///


///

private bool ShouldSerializeEventList(Component a_component)

{

try

{

if (this.GetEventList(a_component).AddedEventList.Count == 0)

{

return false;

}

return true;

}

catch

{

return true;

}

}



///

/// コンポーネント別のイベントリストホルダを取得します

///


/// コンポーネント

/// イベントリストホルダ

[Category(Grobal.C_CATEGORY)]

[Editor(typeof(EventListHolderValueEditor), typeof(UITypeEditor))]

[ResourceDescription("PRO_DSC_EVENTLISTHOLDER")]

[TypeConverter(typeof(EventListHolderTypeConverter))]

public EventListHolder GetEventList(Component component)

{

// 引数をチェック

if (component == null)

{

throw new NullReferenceException("component が null 参照です");

}



// コンポーネントに対するイベントリストオブジェクトを保持していなければ

if (!this.m_eventDictionary.ContainsKey(component))

{

// 新規に生成する

EventListHolder holder = new EventListHolder();



// 生成したリストホルダにイベントリストを追加

holder.EventList.InsertRange(0, component.GetType().GetEvents());



// ディクショナリに追加

this.m_eventDictionary.Add(component, holder);

}



// 値を返す

return this.m_eventDictionary[component];

}



///

/// コンポーネント別のイベントリストホルダを設定します

///


/// コンポーネント

/// イベントリストホルダ

[Category(Grobal.C_CATEGORY)]

[Editor(typeof(EventListHolderValueEditor), typeof(UITypeEditor))]

[ResourceDescription("PRO_DSC_EVENTLISTHOLDER")]

[TypeConverter(typeof(EventListHolderTypeConverter))]

public void SetEventList(Component component, EventListHolder listHolder)

{

// 引数をチェック

if (component == null)

{

throw new NullReferenceException("component が null 参照です");

}



// コンポーネントに対するイベントリストオブジェクトを保持していなければ

if (!this.m_eventDictionary.ContainsKey(component))

{

// 新規に生成する

this.m_eventDictionary.Add(component, null);

}



// 値をセット

this.m_eventDictionary[component] = listHolder;



// デザインモード、もしくはイベントリストホルダがnull参照ならここまでで終了

if (this.DesignMode || listHolder == null)

{

return;

}



// クリティカルセクション

lock (this.m_lockObject)

{

// ログ用ディレクトリがセットされていれば

if (this.m_setDirectoryFlg)

{

// ハンドラの生成を行う

this.CoreTask(component);

}

// セットされていなければコンポーネントプールに追加

else

{

if (this.m_componetPool == null)

{

this.m_componetPool = new List();

}

this.m_componetPool.Add(component);

}

}

}



///

/// コンストラクタ

///


public Guardian()

: base()

{

this.m_eventDictionary = new Dictionary();

this.m_logDirectoryInfo = new LogDirectoryInfo();

this.m_setDirectoryFlg = false;

this.m_componetPool = null;

this.m_lockObject = new object();

}



///

/// コンストラクタ

///


/// コンテナ

public Guardian(IContainer container)

: this()

{

container.Add(this);

}



///

/// コアタスク

/// 動的ハンドラを生成します

///


///

private void CoreTask(Component component)

{

try

{

// コンポーネントごとに指定されたイベントを全てフックします

if (this.m_eventDictionary.ContainsKey(component))

{

Type type;

MethodInfo addMethod;



// 全イベントのハンドラを動的に生成

List eventList = this.m_eventDictionary[component].AddedEventList;

foreach (EventInfo eventInfo in eventList)

{

try

{

type = eventInfo.EventHandlerType;

if (!GrobalHandlerDictionary.Contains(type, eventInfo.Name))

{

GrobalHandlerDictionary.CreateDynamicHandler(type, eventInfo.Name, this.m_logDirectoryInfo);

}

addMethod = eventInfo.GetAddMethod();

addMethod.Invoke(component, new Object[] { GrobalHandlerDictionary.GetDynamicHandler(type, eventInfo.Name) });

}

catch

{

Grobal.GrobalErrorHandler("Guardian.CoreTask¥r¥n予期せぬ例外", 1, 1);

}

}

}

}

catch

{

Grobal.GrobalErrorHandler("Guardian.CoreTask¥r¥n予期せぬ例外", 1, 1);

}

}



///

/// IExtenderProviderインターフェイス実装

/// コンポーネントに対して拡張プロパティを実装するかどうかの値を取得します

///


/// 対象コンポーネント

///

/// true : 実装する

/// false : 実装しない

///


public virtual bool CanExtend(object extendee)

{

if (extendee is Guardian)

{

return false;

}

return true;

}

}

}
using System;

using System.Reflection;

using System.Collections.Generic;

using System.Reflection.Emit;

using System.Diagnostics;

using System.IO;

using System.Threading;

using System.ComponentModel;

using System.Windows.Forms;

using GeoLibrary.Interfaces;

using GeoLibrary.Properties;



namespace GeoLibrary

{

///

/// グローバルハンドラディクショナリクラス

///

/// イベントログ用に生成した動的ハンドラを管理します

///


///

///


#if !DEBUG

[DebuggerStepThrough()]

#endif

public static class GrobalHandlerDictionary

{

///

/// 動的メソッドディクショナリを保持します

///


private static Dictionary> s_dynamicMethodDictionary;



///

/// 同期用オブジェクト

///


private static object s_lockObject;



///

/// 静的コンストラクタ

///


static GrobalHandlerDictionary()

{

GrobalHandlerDictionary.s_dynamicMethodDictionary = new Dictionary>();

GrobalHandlerDictionary.s_lockObject = new object();

}



///

/// 動的ハンドラ取得メソッド

/// ハンドラタイプ、イベント名、片方でも存在しない場合は例外が発生します

///


/// ハンドラタイプ

/// イベント名

/// 動的ハンドラ

public static Delegate GetDynamicHandler(Type type, string eventName)

{

return GrobalHandlerDictionary.s_dynamicMethodDictionary[type][eventName];

}



///

/// 動的ハンドラ生成メソッド

///

/// 引数のイベント情報オブジェクトからイベントハンドラの型を抽出し

/// その型の動的ハンドラを作成します

///

/// 第2引数のログ用ディレクトリ情報オブジェクトの指すディレクトリパスは

/// 動的ハンドラ内で呼び出されるログアウトメソッドに引数として渡されます

///


/// イベントハンドラタイプ

/// イベント名

/// ログ用ディレクトリ情報

public static void CreateDynamicHandler(Type type, string eventName, LogDirectoryInfo logDirectoryInfo)

{

const string C_INVOKE = "Invoke";

const string C_LOGOUTMETHOE = "LogOut";



lock (GrobalHandlerDictionary.s_lockObject)

{

// イベントタイプをチェック

if (type.BaseType != typeof(MulticastDelegate))

{

throw new ArgumentException(Resources.ERR_MES_TYPEOBJECT);

}



// さらにチェック

MethodInfo invoke = type.GetMethod(C_INVOKE);

if (invoke == null)

{

throw new ArgumentException(Resources.ERR_MES_TYPEOBJECT);

}



// 登録されていなければハンドラを生成

if (!GrobalHandlerDictionary.s_dynamicMethodDictionary.ContainsKey(type) ||

GrobalHandlerDictionary.s_dynamicMethodDictionary[type] == null ||

!GrobalHandlerDictionary.s_dynamicMethodDictionary[type].ContainsKey(eventName))

{

// イベントデリゲートの全パラメータを取得

ParameterInfo[] parameters = invoke.GetParameters();

Type[] typeParameters = new Type[parameters.Length];

for (int i = 0; i < dynamicmethod =" new" logoutparameters =" new" logoutmethod =" typeof(GrobalHandlerDictionary).GetMethod(C_LOGOUTMETHOE," path =" logDirectoryInfo.FullName;" ilgenerator =" dynamicMethod.GetILGenerator();">());

}

GrobalHandlerDictionary.s_dynamicMethodDictionary[type].Add(eventName, dynamicMethod.CreateDelegate(type));

}

}

}



///

/// 動的ハンドラ検索メソッド

///


/// ハンドラタイプ

/// ログ用イベント名

///

/// true : 動的ハンドラあり

/// false : 動的ハンドラなし

///


public static bool Contains(Type type, string eventName)

{

if (GrobalHandlerDictionary.s_dynamicMethodDictionary.ContainsKey(type))

{

if (GrobalHandlerDictionary.s_dynamicMethodDictionary[type] != null)

{

if (GrobalHandlerDictionary.s_dynamicMethodDictionary[type].ContainsKey(eventName))

{

if (GrobalHandlerDictionary.s_dynamicMethodDictionary[type][eventName] != null)

{

return true;

}

}

}

}

return false;

}



///

/// ログアウトメソッド

///

/// イベントログを対象にしています

/// 第3・4引数にはイベントハンドラ用の引数をそのまま渡してください

///


/// イベント名

/// ログ用ディレクトリパス

/// sender

/// e

public static void LogOut(string eventName, string directoryPath, object sender, EventArgs e)

{

try

{

string log;

if (e is ILogHolder)

{

log = (e as ILogHolder).Log;

}

else if (sender is Control)

{

log = (sender as Control).Name;



if (sender is CheckBox)

{

log += " " + ((sender as CheckBox).Checked ? "Checked" : "Unchecked");

}

else if (sender is ComboBox)

{

log += "¥nText=¥"" + (sender as ComboBox).Text + "¥" SelectedIndex=" + (sender as ComboBox).SelectedIndex.ToString();

}

else if (sender is TextBox)

{

log += " ¥"" + (sender as TextBox).Text + "¥"";

}

else if (sender is RichTextBox)

{

log += "¥n¥"" + (sender as RichTextBox).Text.TrimEnd(new char[] { '¥r', '¥n' }) + "¥"";

}

else if (sender is System.Windows.Forms.Label)

{

log += " ¥"" + (sender as System.Windows.Forms.Label).Text + "¥"";

}

}

else if (sender != null)

{

log = sender.ToString();

}

else

{

log = "null";

}



// ログをイベントログライタオブジェクトに渡す

XmlEventLogWriter.GetXmlLogWriter(directoryPath).LogWrite(eventName, log);

}

catch

{

Grobal.GrobalErrorHandler(Resources.ERR_MES_LOGOUT, 1, 1);

}

}

}

}

2008年2月7日木曜日

dumpbin.exe

dumpbin.exeの使い方

ヘッダの抽出

dumpbin.exe /headers ***.exe

OPTIONAL HEADER VALUESセクションの
entry point (0040230E)

はアドレス空間内のエントリポイントアドレスを示す。

SECTION HEADERセクションの

314 virtual size

2000 virtual address (00402000 to 00402313)

400 size of raw data

200 file pointer to raw data (00000200 to 000005FF)

は仮想空間の 0x00402000 から 0x00402313 までが

ファイル上の 0x00000200 から 0x000005FF までと対応することを示す。

ちなみにとあるexeのエントリポイントを見てみた。

4A 00 FF 25 C4 26 4A 00

jmp 0x004A26C4

かな?

さらに詳しく見たければ以下を実行

dumpbin.exe /imports ***.exe

そうすると、

KERNEL32.dll

4A2094 Import Address Table

4C70B8 Import Name Table

0 time date stamp

0 Index of first forwarder reference

このように表示されたので、エントリポイントから

KERNEL32.dll内に飛んでいるらしいことがわかった・・・。

ちなみに一度に実行し、ファイルに出力するなら以下。

dumpbin.exe /headers /imports ***.exe /out:C:\***.txt

2008年1月18日金曜日

.NET での共用体

.NET Framework の 共通言語仕様(CLS)には共用体は存在しません。また、C#にもVB.NETにも共用体は存在しません。共用体自体はそれほど使う機会が多いというわけではないですし、また、なければならないというものでもありません。しかし、ごく稀にあると便利かなと思うことがあります。そういうときに、.NET FrameworkのStructLayout属性とFieldOffset属性を用いるとC#やVB.NETの構造体でも共用体の機能を再現することができます。それではまずStructLayout属性について見てみることにします。この属性は構造体(クラスも可)に対して適用し、この属性を適用することで構造体の各メンバ変数のメモリ上での配置方法を指定することができます。具体的には、LayoutKind.Autoを指定するとコンパイラが最も適した方法で配置し、LayoutKind.Sequentialを指定するとメモリ内に連続して順番に配置され、LayoutKind.Explicitを指定するとプログラム側で明示的に位置を指定しなければなりません。また、ここでLayoutKind.Explicitを指定すると、全てのメンバ変数に対して明示的に位置を指定しなければなりません。そこで、位置を指定するために使用する属性がFieldOffset属性です。この属性では構造体の先頭から各メンバ変数の先頭までのオフセット値をバイト単位で指定します。それでは、早速これらの属性を適用した構造体を作成してみようと思います。このサンプルではshortではなくSystem.UInt16を用いていますが、16Bitの符号無し整数型を用いていると言うことを視覚的に表すためであって、それ以外に深い意味はありません。

using System;
using System.Runtime.InteropServices;
namespace StructAndUnion
{
 // StructLayout属性及びFieldOffset属性を適用した構造体
 [StructLayout(LayoutKind.Explicit)]
 struct SampleStruct
 {
  [FieldOffset(0)] public System.UInt16 Value1;
  [FieldOffset(2)] public System.UInt16 Value2;
  [FieldOffset(4)] public System.UInt16 Value3;
  [FieldOffset(6)] public System.UInt16 Value4;
 }

 // アプリケーションのエントリーポイントを提供するクラス
 class SampleClass
 {
  [STAThread]
  static void Main(string[] args)
  {
   SampleStruct s = new SampleStruct();
   // 各フィールドに値を指定
   s.Value1 = 0x1122;
   s.Value2 = 0x3344;
   s.Value3 = 0x5566;
   s.Value4 = 0x7788;

   // 各フィールドの値を表示
   Console.WriteLine( "SampleStruct.Value1 : 0x" + s.Value1.ToString("X4") );
   Console.WriteLine( "SampleStruct.Value2 : 0x" + s.Value2.ToString("X4") );
   Console.WriteLine( "SampleStruct.Value3 : 0x" + s.Value3.ToString("X4") );
   Console.WriteLine( "SampleStruct.Value4 : 0x" + s.Value4.ToString("X4") );
  }
 }
}

オフセット値 格納値
 0 0x22
 1 0x11
 2 0x44
 3 0x33
 4 0x66
 5 0x55
 6 0x88
 7 0x77

このように、StructLayout属性で明示的に配置方法を指定することができ、FieldOffsetでメンバ変数のオフセット値を指定することが出きるとなれば、共用体を作る方法はおのずと浮かんでくるはずです。つまり、共用体の仕組み・構造を思い浮かべて下さい。共用体では一つ以上の同じまたは異なる型のメンバが、同じメモリ領域を共用します。つまり、メンバ変数のオフセット値を全て同じにすれば、共用体と同じ構造の構造体を作ることができることになります。

using System;
using System.Runtime.InteropServices;
namespace StructAndUnion
{
 // 構造体で再現した共用体
 [StructLayout(LayoutKind.Explicit)]
 struct DoubleWord
 {
  [FieldOffset(0)] public System.UInt32 Value;
  [FieldOffset(0)] public System.UInt16 LowWord;
  [FieldOffset(2)] public System.UInt16 HighWord;
 }

 // アプリケーションのエントリーポイントを提供するクラス
 class SampleClass
 {
  [STAThread]
  static void Main(string[] args)
  {
   DoubleWord dw = new DoubleWord();

   // ダブルワード値を指定
   dw.Value = 0x11223344;

   // 下位ワードと上位ワードを表示
   Console.WriteLine( "Low word: 0x" + dw.LowWord.ToString("X4") );
   Console.WriteLine( "High word: 0x" + dw.HighWord.ToString("X4") );
  }
 }
}

オフセット値 格納値
 0 0x44
 1 0x33
 2 0x22
 3 0x11

Windows XPでの自動ログイン

1. コマンドラインから 、もしくはファイル名を指定してcontrol userpasswords2を実行
2.「ユーザーがこのコンピュータを使うには、ユーザー名とパスワードの入力が必要」のチェックをはずして適用
3.自動ログインしたいユーザ名とパスワードを入力

2008年1月9日水曜日

VSセットアッププロジェクトでのGACの登録方法

セットアッププロジェクトから「ファイルシステム」を表示し、「対象コンピュータ上のファイルシステム」を右クリック。「特別なフォルダの追加(A)」より、「グローバル アセンブリ キャッシュ フォルダ」を追加し、GACに登録するDLLファイルを登録して完了

.NET コンポーネントの追加の仕方

レジストリエディタを開き、

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\AssemblyFolder\任意の名前HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727\AssemblyFoldersEx\任意の名前

にパスを登録する