我使用Assembly.LoadFrom(fileName)
加载程序集。当fileName
在本地计算机上时,一切正常。但是,如果相同的文件(和依赖项)位于远程网络共享上,那么当我尝试从远程程序集创建新的System.Security.SecurityException
时,我会得到SqlConnection
:
System.Security.SecurityException:请求类型的权限 'System.Data.SqlClient.SqlClientPermission,System.Data, Version = 2.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089' 失败。
治愈的是什么?
答案 0 :(得分:4)
您可以将程序集作为字节加载并使用Assembly.Load(bytes)
加载它,也许这样可以。
或者您向应用程序提供所请求的权限。
我做了一点测试,它对我有用。这是一些代码:
static Dictionary<Assembly, String> _Paths = new Dictionary<Assembly, String>();
static void Main(string[] args)
{
AppDomain current = AppDomain.CurrentDomain;
current.AssemblyResolve += new ResolveEventHandler(HandleAssemblyResolve);
// This line loads a assembly and retrieves all types of it. Only when
// calling "GetTypes" the 'AssemblyResolve'-event occurs and loads the dependency
Type[] types = LoadAssembly("Assemblies\\MyDLL.dll").GetTypes();
// The next line is used to test permissions, i tested the IO-Permissions
// and the Reflection permissions ( which should be denied when using remote assemblies )
// Also this test includes the creation of a Form
Object instance = Activator.CreateInstance(types[0]);
}
private static Assembly LoadAssembly(string file)
{
// Load the assembly
Assembly result = Assembly.Load(File.ReadAllBytes(file));
// Add the path of the assembly to the dictionary
_Paths.Add(result, Path.GetDirectoryName(file));
return result;
}
static Assembly HandleAssemblyResolve(object sender, ResolveEventArgs args)
{
// Extract file name from the full-quallified name
String name = args.Name;
name = name.Substring(0, name.IndexOf(','));
// Load the assembly
return LoadAssembly(Path.Combine(_Paths[args.RequestingAssembly], name + ".dll"));
}
可能有文件没有匹配的名称和文件名,但您可以通过使用AssemblyName.GetAssemblyName(file)
检查文件夹中的所有文件来解决此问题。
答案 1 :(得分:1)
程序集正在加载LocalIntranet权限集。这限制了某些API。参见:
http://msdn.microsoft.com/en-us/library/03kwzyfc.aspx和http://msdn.microsoft.com/en-us/library/0x4t63kb%28v=vs.80%29.aspx
答案 2 :(得分:1)
好吧,我找到了解决方法。我找不到任何方法来绕过SecurityException
问题 - 所以不是从远程文件夹加载程序集,而是简单地将远程文件夹内容在运行时复制到本地计算机并从那里运行。简单,整洁,完美。此外,它可以说是一种更好的工作方式,因此客户端正在运行本地副本,而不是在服务器上加载,这使得 更容易部署更新版本的原始版本,没有任何文件锁定。
警告给任何试图跟随我的脚步的人:不要尝试复制到app目录的子文件夹;由于某种原因,这会导致依赖性错误。而是复制到'Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)`或您知道自己具有写访问权限的其他文件夹。