Using Main from a class library instead of the program - c#

I have numerous projects that all contain the exact same boilerplate code inside of the main function. They all reference the same assembly (which is the one providing a majority of the functionality). This assembly is not referenced by anybody except for the ones who use this same boilerplate main code.
Is it possible to have a Main function inside of a class within the assembly and use it within the program referencing the assembly instead of a class within the current assembly? I would prefer to not even write a Main function within the programs if I can.
EDIT: I want the Main inside of the referenced assembly to BE the entry point.

No, you cannot skip the static Main function in your executable assemblies because that's the entry point but you could perfectly fine define a method in this assembly with the same signature that will be invoked from the Main methods of all projects that need this boilerplate code.
For example:
static void Main(string[] args)
{
SomeClass.SomeMethodToDoBoilerplate(args);
SomeSpecificMethods();
}

Related

C# DLL Injection - Call Method of Running Application

Lets say I have an executable 'foobar.exe' written in C# and now compiled, running on a Windows box. One of the functions in the application is the following (example):
public static async Task LoadBox(string msg)
{
System.Windows.Forms.MessageBox.Show(msg);
}
I would like to write a DLL in C# that calls this method in the application. The DLL, say 'injected.dll', will be injected into the running 'foobar.exe' process using the injector referenced here: http://www.codingvision.net/miscellaneous/c-inject-a-dll-into-a-process-w-createremotethread
Is it possible from the newly injected DLL to call the public function in the original exe? If so, any example code in C# would be appreciated.
My approach would be to use the concepts of Reflection. We could make the EXE load an assembly through reflection, discover a Type and invoke a method on this Type and then pass an instance of a class in your EXE to this method, which in turn does a call back. A round about way - but it would work.
You can use the method System.Reflection.Assembly.LoadFrom( to load an assembly compiled for .NET. This is a fairly old technique, nothing new about it. Dependency contains and applications that are meant to load plugins post deployment are written using this method.
Step 1
Load the plugin assembly into the current Appdomain using System.Reflection.LoadFrom
Step 2
Find the Type in this plugin assembly by using Assembly.GetTypes()
Step 3
Pass an instance of a class defined in your EXE into the plugin and have the plugin do a call back. This is what an event call back would actually do.
Link
https://learn.microsoft.com/en-us/dotnet/api/system.activator.createinstance?view=netframework-4.7.2#System_Activator_CreateInstance_System_AppDomain_System_String_System_String_System_Boolean_System_Reflection_BindingFlags_System_Reflection_Binder_System_Object___System_Globalization_CultureInfo_System_Object___

Multiple Main Functions

I'm a bit new at this so bear with me. I'm currently learning C# and Java and one of their similarities is that the main function needs to be encapsulated within a class. For example
public class HelloWorld {
public static void main(String[] args) {
// Some Code
}
}
Now I understand that main is often the "entry point" when you run the program. So basically, your program will start executing wherever the main function is. But I believe in both languages you can have multiple main functions within multiple classes. So when I compile a project with multiple main functions, where is the "entry point"? How does the compiler know where to start?
In Java, the computer determines the "entry point" when you actually execute the program, not when you compile. For example, from the command-line
java MyClass
searches for main() in MyClass. All other main() functions are ignored.
If you are using an IDE, then you can set which class contains the main() function that you want to use.
In .NET, you can define which class contains the Main method you want to use when you're compiling.
http://msdn.microsoft.com/en-us/library/x3eht538.aspx
In Java, if you're bundling to a jar, you can define your entry point in the jar's manifest.
http://docs.oracle.com/javase/tutorial/deployment/jar/appman.html
In C#, you can use multiple Main methods.
If there are multiple Main methods, the compiler doesn't know which entry point to use and hence it will show you an error.
You need to specify the Main method to be used at compilation:
You can specify which method to be used as a compiler option in the Visual Studio development environment or through the csc compiler.
The main class is a special class for only one reason: when you run the Java Virtual Machine, that function is what the JVM calls. It is essentially like any other function, and in fact you can call one class's main function from another class.
When you compile a project with multiple classes, you tell the JVM to run the class with the main class you want to use, like so:
java SomeClass
and it will run the main method of SomeClass, assuming that SomeClass is compiled and that the appropriate compiled file is in your classpath. (That is something you'll have to work out with your particular OS, but I think it's fairly usual for the -cp option to specify a classpath). So this:
java -cp /home/MyName Someclass
will run the main function of SomeClass in the directory /home/MyName
In C#, you specify the entry point using the /main: compiler option.
Consider the following code containing two main() functions:
namespace Application {
class ClassOne {
static void main () {
// Code here
}
}
class ClassTwo {
static void main () {
// Code here
}
}
}
To use ClassOne.main() as your entry point, you would specify the following when compiling:
csc /main:Application.ClassOne hello.cs
For multiple main functions entry point can be declared by :
To set this compiler option in the Visual Studio development environment
Open the project's Properties page.
Click the Application property page.
Modify the Startup object property.
reference : http://msdn.microsoft.com/en-us/library/x3eht538.aspx
In Java, as others pointed out, you define the class containing your main function when you run the java command.
But you could also build an executable jar, which can be run with java -jar my.jar. In this case, you need a manifest file called MANIFEST.MF in the folder META-INF in the jar. In this file, you specify the class containing the main function using the statement: Main-Class: YourClass.
The main method is static, which means it belongs to the class rather than the object. So the object won't have another main method inside it at all. It won't have an additional main-method, as main is static. So it's once per class.
If you have multiple main-methods in your project, you will specify which one to launch when starting your application
In fact, in binary file, for example, PE format in windows and ELF format in Linux or any other system, The header of binary file will specify where is the start address and there can be only one.
Which one should be the entry point? It depends on the linker. Just like #SetFreeByTruth said that you can specify it with command line parameters.
Many linkers support specifying entry point with command line parameters. for example, gnu's gld can specify entry point with parameter -e.
I don't know the behavior of Java because it is loaded by Java virtual machine.
In Visual Studio, you select the project that you want to be the entry point, right click and Set as StartUp Project.

How the runtime knows which class contain the Main method in C# application?

I know that for Console/Windows application in C#, "Main" method is entry point to run the application.
If we have hundreds of classes in our application, how the runtime will detect which class contains the "Main" method to run the application?
The compiler looks for
static void Main(string[])
or
static int Main(string[])
to determine the entry point. Main() may also be declared without the string[] argument. You only need to specifically set the project setting if you have multiple classes with Main() functions.
Here's MSDN's detailed answer for you.
Entry Point can be configured in Project Settings.

Marshalling Assembly from another AppDomain

Is it possible to hold a reference to an Assembly from another appdomain without having that assembly loaded into the current appdomain?
I'm working on fixing a memory leak in a Windows Service that dynamically generates Assemblies and runs the dynamically generated code. The problem is the generated Assemblies are loaded into the Current app domain and can never be unloaded.
There is a method in one of the Windows Service libraries that has the follow signature:
public Assembly CreateMethod(ObservableCollection<Field> sourceFields, Field destinationField)
This method creates the code for the assembly and loads it with the CSScript library LoadMethod function:
result = CSScript.LoadMethod(scriptFunction.ToString());
Later this Assembly reference from CreateMethod is used to run a function inside the generated assembly.
public object Run(Field destinationField, ObservableCollection<LinkField> sourceLinkFields, DataRow mainRow, Assembly script) {
...
var method = script.GetStaticMethodWithArgs("*.a" + Id.ToString().Replace("-", String.Empty), argumentTypes.ToArray());
return method(arguments.ToArray());
}
I'm wondering if it is possible to load the dynamically generated assembly into another app domain and run them through some type of proxy without having it loaded into the current app domain.
Edit:
I want to know if I can use an Assembly class reference in one AppDomain when the assembly is loaded in another AppDomain. Looking at the MSDN documentation they show how to use MarshalByRefObject. Basically I am trying to avoid changing the signature to my CreateMethod function, however I may need to change it to return MarshalByRefObject if this is not possible.
Update:
I ended up putting the call to CSScript.LoadMethod in the other app domain where I keep a Dictionary I then made CreateMethod return a Guid instead of an Assembly and then I pass this Guid around until the Run call. The Run call now takes a Guid as an argument instead of an Assembly. Inside the Run call I pass the Guid to the other app domain, run the method, and return the result object through a class that inherits MarshalByRefObject.
If you don't want the dynamic assembly in your main AppDomain, you have to move CreateMethod to another AppDomain, because as soon as you have an instance of Assembly, it's been loaded. In other words, no it is not possible to hold a reference to an assembly in another application domain, only to call into that assembly across application domains.
Without changing the signature and a bunch of your code, it seems like you need to move the minimum amount: 1) assembly creation and 2) Run. Then have the implementation of Run marshall the results.
As far as CreateMethod I think you want a method in the other assembly to "wrap" CreateMethod and return some sort of token that can be passed to Run. It's almost like changing the signature in a way...
This is one of the major features of an AppDomain! Just go look at the documentation

if __name__ == "__main__": equivalent in C#

With python, I can use if __name__ == "__main__": for using the module both as a library and a program.
Can I mimic this feature in C#?
I see a class in C# can have a 'static void Main()', but I'm not sure if every class can have a Main() without a problem.
ADDED
/m:CLASS_NAME is a way to specify the class to run the Main().
You can put a Main method in as many classes as you like, although only one can be an entry point for an application. (For talks, I often have a main method in every class, and use a helper library to present all of those pseudo-entry-points when I run the project.)
Likewise you can definitely add a reference to a .exe assembly and treat it like a library. For example, you could make a unit testing assembly work like a class library in most cases, but also write a main method so that you could just run it to execute the tests without a GUI or whatever.
You can compile a C# project as a program (executable) with a Main() method, and you'd still be able to use it as a library. No special syntax required.
You could add a Main() method to every class, but I doubt it's useful.
.NET applications usually have different structures than Python ones; trying to fit the same programming model is unlikely to get you good results.
C# project files specify a startup object when multiple entry points are available.
See this article for more info.

Categories

Resources