ソースを実行ファイルに埋め込む方法

”ソース == 実行プログラム”　な言語に慣れてしまうと、
この実行プログラムのソースはどうなってるんだ・・と一々データサーバー
まで見に行かないといけないのはちょっとやってられないわけで。

いっその事、ソースも埋め込んでしまえばいいんじゃねというのをやってみた。

## 用意するもの
* .NETフレームワークの入ったWindows（今どきはデフォルトでC#コンパイラ入ってるんですね！すごい！）

```bat
C:\tmp>dir
2014/04/16  21:16               259 README.txt
2014/04/16  21:04               822 resource_test.cs
```

```csharp:resource_test.cs
/*
 *  how to execute
 *  C:\tmp>path=%path%;C:\Windows\Microsoft.NET\Framework64\v4.0.30319
 *  C:\tmp>csc resource_test.cs /resource:resource_test.cs /resource:README.txt
 *  C:\tmp>resource_test.exe
 */
namespace Main
{
  using System;
  using System.IO;
  using System.Reflection;

  class MainClass
  {
    static void Main()
    {
      Assembly asm = Assembly.GetExecutingAssembly();
      foreach(string infile in asm.GetManifestResourceNames()) {
		string otfile = "w_" + infile;
        Console.WriteLine("infile : " + infile);
        Console.WriteLine("otfile : " + otfile);

        // 書き出し準備
        FileStream fs = new FileStream(otfile, FileMode.Create);
        BinaryWriter br = new BinaryWriter(fs);

        // 書き出し
        Stream sr = asm.GetManifestResourceStream(infile);
        byte[] bt = new byte[sr.Length];
        sr.Read(bt, 0, bt.Length);
        br.Write(bt);
      }
    }
  }
}
```

```text:README.txt
・複数個のファイルは/resourceを連続すれば良い。
・もっと数が多いならzip圧縮するバッチを作成して、
　そのzipファイルをコンパイル時に埋め込めば良い。
・リソースエディタとかにかけると埋め込まれているファイルなんて
　丸見えなので暗号化かけるとかはよしなに。
```

## 実行&結果
ぶじ、かきだせました。

```bat
C:\tmp>csc resource_test.cs /resource:resource_test.cs /resource:README.txt

C:\tmp>resource_test.exe
infile : resource_test.cs
otfile : w_resource_test.cs
infile : README.txt
otfile : w_README.txt

C:\tmp>dir
2014/04/16  21:16               259 README.txt
2014/04/16  21:31               968 resource_test.cs
2014/04/16  21:31             5,632 resource_test.exe
2014/04/16  21:31               259 w_README.txt
2014/04/16  21:31               968 w_resource_test.cs
```

# 関数化

* ちゃんとしたモジュール化とかは勉強してないので・・・

```csharp
/*
 *  how to compile and execute
 *  C:\tmp>path=%path%;C:\Windows\Microsoft.NET\Framework64\v4.0.30319
 *  C:\tmp>csc extract.cs /resource:extract.cs /resource:README.txt
 *  C:\tmp>extract.exe
 */
using System;
using System.IO;
using System.Reflection;

class MainClass
{
  static int Main(string[] args) 
  {
    if (args.Length == 0) {
      Console.WriteLine("引数がありません");
      return 0;
    }

    if (args[0] == "/e") {
      Console.WriteLine("ソース展開");
      extractResource();
      return 0;
    }

    Console.WriteLine("何もしません");
    return 0;
  }

  static void extractResource()
  {
      Assembly asm = Assembly.GetExecutingAssembly();
      foreach(string infile in asm.GetManifestResourceNames()) {
        string otfile = "w_" + infile;
        Console.WriteLine("infile : " + infile);
        Console.WriteLine("otfile : " + otfile);

        // 書き出し準備
        FileStream fs = new FileStream(otfile, FileMode.Create);
        BinaryWriter br = new BinaryWriter(fs);

        // 書き出し
        Stream sr = asm.GetManifestResourceStream(infile);
        byte[] bt = new byte[sr.Length];
        sr.Read(bt, 0, bt.Length);
        br.Write(bt);
     }
  }
}
```

# 参考
* [埋め込まれたリソースを読み出してファイルに書く](http://bbs.wankuma.com/index.cgi?mode=al2&namber=8903&KLOG=21)