I have a console app, that is used for importing stuff from a WS.
I'm really new to Console Apps so I have a question.
The Project contains a class called Importer.cs. This class has a Method called Initialize():
class Importer
{
static void Initialize()
{
//here i connect to the server etc.
}
}
Now I want to be able to call my APP like:
Importer.exe Initialize
So it should call the Initialize method, and then I would like to be able to go on with for example:
Importer.exe StartImport
I already work with the args[] parameter, but i'm quite stuck now.
Use a library like CommandLineParser and then use Reflection to call these method as MethodInfo objects.
In your console application, look in your solution explorer (in the right window of VS where all your files are shown). Find the one called PROGRAM.CS. Open it and look for this:
static void Main(string[] args)
{
}
Inside that, put this:
static void Main(string[] args)
{
//This starts a new instance of the Importer Class
Importer myImporter = new Importer();
//This calls the Initialize Method within Importer
Importer.Initialize();
//This calls the StartInput() Method within Importer
Importer.StartInput();
//Use Console.ReadLine() as the last line in this method to keep your screen open after program execution ends.
Console.ReadLine();
}
The first thing your console app runs ins Main() in console app.
Then, you simply test the project using F5. After testing, build the project and run by double-clicking the EXE file.
Depending on what you're exactly doing, this might not even work. I imagine a situation, where you Initialize() and afterwards StartImport(), but in between these 2 calls the program has been finished and the initialized state is gone. If you do not have methods like Initialize(), but rather atomic subcommands, your approach is possible in principle.
But there arises one question: Is this going to be generic? I mean: Say, you add another method. Do you then want to have the access to the method by a subcommand automatically established or wouldn't you mind adding another subcommand case? The first option would mean, you need to get comfortable with Reflection.
Now, say, you add methods, which you cannot declare private due to whatever reason, but you don't want them to be exposed as a subcommand. So you would need to keep track of the visibility. Sure, this would mean poor design, but if you're stuck with legacy components, this might just happen.
Now, let's say you need the Initialize() (or similar) command(s). They take care of a connection state or whatever and the program needs to still run, when the next subcommand is invoked, so it can use the initialized information, handles, etc.. Wouldn't it then make more sense to design your console application like a shell? So you would start with Importer.exe and get asked for subcommands.
Related
I have a c# console application where I need to take some command line arguments.
For this reason I need a main method, instead of the non-main method that is currently there, and since I can't find any material on how to do it without.
So, I tried just pasting some code into my newly created visual studio dotnet 6 c# application:
static void Main(string[] args)
{
Console.WriteLine("hi there");
}
Which does'nt work. The code is not executed.
How do I add a main method, so I can take some cmd arguments?
You don't need a classic Main method to access command-line arguments. You can just access the "magic" variable args. The following is a complete and valid C# program (fiddle):
using System;
Console.WriteLine("I got " + args.Length + " command line arguments.");
This is documented here:
You don't declare an args variable. For the single source file that contains your top-level statements, the compiler recognizes args to mean the command-line arguments. The type of args is a string[], as in all C# programs.
For completeness: If you want a "classic" Main entry point, you need
a class or struct with
a static method called Main with
a return type of either void or int (or Task/Task<int>, if you create an async method) and
no parameter or a single string[] parameter.
It seems like you miss the class in your example. A full minimal working example looks like this:
using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World");
}
}
The exact criteria are documented here:
https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line
When you create the project, there is a box to check to not use top-level statements. Create a new project and check that box, then it will work just like in older versions. The box even has an info icon next to it that, when moused-over displays this message:
Whether to generate an explicit Program class and Main method instead of top-level statements.
If you do create a project with top-level statements, this URL is provided at the top of the code file. The information you needed was provided but you didn't pay attention. It's always important to pay attention to what VS is trying to tell you because it provides a lot of useful information.
Thanks to an advanced initialization scenario (as warned about in the documentation), we're leveraging the ModuleInitializer attribute to run some code at module-initialization time like so...
[ModuleInitializer]
public static void InitModule() {
// Do something with the app here
}
However, we found differences in behavior depending on how the module was loaded. Specifically...
If loaded via a project reference/dependency, Application.Current property is not set.
If dynamically loaded via reflection, Application.Current property is set.
Since we need access to the current application for part of our initialization (it doesn't have to run right then, only when the application exists), our initial approach was during our initializers, test if Application.Current was set. If so, use it as normal. If not, build some sort of 'actions queue' that would queue up all the actions we want to run, then from within the Application class's constructor, process that queue.
As such, the above changed to this...
[ModuleInitializer]
public static void InitModule() {
void appRelatedInitialization(Application application) {
// Do something with the app here
}
if(Application.Current is not null) {
appRelatedInitialization(Application.Current);
}
else {
// Add the method to a queue of actions which take an Application as an argument
Globals.AppInitQueue.Add(appRelatedInitialization);
}
}
But then we ran into an application that doesn't use an Application subclass, instead opting for a main method and doing all the app configuration there.
Of course we could add the queue processing there, just like we could with an initializer and subclassing, but what we really want is to know when the application is instantiated regardless of the type of application it is and have this execute automatically for us so we don't have to add it anywhere.
The issue is Application.Current is a static POCO property that doesn't use INotifyPropertyChanged or similar, so we're not sure how to determine when the Application instance is set. We don't want to use brute-force polling either as that is the worst kind of code-smell.
So, how can we determine when the current Application object is created and assigned to the running process?
Dispatcher.CurrentDispatcher will create a Dispatcher for the current thread if not already created, which will be started by Application.Run(), so you should be able to do
Dispatcher.CurrentDispatcher.BeginInvoke(() => {})
I tried this, and it will run after the App constructor and App_Startup is called, if you leave Dispatcher.Priority as it's default.
(If you want it to run earlier, you can do
Dispatcher.CurrentDispatcher.BeginInvoke(() => {}, DispatcherPriority.Send);
in which case it will run after App construction but before App_Startup, although reading through the source code it seems they explicitly try to run OnStartup first, due to some bug, and this is circumventing that. I don't know the repercussions of doing that.)
I have a situation where I need to create a (arguably dirty) soak test runner. The idea being to use something like Tasks or the ThreadPool to run a massive amount of the tests at one time.
The issue is that it will be using a lot of (poorly developed, by me) helper classes that use statics within them. This has never been an issue as everything was torn down and restarted after it was used. This means that when I start multiple threads in the same app domain, they use the same statics, and things get messy.
Note: it is an assumption based on testing I've been doing, I'm not 100% sure on that being the issue.
I've tried creating a new AppDomain (AppDomain.Create) and then created an instance of a class using it (domain.CreateInstanceFromAndUnwrap), and it creates the instance, and I can call methods on it. The problem is that it doesn't seem to be running in the new AppDomain.
Here's the code I have so far:
static void CallBack(BasePerfTest bpf)
{
Console.WriteLine("CurrentAppDomain (WithinCallback): {0}", Thread.GetDomain().Id);
AppDomain newdomain = AppDomain.CreateDomain(Guid.NewGuid().ToString());
//newdomain.ExecuteAssembly(".\\PerformanceTestRunner.exe", new string[] { bpf.ToString() });
ProcessRunner pr = (ProcessRunner)newdomain.CreateInstanceFromAndUnwrap(Assembly.GetExecutingAssembly().Location, "PerformanceTesting.ProcessRunner");
pr.RunProcess(bpf);
}
}
[Serializable]
public class ProcessRunner
{
public void RunProcess(BasePerfTest bpf)
{
Console.WriteLine("CurrentAppDomain (WithinPR): {0}", Thread.GetDomain().Id);
}
}
Now, I would expect that the RunProcess() method is executed in the domain, but the DomainID is still the same, and therefore it's hitting the issue with the statics colliding.
Now, I did created a separate console app, and the commented out line shows the code I used to run it. This DID run in the new domain, but the question is why.
I'm happy to be pointed in the direction of some bedtime reading on how this works, I've 'd for the past day and I think I must just not be using the right terms.
Any help is much appreciated.
Thanks,
Martin
There are two ways to expose objects over AppDomain boundaries:
Serializable - serializes the object, so you get a copy.
MarshalByRefObject - creates a proxy to your object, using remoting.
You need the latter for your ProcessRunner class.
Make your class inherit from MarshalByRefObject:
public class ProcessRunner : MarshalByRefbject
{
public void RunProcess(BasePerfTest bpf)
{
Console.WriteLine("CurrentAppDomain (WithinPR): {0}", Thread.GetDomain().Id);
}
}
When you instantiate your class in the second AppDomain, you get a proxy. The example in the documentation for MarshalByRefObject on MSDN should also help you - it demonstrates almost exactly what you are trying to do.
Your ProcessRunner class must inherit from System.MarshalByRefObject. What is happening is that the object is actually being created in the secondary appdomain, but when you assign it to your local 'pr' variable it is marshalling it by value back to your primary appdomain, in effect creating a second instance of ProcessRunner in the primary appdomain. If you inherit from MarshalByRefObject then pr will instead get a transparent proxy object which forwards calls to the object residing in the secondary appdomain.
I am reviewing a co-worker's C# console app, and I see this snippet:
class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.RealMain();
}
... non-static RealMain function
}
Presumably, he's doing this because he wants to have instance-level fields, etc.
I haven't seen this before, but this style bugs me. Is it a common and accepted practice?
There is a school of thought that says that the main() function of object oriented code should do as little as possible. Main() is an "ugly" throwback to procedural code design, where programs were written in one function, calling subroutines only as necessary. In OOP, all code should be encapsulated in objects that do their jobs when told.
So, by doing this, you reduce the LOC in the main() entry point to two lines, and the real logic of the program is structured and executed in a more O-O fashion.
It makes sense to me.
In particular, you may want to add just enough logic into Main to parse the command line arguments - possibly using a generalized argument parser - and then pass those options into the constructor in a strongly-typed way suitable for the program in question.
Albin asked why this would be necessary. In a word: testability. In some cases it's entirely feasible to at least test some aspects of a top level program with unit tests or possibly integration tests. Using instance fields instead of static fields (etc) improves the testability here, as you don't need to worry about previous test runs messing up the state.
if you want to get non static functions you have to do like this.
class Program
{
static void Main(string[] args)
{
Program p = new Program(); // dependency of the class will be there.So not a good practice
p.RealMain();// if you want initalize, you have to go like this or better you can do it in some other class.
}
void RealMain(){}
}
Never seen it before. If you want to go with this pattern, create a separate Program2-class with RealMain and instantiate that instead.
Why do you need instance level fields? Is static fields not enough?
There could be a benefit if you internally want to instantiate many Program classes.
I don't see anything particularly wrong with this approach, I just don't have seen it before.
Application entry point is always defined as static void Main(...).
You can decide to write your code inside Main() or use this method to run something else located elsewhere... it's up to you decide...
The accepted practice is to create an instance of a separate class which can contain anything you need. The above snippet looks weird at least :).
If it was any other class but "Program" the question wouldn't have come up. This design gives you the opportunity to instantiate multiple instances of "Program", maybe threaded in the future, so why not. I'm with KeithS here: As few as possible in static void Main.
I see this a lot, particularly for quick console programs knocked up to try something out, or test something.
Visual Studio practically encourages it - if you ask for a new Console program, it generates a single file, with a class containing only a Main method.
Unless you are doing something complicated, which requires more than 1 class, or something very simple, which doesn't require a class at all (i.e. all methods and variables static)
why would you not do it this way?
c# enables us to define more than one class with the method. Main method is the entry point for program execution. So why do we want to have more than one place for program execution. What is the advantage of multiple main methods over single main method.
Edit:
Example.cs
Class Example_1
{
public static void Main()
{
System.Console.WriteLine("Example 1")
}
public void test()
{
System.Console.WriteLine("Test method")
}
}
Class Example_2
{
public static void Main()
{
System.Console.WriteLine("Example 2")
}
}
If I type "csc Example.cs" then what would happen ?
What to do if I want to inherit test method of Class Example_1 in Class Example_2. Will this code work.
Example_1 abc = new Example_1();
abc.test();
You could use it so that different build configurations built the same executable but with different entry points - for example a console entry point vs a WinForms entry point.
Personally I use it when giving talks and in the sample code for C# in Depth. Each file is a self-contained example, but it's simpler to just have one entry point - so that entry point uses a utility class to prompt the user for which example they want to run.
First, if you have multiple main methods, you can specify which to use as the entry point for the application by your compiler.
Multiple main methods can be useful for testing purposes. Maybe you're developing a windows application like a text editor. If you are working on something like syntax highlighting, for example, you can have an extra main method which starts the GUI, loads a test file and enables the appropriate syntax highlighting.
Another example can be an application which will be compiled for console use only or as an windows application involving two different classes with main methods.
There can only be one entry point in a C# program. If you have more than one class that has a Main method, you must compile your program with the /main compiler option to specify which Main method to use as the entry point.
Compile t2.cs and t3.cs, specifying that the Main method will be found in Test2 like this,
csc t2.cs t3.cs /main:Test2
You can have multiple methods called Main() in different classes. But only one of them is used to start the program. It is just normal method, you can use the other Main's for whatever you wish. (But it is not recommended.)
It would probably be a rare occurrence, but I'd imagine if you had to link to some external code that has a Main() method, then you'd want to tell the compiler to use yours.
Why shouldn't you be able to create multiple classes with a Main method? After all, Main is just the name of the method. If you create a class it's perfectly ok to define a method named Main in it.
When you Using Visual Studio CMD Prompt
then Try to execute as given below:
csc filename.cs /main:classname
where filename is the name of the file where the code is stored and classname is the name of the class containing the Main which we would like to be the entry point.
As in given program there are two class A and B in which each containing A Main Method. We may write as
csc filename.cs /main:A [ for Class A Main Execution ] or,
csc filename.cs /main:B [ for Class B Main Execution ]