Visual Studioではなく、Windows付属のcsc.exe だけでC#実行ファイルを作る

PC遠隔操作事件で弁護士さんが容疑者にはC#を作成する環境（Visual Studio 2010）がなかったと主張( http://goo.gl/wJyOc ) をされています。

この事件の事実や行方、あるいは今の容疑者は真犯人なのかといった事柄とは別に、C#のそこの部分を自分の手で確認してみたくなったので、極簡単なコンパイルのテストをしてみました。

「まぁ、C#の世界はよくわからないけど、念のために今Framework\v4.0.30319のcsc.exeでコンパイルしてみたら、hello.exe の中にそのGeneratorバージョンを埋め込めたので、できることはできるのかなと思う。」http://goo.gl/wqlWg

ということで、Visual Studio 2010なしでC#の実行ファイル作成をテストしてみたメモです。(参考：Windows にデフォルトでインストールされている .NET Framework のバージョン http://goo.gl/ZkpOu)

環境は、Visual Studioではなく、Windows Vistaや7や8には最初から入っているC#コンパイラ csc.exe と テキストエディタ（これも最初から入ってるメモ帳でOK）です。

下記で試しているFrameworkはv2.0.50727です。

P.S. もちろん、これができたからといっても、当の遠隔操作ウィルスでも同じことができるかどうかは、そのウィルスを見たこともないのでわかりません。

P.S.2 こうして試してみるとC#って意外に手軽で楽しそうです^^。

##ソースコード

まず、C#のコードを書きます。なんでも良いのですが、たとえばこんな感じ。

```csharp:hello.cs
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Reflection;
using System.Windows.Forms;
using System.Drawing;

class HelloNeko : Form {

  [STAThread]
  public static void Main() {
    GeneratedCodeAttribute generatedCodeAttribute =
        new GeneratedCodeAttribute(
           "Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0"
        );
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run( new HelloNeko());
  }

  HelloNeko(){
    Text = "Button Click Sample";
    ClientSize = new Size(200, 200);
    Button btn1 = new Button();
    btn1.Location = new Point(50, 50);
    btn1.Text = "Click!";
    btn1.Click += btn1_Click;
    Controls.AddRange(new Control[] { btn1 });
  }

  void btn1_Click(object sender, System.EventArgs e) {
    MessageBox.Show("Hello .NEKO World", "こんちわ");
  }
}
```

ちなみに「"Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0"」の部分はexeファイルに埋め込まれるので Visual Studio で作ったっぽく見えます。

##コマンドプロンプトを起動する

上記コードをたとえば hello.cs といった名前にしてC:\testというフォルダへ置きます。

次に、そのフォルダのアドレスバーへ「cmd」と打ち込みエンターすると、そのフォルダのパスでコマンドプロンプトが開きます。

次に、csc.exeを探します。普通は「C:\Windows\Microsoft.NET\Framework」の下にFrameworkのバージョン毎にフォルダが作成されています。

とりあえずここでは、v2.0.50727の下にあるcsc.exeを使うことにします。

つまり、C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe を使います。

そのcsc.exeをコマンドプロンプトへドラッグドロップするとこうなります。

![コマンドプロンプト](http://socketapi.com/jsbu/memo/cs/2.png)

次に、このC:\test>C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exeの後ろへ半角スペースを打ち込んでから、今度は、最初に作ったhello.csをドラッグドロップします。

そうすると、こうなります。

![コマンドプロンプト](http://socketapi.com/jsbu/memo/cs/2.5.png)

##さぁ、コンパイル！

改行します。

これだけです。

##実行しましょう。

コンパイルするとC:\testホルダに hello.exe というファイルができています。

これをクリックするとこうなります。

![実行](http://socketapi.com/jsbu/memo/cs/3.png)

ダイアログが表れて、ボタンをクリックすると「Hello .NEKO World」と表示されます。

ちなみに、csc.exeのオプションは下記の通り。たとえば、/t:winexe をつけてコンパイルすれば、コマンドプロンプトが表示されない通常のアプリケーションになります。

## Visual C# コンパイラのオプション

```
                        Visual C# Compiler のオプション

                        - 出力ファイル -
/out:<ファイル>                出力ファイル名を指定します (既定: メイン
                               クラスかファースト
                               ファイルを伴うファイルのベース名)。
/target:exe                    コンソール アプリケーションをビルドします
                               (既定)。 (短い形式: /t:exe)
/target:winexe                 Windows 実行可能ファイルをビルドします。
                               (短い形式: /t:winexe)
/target:library                ライブラリをビルドします。 (短い形式: /t:library)
/target:module                 別のアセンブリに追加できるモジュールをビルドしま
                               す。 (短い形式: /t:module)
/target:appcontainerexe        Appcontainer 実行可能ファイルのビルド (短い形式:
                               /t:appcontainerexe)
/target:winmdobj               WinMDExp で使用される Windows
                               ランタイムの中間ファイルのビルド (短い形式:
                               /t:winmdobj)
/doc:<ファイル>                生成する XML ドキュメント ファイル
/platform:<文字列>             このコードが実行されるプラットフォームの制限:
                               x86、Itanium、x64、arm、anycpu32bitpreferred、ま
                               たは anycpu。既定は anycpu です。

                        - 入力ファイル -
/recurse:<ワイルドカード>      ワイルドカードの指定に従い、現在のディレクトリと
                               サブディレクトリ内のすべてのファイルをインクルー
                               ドします。
/reference:<エイリアス>=<ファイル>
                               指定されたエイリアスを使用して、指定されたアセン
                               ブリ ファイルからメタベースを参照する (短い形式:
                               /r)
/reference:<ファイル リスト>   指定されたアセンブリ
                               ファイルからメタベースを参照する (短い形式: /r)
/addmodule:<ファイル リスト>   指定されたモジュールをこのアセンブリにリンクする
/link:<ファイル リスト>        指定された相互運用機能アセンブリ
                               ファイルからメタデータを埋め込みます (短い形式:
                               /l)

                        - リソース -
/win32res:<ファイル>           Win32 リソース ファイルを指定します (.res)。
/win32icon:<ファイル>          出力にこのアイコンを使用します。
/win32manifest:<ファイル>      Win32 マニフェスト ファイル (.xml)
                               を指定してください。
/nowin32manifest               既定の Win32 マニフェストを含めません。
/resource:<リソース情報>       指定したリソースを埋め込みます。 (短い形式: /res)
/linkresource:<リソース情報>   このアセンブリに指定されたリソースをリンクします
                               。 (短い形式: /linkres)
                               リソース情報の形式は <ファイル>[,<文字列名>
                                                             [,public|private]]
                               です。

                        - コード生成 -
/debug[+|-]                    デバッグ情報を生成する
/debug:{full|pdbonly}          デバッグの種類を指定します (既定値は full
                               で、実行中のプログラムにデバッガーを付加すること
                               ができます)。
/optimize[+|-]                 最適化を有効にする (短い形式: /o)

                        - エラーと警告 -
/warnaserror[+|-]              すべての警告をエラーとして報告する
/warnaserror[+|-]:<警告リスト> 指定した警告をエラーとして報告する
/warn:<n>                      警告レベル (0-4) を設定する (短い形式: /w)
/nowarn:<警告リスト>           指定の警告メッセージを無効にする

                        - 言語 -
/checked[+|-]                  オーバーフロー チェックの生成
/unsafe[+|-]                   アンセーフ コードの許可
/define:<シンボル リスト>      条件付きコンパイル シンボルを定義する (短い形式:
                               /d)
/langversion:<文字列>          言語バージョン モードの指定:
                               ISO-1、ISO-2、3、4、5、または Default

                        - セキュリティ -
/delaysign[+|-]                厳密な名前のキーのパブリックな部分のみを使ってア
                               センブリを遅延署名します。
/keyfile:<ファイル>            厳密な名前のキー ファイルを指定します。
/keycontainer:<文字列>         厳密な名前のキー コンテナーを指定します。
/highentropyva[+|-]            高エントロピ ASLR の有効化

                        - その他 -
@<ファイル>                    応答ファイルを読み取り、オプションを追加します。
/help                          この使用法のメッセージを表示します。 (短い形式:
                               /?)
/nologo                        コンパイル時の著作権メッセージを表示しません。
/noconfig                      CSC.RSP ファイルを自動的に含めません。

                        - 詳細 -
/baseaddress:<アドレス>        ビルドするライブラリのベース アドレスです。
/bugreport:<ファイル>          'バグ報告' ファイルを作成します
/codepage:<n>                  ソース
                               ファイルを開くときに使用するコードページを指定し
                               ます。
/utf8output                    UTF-8
                               エンコードでコンパイラのメッセージを出力する
/main:<型>                     エントリ ポイントを含む型を指定します
                               (他のエントリ ポイントはすべて無視します)。
                               (短い形式: /m)
/fullpaths                     コンパイラは絶対パスを生成します。
/filealign:<n>                 出力ファイル
                               セクションで使用する配置を指定します。
/pdb:<ファイル>                デバッグ情報ファイル名を指定します (既定: .pdb
                               拡張子の付いた出力ファイル名)
/errorendlocation              各エラーの終了位置の出力行と出力列
/preferreduilang               出力用の言語名を指定します。
/nostdlib[+|-]                 標準ライブラリ (mscorlib.dll) を参照しない
/subsystemversion:<文字列>     このアセンブリのサブシステム
                               バージョンを指定してください
/lib:<ファイル リスト>         参照を検索する追加のディレクトリを指定します。
/errorreport:<文字列>          内部コンパイラ エラーの処理方法を指定します:
                               prompt、send、queue、または none です。既定値は
                               queue です。
/appconfig:<ファイル>          アセンブリ
                               バインディング設定を含むアプリケーション構成ファ
                               イルを指定してください
/moduleassemblyname:<文字列>   このモジュールが一部となるアセンブリ名です
```

##.NET Frameworkライブラリ

http://msdn.microsoft.com/ja-jp/library/aa139615.aspx

##メモ

・ソース中の[STAThread]について
　アパートメントモデルと、.NETのSTAThreadAttribute
　http://d.hatena.ne.jp/zecl/20070708/p1