简体   繁体   中英

Assembly loaded using Assembly.LoadFrom() on remote machine causes SecurityException

I am loading an assembly using Assembly.LoadFrom(fileName) . When fileName is on the local machine, everything works fine. When, however, the identical file (and dependencies) are on a remote network share, I get a System.Security.SecurityException the moment I try to create a new SqlConnection from the remote assembly:

System.Security.SecurityException: Request for the permission of type 'System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.

What's the cure?

You could load the assembly as bytes and load it with Assembly.Load(bytes) , maybe this works.

Or you give the application the requested permission.

Edit:

I made a little test and it worked for me. Here is some code:

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"));
}

Something important:

There may be files which do not have a matching name and file name, but you can resolve this by checking all files in folder with AssemblyName.GetAssemblyName(file) .

The assembly is being loaded with LocalIntranet permission set. This restricts certain APIs. See:

http://msdn.microsoft.com/en-us/library/03kwzyfc.aspx and http://msdn.microsoft.com/en-us/library/0x4t63kb%28v=vs.80%29.aspx

Well, I found a workaround. I could not find any way to circumvent the SecurityException problem - so instead of loading the assembly from the remote folder, I simply copied the remote folder contents at runtime to the local computer and ran from there. Simple, neat and works perfectly. Plus, it's arguably a better way of working, so that the clients are running off their local copy instead of putting load on the server, and it makes it much easier to deploy an updated version of the original, without any file locking.

Caveat to anyone who tries to follow in my footsteps: don't try and copy to a subfolder of your app directory; for some reason this causes errors with dependencies. Rather copy to 'Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)` or some other folder to which you know you have write access.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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