2

私のアプリケーションは、ユーザーが C# でスクリプト化できる必要がありますが、ユーザーのスクリプトは、スクリプトが誤って損傷を引き起こすのを防ぐために、制限された AppDomain で実行する必要がありますが、実際には動作させることができません。AppDomains についての私の理解は残念ながら限られているため、私は理由はよくわかりません。

私が現在試している解決策は、この回答https://stackoverflow.com/a/5998886/276070に基づいています。

これは私の状況のモデルです (厳密な名前のアセンブリにある Script.cs を除くすべて)。コードの壁を許してください。問題をこれ以上要約できませんでした。

class Program
{
    static void Main(string[] args)
    {
        // Compile the script
        CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp");
        CompilerParameters parameters = new CompilerParameters()
        {
            GenerateExecutable = false,
            OutputAssembly = System.IO.Path.GetTempFileName() + ".dll",                         
        };
        parameters.ReferencedAssemblies.Add(Assembly.GetEntryAssembly().Location);

        CompilerResults results = codeProvider.CompileAssemblyFromFile(parameters, "Script.cs");

        // ... here error checks happen ....//                 

        var sandbox = Sandbox.Create();
        var script = (IExecutable)sandbox.CreateInstance(results.PathToAssembly, "Script");

        if(script != null)
            script.Execute();

    }        
}  

public interface IExecutable
{
    void Execute();
}

サンドボックス クラス:

public class Sandbox : MarshalByRefObject
{
    const string BaseDirectory = "Untrusted";
    const string DomainName = "Sandbox";        

    public static Sandbox Create()
    {
        var setup = new AppDomainSetup()
        {
            ApplicationBase = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, BaseDirectory),
            ApplicationName = DomainName,
            DisallowBindingRedirects = true,
            DisallowCodeDownload = true,
            DisallowPublisherPolicy = true
        };

        var permissions = new PermissionSet(PermissionState.None);
        permissions.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess));
        permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));

        var domain = AppDomain.CreateDomain(DomainName, null, setup, permissions,
            typeof(Sandbox).Assembly.Evidence.GetHostEvidence<StrongName>());

        return (Sandbox)Activator.CreateInstanceFrom(domain, typeof(Sandbox).Assembly.ManifestModule.FullyQualifiedName, typeof(Sandbox).FullName).Unwrap();
    }

    public object CreateInstance(string assemblyPath, string typeName)
    {
        new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, assemblyPath).Assert();
        var assembly = Assembly.LoadFile(assemblyPath);
        CodeAccessPermission.RevertAssert();

        Type type = assembly.GetType(typeName); // ****** I get null here
        if (type == null)
            return null;

        return Activator.CreateInstance(type);            
    }
}

読み込まれたスクリプト:

using System;

public class Script : IExecutable
{
    public void Execute()
    {
        Console.WriteLine("Boo");
    }
}

CreateInstanceofではSandBox、常にnullマークされた行に到達します。リフレクションを使用して型名 (または完全修飾名) を読み取るなど、名前を付けるさまざまな形式を試しましたresults.CompiledAssembly。ここで何が間違っていますか?

4

1 に答える 1