Sean P
Sean P

Reputation: 949

Using Reflection, a security exception is thrown

So I have the following code:

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SetDllDirectory(string dllPath);

In a function:

            SetDllDirectory(@"G:\Sean\Debug\");

            Assembly loadedDLL = Assembly.LoadFrom(@"G:\Sean\Debug\BonderControlPanelSim.dll", AppDomain.CurrentDomain.Evidence);
            Type rtsObj = loadedDLL.GetType("Oe.Te.Ranorex.Instrument.BonderControlPanelSim");
            Object obj = Activator.CreateInstance(rtsObj);

            rtsObj.InvokeMember("Initialize", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, obj, new object[] { "COM3", 1, 2 });
            rtsObj.InvokeMember("PushStart", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, obj, new object[] { 3 });
            rtsObj.InvokeMember("Shutdown", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, obj, null);

However, when I run a small app with just this function from the same folder as the DLLs, there is no issue. When I move the executable to another machine that has the G-drive mapped, I get a security exception.

<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Flags="UnmanagedCode"/>

Not sure how to handle this. In Assembly.LoadFrom I pass evidence.

The exception is thrown at the first rtsObj.InvokeMember.

Appreciate your help!

EDIT: The application actually fails to launch on other machines. If I have the executable alone by itself on my machine, it will launch.

Upvotes: 0

Views: 1142

Answers (2)

AdamSane
AdamSane

Reputation: 2882

You can change your security policy to allow the CLR to open from a remote source.

Link

// From the Article
// Since this application only trusts a handful of LoadFrom operations,
// we'll put them all into the same AppDomain which is a simple sandbox
// with a full trust grant set.  The application itself will not enable
// loadFromRemoteSources, but instead channel all of the trusted loads
// into this domain.
PermissionSet trustedLoadFromRemoteSourceGrantSet
    = new PermissionSet(PermissionState.Unrestricted);
 
AppDomainSetup trustedLoadFromRemoteSourcesSetup = new AppDomainSetup();
trustedLoadFromRemoteSourcesSetup.ApplicationBase =
    AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
 
AppDomain trustedRemoteLoadDomain =
    AppDomain.CreateDomain("Trusted LoadFromRemoteSources Domain",
                           null,
                           trustedLoadFromRemoteSourcesSetup,
                           trustedLoadFromRemoteSourcesGrantSet);
 
// Now all trusted remote LoadFroms can be done in the trustedRemoteLoadDomain,
// and communicated with via a MarshalByRefObject.

Upvotes: 1

cdhowie
cdhowie

Reputation: 169008

.NET assemblies residing on remote network shares are not considered trusted enough by the default .NET security policy to allow them to execute P/Invokes. You will need to change your security policy, copy the assembly to a local folder (not a mapped network drive), or remove the SetDllDirectory P/Invoke call entirely.

Upvotes: 1

Related Questions