38

I have a (C#) function similar to the following.

private static bool SpecialCase = false;

public void Foo()
{
    if (SpecialCase)
    {
        InternalMethod();
        return;
    }

    Console.WriteLine();
}

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void InternalMethod();

When I execute this with the .NET Framework 4 inside the debugger, the method successfully prints blank line to the console and returns. When I execute it outside the debugger, it throws an exception with the following message:

System.Security.SecurityException: ECall methods must be packaged into a system module.

It appears the exception is thrown when the JIT compiler compiles the method as opposed to when (if) InternalMethod is called. Is there anything I can do (e.g. attributes) to tell the CLI to either not throw the SecurityException, or delay the exception until the method is actually called?

Side note on the use case: The SpecialCase field is effectively false when running with Microsoft .NET Framework, and true when running under a different (specific) implementation of the CLI. When running under the Microsoft .NET Framework, the call to InternalMethod is effectively unreachable.

Sam Harwell
  • 92,171
  • 18
  • 189
  • 263
  • 1
    Can you wrap it in a normal method? – SLaks Jul 01 '12 at 22:11
  • 2
    Yes, it appears that calling a wrapper method like the following avoids the exception. The downside is this practice would lead to even more confusing code paths in an already complex algorithm, so I prefer a cleaner solution if one can be found. `private static void InternalMethodWrapper() { InternalMethod(); }` – Sam Harwell Jul 01 '12 at 22:18
  • BTW It happens also on `.NET 4.5.2` but in both frameworks (both frameworks has the same `CLR` anyway) only in `Release` not in `Debug`, did you consider working in `Debug` mode? – Tamir Vered Sep 30 '15 at 09:10
  • The only info I could dig up about this is that the error message is a resource with id 8244 in mscorrc.dll (Microsoft .NET Runtime resources). – Siderite Zackwehdex Mar 29 '16 at 20:34

2 Answers2

2

You may want to check the compiler directives as a possible option. Unlike using a run-time "if", this will determine whether the call is included in the compiled code at all, rather than always compiling it into the code and trying to determine whether to call it at run-time (which is too late, based on your analysis).

Your use-case seems like a testing/validation scenario, which means that you don't need it compiled into the code except when the internal call will actually be made.

Note that if your use-case involves a non-.NET runtime, you should provide more information since that could drastically change the correct answer.

Emzor
  • 1,320
  • 16
  • 27
Matt Jordan
  • 2,080
  • 7
  • 10
1

Add attribute [ComImport] to your class declaration

SkyFx
  • 166
  • 8