繁体   English   中英

在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类,但它们都有自己的主要问题。

这里有三个核心问题:

  1. Codedom似乎忽略了它自己的TempFiles属性,因此在Azure中,它们始终被写入不可访问的inetsrv目录。
  2. Codedom的“ GenerateInMemory”要么不起作用,要么其名称完全具有误导性。
  3. 我需要使用提升的权限来启动WebRole(对此权限不是100%肯定,但尚未删除代码)

解决方案是:

  1. 在Azure实例上创建一些本地存储空间。
  2. 将DLL写入本地存储。
  3. 捕获与删除.TMP文件相关的所有错误,并忽略它们。 我发现这些错误意味着CompiledAssembly中没有数据,但是DLL仍被写到本地存储中。
  4. 不用理会GenerateInMemory
  5. 提升权限

希望这可以节省别人的麻烦!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM