在 Azure 上使用 Codedom/CSharpCodeProvider 进行动态编译
Dynamic compilation using Codedom/CSharpCodeProvider on Azure
我正在使用以下代码动态编译一些代码并将生成的 DLL 存储在 Azure 存储中。
当我在本地 运行 时一切正常,但在使用 Azure 部署版本时不起作用。
我现在已经尝试了很多东西。
这是我使用的最新版本。这不会引发任何错误,但不会存储 DLL(存储方法工作正常,因为它在许多其他地方使用)。我假设存在权限问题或 DLL 未存储为文件的事实。
public Tuple<bool,string> compileAndStoreCodeAsDLL(Guid actionID, string actionName, string actionMethod, string code)
{
string newFileName = "AncillaryTestMethods_" + actionName + ".dll";
try
{
// Compile the code
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = false;
parameters.OutputAssembly = newFileName;
parameters.GenerateInMemory = false;
parameters.TempFiles = new TempFileCollection(".", true);
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("System.Core.dll");
parameters.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, code);
MemoryStream stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, results.CompiledAssembly);
// Store the code in the current firm's azure directory/ActionDLLs
this.putFile(stream, newFileName, "ActionDLLs");
// Return ok
return new Tuple<bool, string>(true, null);
}
catch (Exception e)
{
// Return fail
return new Tuple<bool, string>(true, e.Message);
}
}
我从这段代码开始(在本地也有效):
public Tuple<bool,string> compileAndStoreCodeAsDLL(Guid actionID, string actionName, string actionMethod, string code)
{
string newFileName = "AncillaryTestMethods_" + actionName + ".dll";
try
{
// Compile the code
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = false;
parameters.OutputAssembly = newFileName;
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("System.Core.dll");
parameters.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, code);
// Store the code in the current firm's azure directory/ActionDLLs
this.putFile(results.CompiledAssembly.GetFile(newFileName), newFileName, "ActionDLLs");
// Return ok
return new Tuple<bool, string>(true, null);
}
catch (Exception e)
{
// Return fail
return new Tuple<bool, string>(true, e.Message);
}
}
但在 Azure 上抛出错误“生成 Win32 资源时出错:访问被拒绝。无法删除用于默认 Win32 资源的临时文件 'd:windows\system32\inetsrv...tmp' -- 系统找不到指定的文件。
这大概是 Azure 权限相关的,所以我尝试了上面的代码。
任何人都可以建议任何更改以使此功能在 Azure 中运行吗?
经过大约 17 个小时,我终于让它工作了。情况非常糟糕,我什至尝试连接到 FluidSharp 库中的 Roslyn 类,但它们有自己的重大问题。
这里有三个核心问题:
- Codedom 似乎忽略了它自己的 TempFiles 属性,因此在 Azure 中这些总是写入不可访问的 inetsrv 目录。
- Codedom 的 "GenerateInMemory" 要么不起作用,要么它的名字完全具有误导性。
- 我需要以提升的权限启动我的 WebRole(对此不是 100% 确定,但尚未删除代码)
解决方案是:
- 在 Azure 实例上创建一些本地存储 space。
- 将 DLL 写入本地存储。
- 捕获与删除 .TMP 文件相关的任何错误并忽略它们。我发现这些错误意味着 CompiledAssembly 中没有数据,但 DLL 仍然被写入本地存储。
- 不要为 GenerateInMemory 而烦恼
- 提升权限
希望这可以为其他人省去很多麻烦!
我正在使用以下代码动态编译一些代码并将生成的 DLL 存储在 Azure 存储中。
当我在本地 运行 时一切正常,但在使用 Azure 部署版本时不起作用。
我现在已经尝试了很多东西。
这是我使用的最新版本。这不会引发任何错误,但不会存储 DLL(存储方法工作正常,因为它在许多其他地方使用)。我假设存在权限问题或 DLL 未存储为文件的事实。
public Tuple<bool,string> compileAndStoreCodeAsDLL(Guid actionID, string actionName, string actionMethod, string code)
{
string newFileName = "AncillaryTestMethods_" + actionName + ".dll";
try
{
// Compile the code
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = false;
parameters.OutputAssembly = newFileName;
parameters.GenerateInMemory = false;
parameters.TempFiles = new TempFileCollection(".", true);
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("System.Core.dll");
parameters.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, code);
MemoryStream stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, results.CompiledAssembly);
// Store the code in the current firm's azure directory/ActionDLLs
this.putFile(stream, newFileName, "ActionDLLs");
// Return ok
return new Tuple<bool, string>(true, null);
}
catch (Exception e)
{
// Return fail
return new Tuple<bool, string>(true, e.Message);
}
}
我从这段代码开始(在本地也有效):
public Tuple<bool,string> compileAndStoreCodeAsDLL(Guid actionID, string actionName, string actionMethod, string code)
{
string newFileName = "AncillaryTestMethods_" + actionName + ".dll";
try
{
// Compile the code
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = false;
parameters.OutputAssembly = newFileName;
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("System.Core.dll");
parameters.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, code);
// Store the code in the current firm's azure directory/ActionDLLs
this.putFile(results.CompiledAssembly.GetFile(newFileName), newFileName, "ActionDLLs");
// Return ok
return new Tuple<bool, string>(true, null);
}
catch (Exception e)
{
// Return fail
return new Tuple<bool, string>(true, e.Message);
}
}
但在 Azure 上抛出错误“生成 Win32 资源时出错:访问被拒绝。无法删除用于默认 Win32 资源的临时文件 'd:windows\system32\inetsrv...tmp' -- 系统找不到指定的文件。
这大概是 Azure 权限相关的,所以我尝试了上面的代码。
任何人都可以建议任何更改以使此功能在 Azure 中运行吗?
经过大约 17 个小时,我终于让它工作了。情况非常糟糕,我什至尝试连接到 FluidSharp 库中的 Roslyn 类,但它们有自己的重大问题。
这里有三个核心问题:
- Codedom 似乎忽略了它自己的 TempFiles 属性,因此在 Azure 中这些总是写入不可访问的 inetsrv 目录。
- Codedom 的 "GenerateInMemory" 要么不起作用,要么它的名字完全具有误导性。
- 我需要以提升的权限启动我的 WebRole(对此不是 100% 确定,但尚未删除代码)
解决方案是:
- 在 Azure 实例上创建一些本地存储 space。
- 将 DLL 写入本地存储。
- 捕获与删除 .TMP 文件相关的任何错误并忽略它们。我发现这些错误意味着 CompiledAssembly 中没有数据,但 DLL 仍然被写入本地存储。
- 不要为 GenerateInMemory 而烦恼
- 提升权限
希望这可以为其他人省去很多麻烦!