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.
Add attribute [ComImport] to your class declaration
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.
Related
My analyzer will match methods with certain signatures. I would like from inside my analyzer to create an instance of the class I'm analyzing and call the method that caused the analyzer to kick in.
Assuming the source code is in a compilable state, is it possible?
Getting the class name and method name is pretty easy, but Type.GetType(...) will always return null.
The purpose of this is that I would like for my analyzer to kick in when I'm on a test method and run it, failing if the test fails.
If the code is not ready for compilation, it would be fine to just return.
It seems possible, but you'd need to check the efficiency of these solutions. Also, you can't guarantee that the code is compilable.
You can grab the Compilation object (from let's say context.SemanticModel.Compilation), call Emit on it, and write it to disc. Then use Assembly.Load to load it, and then it's simple reflection to instantiate the class, whose name you already know, and call the method on it with appropriate arguments.
Another approach would be to use the Compilation in a scripting session as a reference assembly, and use the Roslyn Scripting API to invoke the method. There is a ToMetadataReference method on the Compilation, so you could get a MetadataReference, which could be then passed to ScriptOptions.Default.AddReferences. And then you'd need to pass the resulting options instance to CSharpScript.EvaluateAsync().
There's another fundamental reason you can't run code from the user's compilation, even if it did actually compile -- it might be the wrong environment. Consider a scenario where you're targeting Windows Phone, or Xamarin Android/iOS, .NET Core on Linux, or whatever. In any of these cases the compiler has reference assemblies that you can compile against but obviously you can't actually run that code because it's targeting a different platform. People often ask why you can't convert an ITypeSymbol to a reflection System.Type and back, and this is one of the reasons why -- the compiler can compile code on platform A for platform B, when it can't actually run (or fully load) B's assemblies in the first place.
This question already has answers here:
C# equivalent of DllMain in C (WinAPI)
(4 answers)
Closed 8 years ago.
Below is how to write C++ functionality to do something when the DLL is first called on the server. How does one do this in C# Class Library? The Startup in properties is grayed (disabled) for Class Library project out in Visual Studio but need to be library as I'm using it in my web application as reference. And not sure how to write an equivalent in C# so I could do some code to log events when the dll is loaded or started.
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved ) // reserved
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Here is where the module POST should be invoked
// Return FALSE to fail DLL load in case POST fails
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
I'm using it in my web application as reference
If it's hosted in IIS you can use PreApplicationStartMethodAttribute to run code very early on in your application startup.
This allows you to perform once-off initialisation but might force the initialisation earlier than necessary, because IIS will run your code as the application starts up rather than the first time you use classes in the assembly.
how to write an equivalent in C# so I could do some code to log events when the dll is loaded or started.
DllMain has some pretty severe restrictions. You can't expect to be able to log events reliably from DllMain anyway, so there's no precedent for "I can do it like this in C++ now how do I do it in C#".
There is no such construct in C#. C# is an object-oriented language, so all* executable code resides in classes. The CLR supports such an initialization, but it is not available in C# or VB.NET.
ASP.NET does support attributes that can be added to assemblies to execute code on startup, but it's specific to ASP.NET; it does not get executed when you load the assembly into a WPF app, for example.
However, that also means that you do not need library initialization code in C#. If you have code that needs to be run before classes in the assembly are used, then use the static or instance constructors of those classes to initialize appropriately.
If you have expensive code that is not appropriate to run in a constructor, my next choice would be a documented Init method where you allow the user to choose when to run initialize code. If the user chooses not to run it at startup (or does not know to, then run it when the initialization is required (constructor, member access, etc.)
* I would expect that are some esoteric exceptions, but none that I can think of
I'm not sure if this is the best approach, but you could use a static constructor, for example:
public static class Class1
{
static Class1()
{
//this constructor will be called the first time this class is used.
}
}
Note, that this constructor would not be called until the first time any of the static members of the DLL are used, which is why this may not be the best approach. However, you could, of course, take care of any instance-based initiation in an instance constructor.
Help me out folks - why does this code cause a VerificationException when run under .NET 4.0?
public T parseEnum<T>(string value, T defaultValue) {
//Removing the following lines fixes the problem
if (!typeof(T).IsEnum) throw new ArgumentException("T must be an enumerated type");
return defaultValue;
}
I ran peverify on the .net 2.0 assembly and got the following message:
ImageResizer.Util.Utils::parseEnum[T]][offset 0x0000000A] The 'this' parameter to the call must be the calling method's 'this' parameter.
This causes a VerificationException: Operation could destabilize the runtime message when running the code under medium trust.
I've already read all the similar-looking posts on stack overflow, and none of them apply to this code.
Is there something new with generics that would cause this code to be somehow invalid?
The underlying reason for the error is a change in the signature of IsEnum.
In .NET 2.0 (and 3.0), IsEnum wasn't a virtual method:
public bool IsEnum { get; }
The assembly emitted to call it is:
call instance bool [mscorlib]System.Type::get_IsEnum()
In .NET 4.0, IsEnum is a virtual method:
public virtual bool IsEnum { get; }
Here is the same line of assembly for 4.0:
callvirt instance bool [mscorlib]System.Type::get_IsEnum()
The error you're getting was added in peverify just before the 2.0 release, and warns when a virtual method is called non-virtually.
Now, peverify loads up your code, loads .NET 4.0, and then checks your code. Since your code calls the (.NET 4.0) virtual method non-virtually, the error is shown.
One would think that since you're building against the .NET 2.0 version, this should be fine, and it would load the .NET 2.0 CLR to check. It doesn't seem so.
Edit:
In order to check this, I downloaded .NET 2.0's SDK and tried the peverify in there. It correctly verifies the code.
So the message would seem to be this: use a peverify which matches the target framework of your code.
Solution:
It seems that the _Type interface provides a solution to this:
if (((_Type)typeof(T)).IsEnum) ...
The documentation says it is designed to be called from unmanaged code, but as a side effect of it being an interface, it provides a stable (virtual) method to call.
I have confirmed that it works with peverify whether you target 2.0 or 4.0.
As I understand statements like Debug.WriteLine() will not stay in the code in the Release build. On the other hand Trace.WriteLine() will stay in the code in the Release build.
What is controling this behaviour? Does the C# compiler ignores everything from the System.Diagnostics.Debug class when the DEBUG is defined?
I am just trying to understand the internals of C# and just curious.
These methods use the ConditionalAttribute to designate when they should be included.
When DEBUG is specified as a #define, via the command line or the system environment (set DEBUG = 1 in the shell), a method marked with [Conditional("DEBUG")] will be included by the compiler. When DEBUG is not included, those methods and any calls to them will be omitted. You can use this mechanism yourself to include methods under certain circumstances and it is also used to control the Trace calls like Trace.WriteLine (this uses the TRACE define).
This is due to ConditionalAttribute; the compiler ignores calls to methods marked as conditional unless that symbol is defined.
You can have your own:
[Conditional("BLUE")]
void Bar() {...}
which will only be called when BLUE is defined.
Note that there are some restrictions, to make "definite assignment" work:
no return value
no out parameters
(the same restrictions apply to partial methods for similar reasons)
Is main() (or Main()) in C, C++, Java or C#, a user-defined function or a built-in function?
It's a user-defined function that is necessary for a program to execute. When you go to run your program in the compiled language, the main function is what is executed. For instance, in Java, if you have a function of the signature public static void main(String ... args) in a class then that class can be executed, as the JVM will execute the contents of that main method.
Example in Java:
public class Test {
public static void main(String ... args) {
System.out.println("Hello World");
}
}
...
javac Test.java
...
java Test
Results in "Hello World" being printed to the console.
I'm not sure what you mean by built-in vs. user defined. Almost no language actually gives your user-defined function the privilege of being the true entry-point into the program. C++, any .NET language, and Java all have hidden (built-in) entry point methods that in turn call your user-defined Main method (or whatever the entrypoint method for that language is called -- in .NET it can be named anything, although C# and VB.NET force it to be called Main).
So yes, virtually every language has a concept of a method that is automatically called, and this method is a user-defined method and usually mandatory. But virtually every language also has a built-in entry point method that actually sets up the framework and/or memory management for the process before invoking your user-defined "entry-point" function.
Quote from the C Standard (emphasis is mine):
5.1.2.1 Freestanding environment
In a freestanding environment (in
which C program execution may take
place without any benefit of an
operating system), the name and
type of the function called at
program startup are
implementation-defined. Any
library facilities available to a
freestanding program, other than the
minimal set required by clause 4,
are implementation-defined.
main(), in a freestanding environment, is very much a user-defined function.
It's a required user defined function (the entry point for executables)...
It is not "built-in" in any language, in a sense that there is no standard implemented-for you main() avialable.
For C/C++/Java, it is a function with a special property, namely, the function that will be called at the start of your program after all the static setup is done. E.g. entire C program's execution path is:
Do some initialization code
Call main()
Exit.
As such, it has a standard declaration (# of parameters passed from command line + array of "strings" - however the language implements that - which are the actual arguments from command line)
In C/C++, it a standard so its built in and reconized.
Java, not sure, no experience
C# - Its a part of a class so its defined by you.
All of these are defined by you -- you tell it what to do.
It's a user defined function that is called by the language's runtime library. For example, a C runtime library will grab the command line arguments and sometimes environment variables from the operating system and pass them into to your main() function.
Different language runtimes usually perform the same operation in one form or another, and will throw some sort of error if the function it tries to call doesn't exist.
It's declaration is built-in. It's definition is user supplied, or in some cases supplied by an application framework that has some other entry point, or in the case of most event-driven GUI frameworks, no single user-defined entry point.
In Java main(String[] args) is the entry point for applications by convention (to make C++ programmers comfortable). For applets or servlets the invocation of code happens differently. Note that a jar may contain any or none of these entry points and that each class may contain a main so a given jar can be invoked in many different ways as an applcation if so desired.