当我尝试在具有受限权限的AppDomain中运行IronPython脚本引擎时,我遇到了启动时间过长的问题。有人可以提供一个如何以高效的方式执行此操作的规范示例吗?
No AppDomain no standard library
Time taken: 36.1022ms
No AppDomain with standard library
Time taken: 37.8556ms
我看到它在某处提到创建AppDomain实例很昂贵。创建一个受限制的AppDomain并重用它是最佳做法吗?
[assembly: AllowPartiallyTrustedCallers]
public class ScriptEvaluator : MarshalByRefObject
{
public ScriptEngine ScriptEngine { get; set; }
public String PythonStandardLibaryPath { get; set; }
public String PythonApplicationCodePath { get; set; }
public ScriptEvaluator()
{
PythonStandardLibaryPath = Path.GetFullPath(@"..\..\..\MyProject\standard_library");
PythonApplicationCodePath = Path.GetFullPath(@"..\..\..\MyProject\python_code");
}
public ScriptEvaluator InstantiateInAppDomain()
{
/* create app domain setup */
var appDomainSetup = new AppDomainSetup { ApplicationBase = Environment.CurrentDirectory };
//appDomainSetup.ApplicationBase = Path.GetDirectoryName(Environment.CurrentDirectory);
//appDomainSetup.ApplicationBase = Environment.CurrentDirectory;
//appDomainSetup.DisallowBindingRedirects = false;
//appDomainSetup.DisallowCodeDownload = true;
//appDomainSetup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
/* assign permissions */
var permissionSet = new PermissionSet(PermissionState.None);
permissionSet.AddPermission(new ReflectionPermission(PermissionState.Unrestricted));
permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, PythonStandardLibaryPath));
permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, PythonApplicationCodePath));
if (Debugger.IsAttached)
{
permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode));
}
/* create a script evaluator instance in the app domain and return a reference */
var appDomain = AppDomain.CreateDomain("Sandbox", null, appDomainSetup, permissionSet);
var scriptEvaluator = (ScriptEvaluator)appDomain.CreateInstanceAndUnwrap("MyProject", typeof(ScriptEvaluator).FullName);
scriptEvaluator.CreateScriptEngine();
return scriptEvaluator;
}
public ScriptEngine CreateScriptEngine()
{
/* create the iron IronPython engine */
var options = new Dictionary<string, object> { { "Debug", Debugger.IsAttached } };
ScriptEngine = Python.CreateEngine(options);
/* add library directories to the search paths */
var searchPaths = ScriptEngine.GetSearchPaths();
searchPaths.Add(PythonStandardLibaryPath);
searchPaths.Add(PythonApplicationCodePath);
ScriptEngine.SetSearchPaths(searchPaths);
return ScriptEngine;
}
}
注意:我必须使用AllowPartiallyTrustedCallers来解决安全错误,我不确定这是否是一种理想的方法。
用法:
var scriptEvaluator = new ScriptEvaluator().InstantiateInAppDomain();
var scriptScope = scriptEvaluator.ScriptEngine.CreateScope();
script = @"from mymodule import *; a = 1 + 1; b = 2 + 2; c = a + b";
foreach (var number in Enumerable.Range(1, 10))
{
Stopwatch stopwatch = Stopwatch.StartNew();
scriptEvaluator.ScriptEngine.Execute(script, scriptScope);
stopwatch.Stop(); Console.WriteLine("Time taken: {0}ms", stopwatch.Elapsed.TotalMilliseconds);
}
进行了一些分析,看起来第一次执行ScriptEngine.Execute比后续执行更昂贵。
// Time taken: 8.937ms -- InstantiateInAppDomain
// Time taken: 429.9291ms -- CreateScriptEngine
// Time taken: 9.1289ms -- CreateScope
// Time taken: 2080.1795ms -- ScriptEngine.Execute first
// Time taken: 5.2469ms -- ScriptEngine.Execute second
// Time taken: 7.9255ms -- ScriptEngine.Execute third
// Time taken: 3.1206ms -- ScriptEngine.Execute fourth
// Time taken: 3.1316ms -- ScriptEngine.Execute fifth
// Time taken: 3.0643ms -- ScriptEngine.Execute sixth
是否有人知道缺少哪些权限才能在受限制的AppDomain中导入os模块?添加我能找到的每个权限都不起作用。