First of all, your "-cli" parameter would be just a bad name, because all .NET assemblies are always CLI, console, WPF, and all other application types, even mixed mode (managed + unmanaged).
Now, some background. The problem is that the console presence is something specified during compilation, not during run time. All compilers has such option in the command line, and in the project file, this is prescribed "Output type" in project properties. If you specify "Windows Application" console is not shown, and if you specify "Console Application", the console is show. Unfortunately, this is misleading, so way to many developers do not understand what really happens. A Windows application can be a console application. You you develop a WPF application and use the option "Console Application" at any time, your application will remain WPF application, and
the console will be shown, additionally. "Console Application" does not mean "not Windows".
Moreover, if you develop non-console application, console is not shown, but it still exists as the API
System.Console
. You still can write in such console, but it's just not shown.
So, what to do with that? You can show both, but the only problematic thing is to remove console which is already created, due to the compilation option. By the way, it's not a problem to remove a WPF window and all related code. For this, you need to write the WPF the
entry point with the
Application
explicitly. Normally, it's hidden, but you can find the sample code in your auto-generated code. When you get it, remove "app" nodes from the project and write normal, not auto-generated code with the explicit entry point (
Main
). Of course, for your purpose, you would need to create the instance of
Application
and run it under
if
block, depending of command line.
So, this part is easy. But in the opposite option, how to remove the console. This is such a bad thing, that I would not recommend you to do so at all. I really don't know a good method (even though it might exist, but I doubt it). But using some "dirty" method is easy. For example, you can remove or hide the Windows using Windows API:
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/ea8b0fd5-a660-46f9-9dcb-d525cc22dcbd[
^].
I call this method "dirty", because it is too much Windows-specific. This way, you badly hurt potential platform compatibility of your code. Besides, finding a window by name… not reliable thing. However, this part can be fixed. In better code, you could use
GetConsoleWindow
, which would give you your console window, the one of the calling process. And then hide it. Please see:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683175%28v=vs.85%29.aspx[
^].
The P/Invoke of that will be:
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
const int SW_HIDE = 0;
const int SW_SHOW = 5;
So, this is already a solution, as I say, dirty, but only due to the need for P/Invoke, not just the pure .NET code.
So, I still invite you to think about a work-around. If you need just one application, you still can have it. As I say, develop two separate tiny applications based on big shared code base, one WPF, another one console. Name them differently, not *.EXE, to avoid running them by accident. Create another, third application with the command line. Depending on command line, execute one of those two using
System.Diagnostics.Process.Start
. Also not very elegant, but this is a clear .NET solution without P/Invoke. This is another solution which will work.
Now, a very fancy variant of the previous solution. Create two separate assemblies the way I described above. In the host application (third one), create a separate Application Domain and execute your application there.
So, that's all you can do, to best of my knowledge. What else? Yes, for command line parsing, you can use my easy-to-use library:
Enumeration-based Command Line Utility[
^].
—SA