Both CLI and GUI application - c#

I am writing an application that has both CLI and GUI.
I read most questions and articles regarding it, and found highly usefull this question:
Can one executable be both a console and GUI application?
My final code looks like:
if (args.Length > 0)
{
//console code
}
else
{
FreeConsole();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form());
}
This works great when running the .exe by double click, or when debugging, or from console with arguments.
However, when running it from the console with no arguments, the GUI is opened, like I intended, but the console is stuck waiting for the GUI to close.
This is uncharacteristic GUI and console behavior. the console usually launch the GUI and not wait to its exit, but for new commands.
Is there is a way to avoid it?

The accepted answer in the question you linked to contains this passage:
Junfeng's second technique is what ildasm uses. He quotes the process
that ildasm's author went through when making it run in both modes.
Ultimately, here's what the it does:
The program is marked as a console-mode binary, so it always starts
out with a console. This allows input and output redirection to work
as normal. If the program has no console-mode command-line parameters,
it re-launches itself. It's not enough to simply call FreeConsole to
make the first instance cease to be a console program. That's because
the process that started the program, cmd.exe, "knows" that it started
a console-mode program and is waiting for the program to stop running.
Calling FreeConsole would make ildasm stop using the console, but it
wouldn't make the parent process start using the console.
To me it looks like the headache of having a binary trying to switch between the console subsystem and GUI subsystem (which really isn't allowed) is more effort than it's worth.
One approach would be to have a separate GUI application .exe. Whenever the console app is started without parameters it launches the GUI app and closes itself.
To prevent code duplication this probably requires all the actual logic of the application to be put in a separate class library.

THe usual way to do this is to abstract presentation from logic and then have two exes, one CLI, one GUI, not to have one that could be either. Going down that route leaves you with some sort of awful compromise with the benefits of neither approach.
GUI with command line options is not a CLI app, it's a GUI with an invisble / short lived window.

Maybe is not an answer to your direct question, but with this dual solution you are asking for trouble :) This is a hack that will work in some cases, but in other not.
Proper solution would be exclude functionality and application logic in separate class library and then from both console and GUI application call that "engine". Put all that three projects in one Visual Studio solution. All functionality and vast majority of code should be in that class library, GUI and console projects would only deal with that specific aspects that depends on environment (eg. button click event would only be in GUI app etc.)

This looks correct. You launch a command that only returns when the application is stopped.
If you don't want to wait for it to return, start it in a new thread. (ThreadPool, Thread, Task, async/await in C#5.0 => pick your favorite).

Need to start a gui application from console without stuck the console? From the command prompt type:
start "[title not necessary for gui exe]" "full path to .exe"
See here

Best approach to write application working in GUI/CLI/CUI/Network mode is using libgreattao.
Search for it on sourceforge.net.
Libgreattao decouples business logic and communication mechanism, so you can put libgreattao related code everywhere in your program.

Related

C# gracefully close a separate application that has no UI

I use the c# process class to open a separate application that has no GUI. it is s a c++ project that I use the Process.Kill() on to end it. The problem is this doesn't give it a chance to finish its actions. Process.Close() just releases the object in my main app and and leaves the separate application running.
Whats the best way to make this process close gracefully?
In the past I needed to start a non-gui C# tool from a GUI C# tool, both of which I had written. I used the standard input/output streams to communicate between both tools.
You could make your C++ tool listen on its stdin for a command that indicates the tool should quit gracefully. Then, in your C# application, send the quit command, wait for a reasonable amount of time and if the tool hasn't ended by then, kill it.
I'm sorry that my C++ is not good enough to give you an example for the C++ side, but the following lines are used in my C# project to tell the external process to end:
m_consoleProcess.StandardInput.WriteLine("QUIT");
m_consoleProcess.WaitForExit(10000);
if (!m_consoleProcess.HasExited)
{
m_consoleProcess.Kill();
}
If you need to manage separate external processes, of course you need to store one Process instance for each of them and you have to handle the case that the external process was ended before your application should quit.

How does Ninject 3 affect object lifetime?

Before I had refactored my project for DI with Ninject, I had a simple test class with a simple method:
public void TestImport()
{
var functionality = new ImportFunctionality();
functionality.Execute();
}
When I ran this "app" (merely a sandbox WPF client app for integration testing my library), I had the "main" window showing up and clicking a button on that window called this TestImport method, which executed and then I could test and debug my code, and when then main window was closed, the app died right there and VS would exit debug mode. Normal stuff.
Then I refactored the whole thing and implemented dependency injection with Ninject, factories and interfaces all over the code; the TestImport method now looks like this:
public void TestImport()
{
using (var kernel = new StandardKernel())
{
kernel.Load<SecurityNinjectModule>();
kernel.Load<HelpersNinjectModule>();
kernel.Load<ImportFunctionalityNinjectModule>();
var functionality = kernel.Get<IImportFunctionality>();
functionality.Execute();
}
}
Now when I run the WPF sandbox/test app, everything works and that's great, except when the "main" window gets closed, the application does not exit anymore and Visual Studio remains in debug mode. I added the call to Dispose() in the hope to fix it, but no luck; wrapping it in a using block doesn't fix it either.
If I run the sandbox without clicking the button to run the TestImport method, and then close the main window, the app shuts down properly.
This leads me to the Ninject kernel object. Could it be holding on to its resources somehow despite the Dispose() call? Then how do I properly shut down an application that's running Ninject 3.0?
EDIT
If I bring up the debug/windows/threads window, I see all instantiated threads either sleeping or "in a sleep, wait, or join", if not "not available"; a thread by the name of .NET System Events is sleeping, waiting or joining; the main thread is "managed to native transition" as well as a thread called vshost.RunParkingWindow - and this is where I got to Why won't my WPF application close properly after it displays a WinForms dialog?. The answer seems to work given it is accepted, but as #BahriGungor says "Using System.Environment.Exit is a lot like using dynamite to make a door because you didn't want to follow the exit signs". And it doesn't say why this is happening.
The interesting thing is, it doesn't happen consistently: sometimes I can break and step through code and when I "F5" to resume, and then close the main window, it does shut down properly. What's going on?
EDIT 2
The functionality brings up a FileDialog, and if that dialog doesn't return an Excel workbook's filename, the import window doesn't show up. I've narrowed it down to this:
If the import view is shown, no matter how it is closed after closing the main app window VS will properly exit debug mode.
If the import view is not shown (i.e. the FileDialog doesn't return anything editable) then VS will not exit debug mode after closing the main app window.
Your DI should have a composition root where 99% of your DI code lives. Factories should be the 1% case of dependency injection. For WPF that is the onStartup method.
Also I don't see anywhere in your code where you specify a lifetime management part of DI. If you aren't specifying a lifetime management aka Bind<Samurai>().ToSelf().InSingletonScope(); then you may be getting no lifetime management and no disposal. Here's the information on scopes for ninject.
You say you added a call to dispose somewhere along the way, but if you have event listeners set up without weak references there can be a memory leak leading to a lack of disposal.
Finally did you follow the other answer on your linked System.Environment.Exit question?
Check the Application.Current.Windows collection in the debugger to find the offending window. https://stackoverflow.com/a/7349650/57883
Have you tried using other win forms dialogs or just the one to see if it is reproducable?

What isn't available to me before calling Application.Run() in a standard WinForms application?

I want to do some initialization of various things at runtime of my WinForms application. I'm looking specifically at the Program.cs file that every WinForm application has. In it, I see:
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frmMain());
}
I know that this is what starts up the application and creates the initial form (in my case, an instance of frmMain).
Can I not just put my initialization code before Application.Run()? The initialization I need to do is to check a few registry entries, create them if necessary, and connect to a database. Will any feature not be available to my instantiation code if I put it before Application.Run()?
Application.Run() starts message loop for your main thread. SO before that line of code you can do anything except what is dependent on windows messages (click, keyup, ...)
A Windows Forms application starts when the Main method is called. You can implement initialization procedures on the Main function. However, to initialize a Windows Forms application fully and start it routing Windows Forms events, you need to invoke Application.Run.
Read about Application
Yes, no problem, the code in Main() is boilerplate but not cast in stone.
Do keep in mind that any code you run before calling Application.Run() will delay the startup of your user interface. Once that goes over a second or two, give or take, you might want to consider displaying a splash screen so that the user gets some visual feedback that your program got started. Well supported by the .NET framework, check this answer.
One important thing you don't have available before Run is a valid SynchronizationContext.Current. So if you use any kind of event-based asynchronous pattern components, they'll seem to work just fine, but will fire their events on a thread pool thread instead of the GUI thread.
Because of this, any asynchronous startup code that queues completion events to the GUI should be started from an event, not before Run.
As long as you don't need to access anything declared in frmMain you should be OK.
However the MSDN states:
Begins running a standard application message loop on the current thread.
so you won't have access to the message loop.
There is another overload Application.Run(ApplicationContext) that will let you execute code before your form is displayed - this appears to be the way to go.
The example code on this page does some initialisation before showing two forms, so you should be OK with your model.

c# windows service or just normal program? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
windows service vs scheduled task
Windows Service Vs Simple Program
I'm trying to create a program that runs periodically (say every 5 minutes), or have the program running and have it execute the function within it (every 5 minutes).
The program is to obtain data from a database when it's executed and then write this to (for now) say info.txt file (no sensitive stuff is contained in here). each time it writes to the file it should overwrite the existing info within the file.
The program should also be started automatically at windows start up. (thus no need to login on the machine and to execute the .exe [if it's a normal program and not a service])
In between the periods that it executes the program would have nothing to do.
Therefore, should I run this program as a Windows Service, or should I use the Task Scheduler to periodically start the program to do this?
My goal is for this program to run as smooth as possible without clogging up resources. (eg. it shouldn't need more than 5% of the cpu)
I hope my question was clear enough.
I would go with application that is triggered by task scheduler. Only thing that you need to worry about is to run single instance of your application.
You can set task to run under specific user account and to run even if user is not logged on. There are number of events that can trigger task star like "Windows start", "System Idle"...
Other advantage is: If something crashes you can set task scheduler to send you an email or alert you in number of ways. You can control "exit code" of your application and signal to task scheduler what's going on and what to do.
There are a lot of positive features that task scheduler offers but not many people are using them.
I would suggest a Windows Service for this. Might be a good idea to create both and compare what the resource usage is like anyway?
I would actually recommend going for both depending on the requirements of the task you wish to run. I generally build most functionality for scheduled services into a single class library and then wrap it in a console application to start with and for debugging. When satisfied I wrap it in a windows service and forget about it.
Considerations of using a console app:
Make sure you run it under system account if possible or you can put in a specific login under Run as in scheduler. This will ensure an interactive login is not required.
If having 2 instances of it running at the same time is a problem, make sure you name it clearly and check for an instance of it running in your main method and exit if it is. A windows service will avoid this issue.
Considerations of using a window service
Make sure you're educated on thread usage. Windows services will use less resources if managed properly, but can be tricky if it's new to you and end up leaking memory in timer based tasks.
..there's a lot more to consider, but code it right and you can start with one and move to the 2nd when you're confident about it.

c# isBackground Thread is NOT terminating properly

I have one background thread I use for processing separately from the GUI, and everything works fine between the threads. However when I close the application, the program "closes" but does not kill the process. The background thread is keeping the program alive it seems.
I have set "myThreadInstance.IsBackground = true;", and I thought this would require C# to kill it when it is killed.
I am testing this all in Visual Studio (2010, using .NET 4.0), and after the first build, the rest all fail because the exe is still in use so it cannot overwrite it. Looking in task manager, it is there. Killing Visual Studio releases the vbhost process which releases my exe. Killing my exe's process, makes vbhost respawn it in a second or two.
Actually, based on your description and other things you've tried (and their results), I believe the most likely cause is this:
You have another foreground thread in your application, other than the one you're examining.
Try using Application.Exit(0); in the form_closing/form_closed event.
Bug: I think this might be a bug. Look at the comments at the bottom of this MSDN page: http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground.aspx
Also, try using the BackgroundWorker. Here's a good description in the VisualStudio Magazine: http://visualstudiomagazine.com/articles/2007/09/01/simplify-background-threads.aspx
This type of problem usually requires code to figure out. Take your app and trim it down to the bare minimum necessary to show the issue.
However, most likely you are either not signaling the thread to terminate or the thread is such a long running beast that it doesn't ever see the signal.

Categories