PowerShellからcsc.exe(C#コンパイラ)を使う

PowerShellは便利ですが、起動時のオーバーヘッドがそれなりにあります。
消費リソースの節約や、配布など諸々の事情で、スクリプトでなくexeファイルを生成したい状況もあるでしょう。
PowerShell自体は.NETベースですので、PowerShellで書いたスクリプトをC#等に移植するのは容易なケースが多いですし、C#で書くつもりのプログラムのプロトタイプをPowerShellで書いてみたりるシーンもあるのではないでしょうか。

.NETのコンパイラは.NET Frameworkに付属しています。フォルダの奥深くにあるので引っ張り出すのが面倒ですが、大まかな位置を把握しておけば検索にさほど手間が掛からず、エイリアスを定義すればまあ即興で使えるレベルです。
Visual Studio等インストールされていないWindows環境で、exeファイルを生成したいような状況がいつかあるかもしれません。
あるいは、PowerShellから動的にexeファイルを作成するような知識が、役に立つ時がいつかあるかもしれませんし。

#.NET Framework付属のC#コンパイラを探す
コンパイラの実行ファイル名はcsc.exeで、だいたい以下のようなフォルダにあります。

* C:\windows\Microsoft.NET\Framework\v2.0.50727\csc.exe
* C:\windows\Microsoft.NET\Framework\v3.5\csc.exe
* C:\windows\Microsoft.NET\Framework\v4.0.30319\csc.exe
* C:\windows\Microsoft.NET\Framework64\v2.0.50727\csc.exe
* C:\windows\Microsoft.NET\Framework64\v3.5\csc.exe
* C:\windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe

Framework64は64bit版で、これが存在するのは 64bit版のWindowsのみです。
.NET Frameworkのインストールバージョンにより、各ファイルの存在状況は変わります。

とりあえず  windows\Microsoft.NET までのパスは何とか記憶しておき、大雑把に検索したい場合はPowerShellコンソールから

```ps1:(PowerShell)csc.exeを探す
ls $Env:windir\Microsoft.NET csc.exe -Recurse|select FullName
```
とやれば、時間は掛かりますが見つかります。
バージョンで対象を絞りたい場合は おしりに`|?{$_ -like '*64*4.0*'}` でもつけるか…最初からフルパスで探すべきですかね。

ともあれ、csc.exeが見つかったとします。

# csc.exeにエイリアスを付ける
csc.exeを簡単に呼び出せるように、即興でエイリアスを付けcscとします。
パスを通す手もありますが、今回はより副作用の少ない方法としてエイリアスで対応します。

```ps1:(PowerShell)csc.exeにcscの名前でエイリアスを付ける
sal csc C:\windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe
```
(sal = Set-Alias です)
csc.exeのフルパス部分には、先ほどの検索で見付かったものを指定します。

これを実行し、続いてcscとコマンドを打ち、

```text:PowerShellコンソール
PS C:\work> csc
Microsoft (R) Visual C# Compiler Version 4.0.30319.33440
for Microsoft (R) .NET Framework 4.5
Copyright (C) Microsoft Corporation. All rights reserved.

warning CS2008: ソース ファイルが指定されていません。
error CS1562: ソースのない出力には、/out オプションを指定しなければなりません。
```
csc.exeの実行結果らしい反応があれば結構です。

# csファイルをコンパイルする
C#のソースファイルを用意しておきます。

```cs:Test.cs1
public class Test
{
	public static void Main()
	{
		System.Console.WriteLine("コンパイルのテスト");
	}
}
```

コンソールからコンパイルのコマンドを打ちます。

```text:PowerShellコンソール
PS C:\work> csc .\Test.cs1
Microsoft (R) Visual C# Compiler Version 4.0.30319.33440
for Microsoft (R) .NET Framework 4.5
Copyright (C) Microsoft Corporation. All rights reserved.
```

生成されたファイルを確認します。

```text:PowerShellコンソール
PS C:\work> ls


    ディレクトリ: C:\work


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2015/06/10     13:17        125 Test.cs1
-a---        2015/06/10     13:17       3584 Test.exe
```

Test.exeが作成されていたので、実行してみます。

```text:PowerShellコンソール
PS C:\work> .\Test.exe
コンパイルのテスト
```

こんなところですね。

# その他
`csc /?`でcsc.exeのヘルプを確認できますが、ogv(Out-GridView)を併用すると読み易いかもしれません。

```text:PowerShellコンソール
PS C:\work> csc /?|ogv
```
実行すると、cscの出力が別ウィンドウで表示されます。

# 余談 JScript.NETのコンパイル
JScript.NETというマニアックな言語のコンパイラがまだ提供されているようです。

```text:PowerShellコンソール
PS C:\> ls $Env:windir\Microsoft.NET jsc.exe -Recurse|select FullName

FullName
--------
C:\Windows\Microsoft.NET\Framework\v2.0.50727\jsc.exe
C:\Windows\Microsoft.NET\Framework\v4.0.30319\jsc.exe
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\jsc.exe
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\jsc.exe
```
これも試してみましょう。
JavaScriptっぽいサンプルは…と考えてよいアイデアが出ず、どうでもいいフォルダツリー表示プログラムに落ち着きました。

```js:Tree.js
import System.IO;

function outputChildren(path, header){
	try {
		var caption = Path.GetFileName(path);
		if( caption.Length == 0 ){
			caption = path;
		}
		var cs = Directory.GetDirectories(path);
		var mark = cs.Length>0? "+ ":"- ";
		print( header+mark+caption );
		
		for( var i=0; i<cs.Length; i++ ){
			outputChildren(cs[i], header+"  ");
		}
	} catch (e){
		print(e);
	}
}

var args = System.Environment.GetCommandLineArgs();
if( args.Length < 2 ){
	print("パラメータにツリー出力するパスを指定してください。");
} else {
	outputChildren(args[1],"");
}
```

csc.exeと同様の流れでコンパイル、exe生成、実行までできます。

```text:PowerShellコンソール
PS C:\work> jsc .\Tree.js
Microsoft(R) JScript Compiler version 12.00.20806
for Microsoft(R) .NET Framework version 4.0.30319
Copyright (C) Microsoft Corporation. All rights reserved.

PS C:\work> .\Tree.exe C:\windows\System32\WindowsPowerShell
+ WindowsPowerShell
  + v1.0
    - en-US
    - Examples
    - ja
    - ja-JP
    + Modules
      + ActiveDirectory
        - en-US
        - ja-JP
      + AppBackgroundTask
        - en-US
(以下略)
```

JavaScriptとは似て非なるものですが、JavaScriptなら分かるという人に何かしてもらうには使えるかもしれません。