.NET FrameworkのクラスライブラリのSystem.Reflection.Emit名前空間のクラスを使用すると、アプリケーションの実行時に、実行ファイルを生成することができます。
しかし、あのあたりはヘルプが役に立たない上、動的に実行ファイルを生成するサンプルは、ネット上にほとんど転がっていません。 近いものはMSの英語サイトにサンプルがおいてありましたが。
ってことで、今回は動的にHelloWorldな実行ファイルを出力するサンプルを書いておきます。
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
namespace DynamicEXETest
{
class Program
{
static void Main(string[] args)
{
AppDomain tAppDomain = Thread.GetDomain();
// アセンブリの名前を生成
AssemblyName tAssemblyName = new AssemblyName();
tAssemblyName.Name = "TestDynamicAssembly";
// 動的アセンブリを定義して、そのビルダーを得る
AssemblyBuilder tAssembly = tAppDomain.DefineDynamicAssembly(tAssemblyName, AssemblyBuilderAccess.Save);
// アセンブリ内にモジュールを定義
ModuleBuilder tModule;
tModule = tAssembly.DefineDynamicModule("TestDynamicModule", "TestDynamicModule.mod");
// モジュール内にクラスを定義
TypeBuilder tDynamicClass = tModule.DefineType("TestClassDynamic", TypeAttributes.Public);
// エントリーポイントのメソッドを定義
MethodBuilder tMainMethod = tDynamicClass.DefineMethod("Main", MethodAttributes.Private | MethodAttributes.Static, null, new Type[] { typeof(string[]) });
// ILコードを書く
ILGenerator tILGenerator = tMainMethod.GetILGenerator();
{ // メソッド本体
// 文字列"Hello World"をスタックに乗せる
tILGenerator.Emit(OpCodes.Ldstr, "Hello World");
// Console.Writelineを呼び出す。
tILGenerator.EmitCall(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }), new Type[] { typeof(string) });
// Console.ReadLineを呼び出す。
tILGenerator.EmitCall(OpCodes.Call, typeof(Console).GetMethod("ReadLine"), null);
// スタックからReadLineで読み込んだ値を削除
tILGenerator.Emit(OpCodes.Pop);
// メソッド終了
tILGenerator.Emit(OpCodes.Ret);
}
// これまでの情報から型を生成
tDynamicClass.CreateType();
// アセンブリのエントリーポイントを設定
tAssembly.SetEntryPoint(tMainMethod);
// ファイルに書き出す。
tAssembly.Save("testAssembly.exe", PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
}
}
}
このコードを実行してできた”testAssembly.exeをReflectorを使って逆アセンブルすると、以下のようなコードが見れます。
private static void Main(string[])
{
Console.WriteLine("Hello World");
Console.ReadLine();
}
1件のコメント
来栖川ブログ » 計算機を作ってみる(さいご) · 2009-03-09 22:50
[…] 前回動的に実行ファイルを作るサンプルを書いたので、ついでに、前に作った計算機を、実行ファイルを吐き出すように改造してみた。 Visual Studio2005のプロジェクト -> calc_compiler.zip ISyntacticNodeのEvalをILGeneratorが渡ってくるように書き換え。 PLAIN TEXT C#: […]
現在コメントは受け付けていません。