PowershellでC#等をコンパイルする
.Netにはもれなくコンパイラーが含まれている。
このため、VisualStudio等を導入しなくても、C#等のビルドが可能である。
しかし、ググッても一ページ目に出なかったので、メモ書きする。
追記 20140116
Powershell v2.0以降なら、Add-Typeでビルドすべきと気づいたので修正。
こんな簡単じゃあ、、、ぐぐっても出ないよねぇ。
Add-Typeでビルド
$sourceにソース、$outpathが出力先として、
C# DLLなら、OutputAssemblyを指定するだけ。
Add-Type $source -OutputAssembly $outpath
ビルドと同時にロードもしたいなら、-PassThruを指定してやって。
VisualBasic/JScriptなら、Languageを指定する。
それ以外は、下とあんまり変わらないので割愛(CodeDomProviderを指定する必要がある)
C# EXEなら、OutputTypeを追加。
コンソールアプリケーションなら
Add-Type $source -OutputAssembly $outpath -OutputType ConsoleApplication
コンソールいらないなら
Add-Type $source -OutputAssembly $outpath -OutputType WindowsApplication
メインクラスを指定する必要がある場合は、CompilerParametersを指定してやる必要がある気がします。
その場合、OutputTypeは指定しなくて良いと思われる(CompilerParametersに含まれるため)
CompilerParametersの作り方は、下を参照してくださいな。
DLLのビルド
$sourceにソース、$outpathが出力先(DLL名)
$provider = [System.CodeDom.Compiler.CodeDomProvider]::CreateProvider("CSharp") $parameters = New-Object System.CodeDom.Compiler.CompilerParameters $parameters.OutputAssembly = $outpath $provider.CompileAssemblyFromSource($parameters, $source)
EXEのビルド
$sourceにソース、$outpathが出力先(EXE名)、$mainがMainのクラス
$provider = [System.CodeDom.Compiler.CodeDomProvider]::CreateProvider("CSharp") $parameters = New-Object System.CodeDom.Compiler.CompilerParameters $parameters.GenerateExecutable = $true $parameters.OutputAssembly = $outpath $parameters.MainClass = $main $provider.CompileAssemblyFromSource($parameters, $source)
Hello, world!
$source = @" public class Hello { public static void Main(string[] args) { System.Console.WriteLine("Hello, world!"); } } "@ $outpath = '.\hello.exe' $main = "Hello" $provider = [System.CodeDom.Compiler.CodeDomProvider]::CreateProvider("CSharp") $parameters = New-Object System.CodeDom.Compiler.CompilerParameters $parameters.GenerateExecutable = $true $parameters.OutputAssembly = $outpath $parameters.MainClass = $main $provider.CompileAssemblyFromSource($parameters, $source) &$outpath
使える言語は?
プロバイダーを「CSharp」で作成してますから、C#。
同じノリでVBとかもいけますよ!
一覧は以下をどうぞ。別名も確認できますよ。
[System.CodeDom.Compiler.CodeDomProvider]::GetAllCompilerInfo() | ForEach-Object {$_.GetLanguages()}
なお、言語名に大文字・小文字の区別はありません。
$source = @" Imports Microsoft.VisualBasic Public Class Hello Public Shared Function Main(ByVal args() As String) As Integer return MsgBox("Hello, world!") End Function End Class "@ $outpath = '.\hello.exe' $main = "Hello" $provider = [System.CodeDom.Compiler.CodeDomProvider]::CreateProvider("VisualBasic") $parameters = New-Object System.CodeDom.Compiler.CompilerParameters $parameters.GenerateExecutable = $true $parameters.OutputAssembly = $outpath $parameters.MainClass = $main $provider.CompileAssemblyFromSource($parameters, $source) &$outpath
備考
この方法で、クラスをメモリーにコンパイルしてファイル化することなく使うことも可能ですが、それならAdd-Typeを使った方が楽でしょう。
いずれにしてもメモリーコンパイルではクラスを排除する方法はないので、クラスを作り直すことを考慮するなら、AppDomainを別にしてAppDomain毎破棄とか、Powershell内Powershellで「exit」するとかが必要です。
XPが死滅しようとしている今、バイナリーの持ち込みを禁止することは、ほぼ不可能なのです。
ネットワーク管理者は無駄な抵抗はやめるべきです。