CodeDomProvider objCodeCompiler = CodeDomProvider.CreateProvider( "CSharp" );
CompilerParameters objCompilerParameters = new CompilerParameters();
...
CompilerResults objCompileResults = objCodeCompiler.CompileAssemblyFromFile( objCompilerParameters, files.ToArray() );
ファイルをコンパイルすると、次のようになります。
FileFunctions.cs(347):エラー:予期しない文字 '$'
誰かがCodeDomコンパイルで文字列補間を機能させる方法を知っていますか?
私はこのリンクを見つけました: CSharpCodeProviderで.net 4.5をターゲットにする方法?
だから私は試しました:
var providerOptions = new Dictionary<string, string>();
providerOptions.Add( "CompilerVersion", "v4.0" );
// Instantiate the compiler.
CodeDomProvider objCodeCompiler = CodeDomProvider.CreateProvider( "CSharp", providerOptions );
しかし、まだ同じエラーが発生します。
ターゲットフレームワークも.NET Framework 4.6に更新しました。
注:「v4.5」または「v4.6」を指定できない場合、次のようになります。
************** Exception Text **************
System.InvalidOperationException: Compiler executable file csc.exe cannot be found.
at System.CodeDom.Compiler.RedistVersionInfo.GetCompilerPath(IDictionary`2 provOptions, String compilerExecutable)
at Microsoft.CSharp.CSharpCodeGenerator.FromFileBatch(CompilerParameters options, String[] fileNames)
at Microsoft.CSharp.CSharpCodeGenerator.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromFileBatch(CompilerParameters options, String[] fileNames)
at System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromFile(CompilerParameters options, String[] fileNames)
at Dynamic.CodeDOMCompiler.CompileAllCodeFiles() in C:\Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\Core\CodeDOMCompiler.cs:line 93
at NewForm.InitializeSystem() in C:\Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\NewForm.cs:line 179
at NewForm.NewForm_Load(Object sender, EventArgs e) in C:\Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\NewForm.cs:line 111
at System.Windows.Forms.Form.OnLoad(EventArgs e)
Thomas Levesqueの提案を使用してみました。
CodeDomProvider objCodeCompiler = new Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider();
しかし、私は得る:
************** Exception Text **************
System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\bin\x86\Debug\bin\roslyn\csc.exe'.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
at Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Compiler.get_CompilerName()
at Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Compiler.FromFileBatch(CompilerParameters options, String[] fileNames)
at Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Compiler.CompileAssemblyFromFileBatch(CompilerParameters options, String[] fileNames)
at System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromFile(CompilerParameters options, String[] fileNames)
at Dynamic.CodeDOMCompiler.CompileAllCodeFiles() in C:\Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\Core\CodeDOMCompiler.cs:line 87
at NewForm.InitializeSystem() in C:\Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\NewForm.cs:line 179
at NewForm.NewForm_Load(Object sender, EventArgs e) in C:\Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\NewForm.cs:line 111
at System.Windows.Forms.Form.OnLoad(EventArgs e)
Binディレクトリのサブフォルダーで「csc.exe」を検索しようとしている理由がわかりません。
このパスは存在します:
C:\ Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\ bin\x86\Debug\roslyn
しかし、それは探していました:
C:\ Users\Derek.Morin\Documents\Visual Studio 2010\Projects\ScriptCode\ScriptCode.ConvertedToC#\ bin\x86\Debug\bin\roslyn\csc.exe
組み込みのCodeDOMプロバイダーはC#6をサポートしていません。代わりにこれを使用してください:
https://www.nuget.org/packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/
Roslynをベースにしており、C#6の機能をサポートしています。
この行を変更するだけです:
CodeDomProvider objCodeCompiler = CodeDomProvider.CreateProvider( "CSharp" );
これに:
CodeDomProvider objCodeCompiler = new Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider();
更新:2018年3月
注意:NuGetバージョン1.0.6 ... 1.0.8は、非Webプロジェクトのビルド出力ディレクトリに/ roslynフォルダーをコピーしません。 1.0.5のベストスティック https://github.com/aspnet/RoslynCodeDomProvider/issues/38
@ thomas-levesqueが述べたように、C#6機能を使用したランタイムコンパイルには新しいコンパイラが必要です。このコンパイラは、nugetパッケージ Microsoft.CodeDom.Providers.DotNetCompilerPlatform
を使用してインストールできます。
デスクトップアプリケーションの場合、問題があります。 ASP.NETチームは、その無限の知恵により、コンパイラへのパスを<runtime-directory>\bin\roslyn\csc.exe
としてハードコーディングしました https://github.com/dotnet/roslyn/issues/948 のディスカッションを参照してください
デスクトップアプリケーションが\myapp\app.exe
にコンパイルされている場合、roslynコンパイラは\myapp\roslyn\csc.exe
、にありますが、CSharpCodeProvider
はcsc.exe
を解決します\myapp\bin\roslyn\csc.exe
として
私の知る限り、2つの選択肢があります
\roslyn
サブディレクトリを\bin\roslyn
に移動するビルド後および/またはインストールルーチンを作成します。これは、ユーティリティクラスのプロパティとしてCSharpCodeProvider
を公開することによる#2です。
using System.Reflection;
using Microsoft.CodeDom.Providers.DotNetCompilerPlatform;
static Lazy<CSharpCodeProvider> CodeProvider { get; } = new Lazy<CSharpCodeProvider>(() => {
var csc = new CSharpCodeProvider();
var settings = csc
.GetType()
.GetField("_compilerSettings", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(csc);
var path = settings
.GetType()
.GetField("_compilerFullPath", BindingFlags.Instance | BindingFlags.NonPublic);
path.SetValue(settings, ((string)path.GetValue(settings)).Replace(@"bin\roslyn\", @"roslyn\"));
return csc;
});
最近この問題に遭遇しました。コンテキストとして、System.CodeDom
を使用してライブラリプロジェクトに対してMSTestプロジェクトを実行しようとしましたが、Microsoft.Net.Compilers
またはMicrosoft.CodeDom.Providers.DotNetCompilerPlatform
パッケージが参照されているかどうかに関係なく、C#5を実装するコンパイラが常に提供されましたテスト中のプロジェクトによって。
これに対する私の修正は:
Microsoft.CodeDom.Providers.DotNetCompilerPlatform
を使用PrivateAssets
をcontentfiles;analyzers
に設定しますCompilerDirectoryPath
をコピーしたディレクトリに設定PrivateAssets
の- デフォルト値 はcontentfiles;analyzers;build
であるため、参照プロジェクトでフォルダーもコピーするには、build
を設定から削除する必要があります。
コード例:
var compiler = CodeDomProvider.CreateProvider("cs", new Dictionary<string, string> {
{ "CompilerDirectoryPath", Path.Combine(Environment.CurrentDirectory, "roslyn") }
});
これをMicrosoft.Net.Compilers
で機能させると、コピーが作成されないので少し面倒になりますが、パッケージのtoolsフォルダーでCompilerDirectoryPath
をポイントする最後の手順は同じです。
更新された情報:FW 4.8をリリースした後でも、C#8.0のすべての新機能を使用できません-ディストリビューションにはバージョン5.0に限定されたCSCが含まれています。しかし、VS2019で配布されているCSCを使用するハックがあります(そう、インストールする必要があります)。
var csprovider = new CSharpCodeProvider(new Dictionary<string,string> {
["CompilerDirectoryPath"] = @"c:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Roslyn",
});
options += " -langversion:8.0 ";
var par = new CompilerParameters { GenerateInMemory = true, CompilerOptions = options };
par.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
par.ReferencedAssemblies.Add("System.Core.dll");
var res = csprovider.CompileAssemblyFromSource(par, "your C# code");
return res.CompiledAssembly;// <- compiled result
ところで、明示的なオプション「GenerateInMemory」にもかかわらず、コードはとにかくファイルに書き込まれ、それからコンパイルされます。アプリケーションをディスクアクセスなしで実行する場合は注意してください。
完全に壊れたコンパイラの同じ問題に直面し、ハードコードされたパス{ProgramLocation}\bin\roslyn
を設定する前に、私が見つけたライブラリの逆コンパイルされたソースを見て、 Aaronの答え にリストされているものに加えて3番目の解決策を見つけましたその場所の環境変数(これもハードコーディングされている)を検索し、設定されている場合は代わりにそれを使用します。
このことを念頭に置いて、次のようなコードも問題を「修正」します。
//Set hardcoded environment variable to set the path to the library
Environment.SetEnvironmentVariable("ROSLYN_COMPILER_LOCATION", "actual compiler location goes here", EnvironmentVariableTarget.Process);
//Create compiler object
CSharpCodeProvider compiler = new CSharpCodeProvider();
//Clean up
Environment.SetEnvironmentVariable("ROSLYN_COMPILER_LOCATION", null, EnvironmentVariableTarget.Process);
//Use "compiler" variable to actually compile the dynamic code
これは内部の混乱にリフレクションを使用するわけではありませんが、実装の詳細に依存しており、このような環境変数の悪用は間違っていると感じています。私は個人的にリフレクションの選択肢よりもこれを気に入っていますが、同時に両方とも正確な実装(およびハードコードされたパス)に依存していることも知っています。
この問題と、インプロセスで実行する必要があることを実行するために外部プログラムを呼び出す必要があるため、このライブラリは完全に壊れていると考えています。