C# プロジェクトを、インストーラーではなく実際のプログラムである単一の EXE ファイルとして配布する必要があるという問題が発生しました。また、現在サブディレクトリにある翻訳も含める必要があります。
バイナリに直接埋め込むことは可能ですか?
C# プロジェクトを、インストーラーではなく実際のプログラムである単一の EXE ファイルとして配布する必要があるという問題が発生しました。また、現在サブディレクトリにある翻訳も含める必要があります。
バイナリに直接埋め込むことは可能ですか?
短い答えはイエスです。この方法でアセンブリを埋め込むAssembly Linker (AL.exe)と呼ばれるプログラムがあります。その主なユースケースはローカリゼーションですが、それも必要なようです。もしそうなら、それは簡単なはずです。
例えば:
al /t:lib /embed:strings.de.resources /culture:de /out:MyApp.resources.dll
また
al.exe /culture:en-US /out:bin\Debug\en-US\HelloWorld.resources.dll /embed:Resources\MyResources.en-US.resources,HelloWorld.Resources.MyResources.en-US.resources /テンプレート:bin\Debug\HelloWorld.exe
これは、上記の例などを含む MSDN のウォークスルーの例です。また、このブログ投稿を読んで、その使用法をもう少し詳しく説明することもできます。
これは、インターネットで見た最も簡単な解決策です。
このソリューションの便利な実装も: http://code.google.com/p/costura/wiki/HowItWorksEmbedTask
もう 1 つのオプションは、他のアセンブリを EmbededResource として埋め込むことです。次に、アプリ ドメイン AssemblyResolve を処理します。ここから、リソースからアセンブリを読み取り、ランタイムに読み込むことができます。次のようなもの:
public class HookResolver
{
Dictionary<string, Assembly> _loaded;
public HookResolver()
{
_loaded = new Dictionary<string, Assembly>(StringComparer.OrdinalIgnoreCase);
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}
System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
string name = args.Name.Split(',')[0];
Assembly asm;
lock (_loaded)
{
if (!_loaded.TryGetValue(name, out asm))
{
using (Stream io = this.GetType().Assembly.GetManifestResourceStream(name))
{
byte[] bytes = new BinaryReader(io).ReadBytes((int)io.Length);
asm = Assembly.Load(bytes);
_loaded.Add(name, asm);
}
}
}
return asm;
}
}
ILMergeは、アプリケーション用に単一の exe ファイルを作成します。マイクロソフトからダウンロードできます。アセンブリを一緒にマージし、それらを内部化して、マージされたクラスが internal に設定されるようにします。これは、私が何度も単一ファイルのリリースを作成するために使用したものです。ビルド プロセスに統合するのは非常に簡単です。