I have a winforms application. I would like to run the .exe from the commandline and redirect the output from one of the output textboxes to the commandline. I don't want to launch the winform application just run the logic in the background.
I tried the advice from this thread
C# application both GUI and commandline
but I didn't see any of my console.writeline messages in the command line in cmd.exe when I ran the application via the cmd.exe. Can anyone guide me as to what I might be doing wrong?
I have an if statement that did this logic:
if(args.Length >0)
{
Console.writeline("this has arguments");
new Mainform();
}
else
{
Application.EnableVisualStyles();
Application.Run(new MainForm());
}
The else part still works. But nothing happens in the if part either using the cmd.exe to run the application or when I use the properties ->debug->command line arguments and give it arguments to run while debugging it. I have no idea what I am doing wrong.
I think you created your Windows Forms project and pasted the code? If so, it couldn't work. You have to create your Console project and here is the code I've tested, works like a charm except that when the Form is shown (GUI mode) the Console is still there, closing that Console will also close your Form:
class Program
{
static void Main(string[] args)
{
if (args.Length == 0)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else //Process command lines
{
Console.WriteLine("Please enter some command.");
string cmd = Console.ReadLine();
Console.WriteLine("You entered: " + cmd);
}
}
}
Because the Console project doesn't add reference to System.Windows.Forms.dll automatically for you, so you have to do that manually to be able to create your form in that Console project. The point is that you applied the code in a Winforms project while it should be in a Console project. There is only a way I know which can show a Console window in a winforms application is running the cmd.exe but that will show a new Console window than the existing one which you are using to run your application.
Related
So, I've written an import/export function on my application, and I have set a file extension associated with my application. When exporting reminders, it creates a .remindme file. This can be opened, and it is caught in my program.cs like this
[STAThread]
[HandleProcessCorruptedStateExceptions]
static void Main(string[] args)
{
using (Mutex mutex = new Mutex(false, "Global\\" + "RemindMe"))
{
if (!mutex.WaitOne(0, false))
{
if (args.Length > 0)
{//The user double-clicked an .remindme file while remindme is running!
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Import(args[0]));
}
//one instance of remindme already running
return;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
Application.Run(new Form1());
}
}
I tried making an new instance of Import(a windows-form) here, and doing Import.Show() , but that doesn't work. I've searched all over the place, and the only thing I found is by using Application.Run() on the form. This does indeed launch it, but it creates another instance of my application. This carries problems with it, including not being able to use the database.
When I double-click the .remindme file while the application is running, using a second Application.Run() the form successfully launches.
But, when I press yes(attempts to insert data into the database) it throws an EntityException
full stacktrace on pastebin
After some digging I found that I can't use two instances using the same SQLite database. This new form counts as a new instance, because I used Application.Run
So, in conclusion what I'm looking for is a way to launch a new form from program.cs (because that's where I catch the double-click on a .remindme file)
After a lot of searching, i came to a solution of sending a windows process message, and it works well!
I got it working using the example here
On Visual Studio, the C# Console application keeps on terminating when I try to run a program. I tested this by just writing Hello World, shown here:
(screenshot of what I wrote)
When I run it, the command prompt window appears for a second, then immediately closes. Is there a way to fix this?
When a console application runs it executes the code and exits, console applications do not have a message loop to keep them alive, it is the same as creating a batch file and double clicking it, the command window will open and then close when execution finishes. If you want then console window to hang around afterwards then you need to use Console.ReadLine(); which will wait for user input before closing (i.e. pressing Enter).
You code (which should be in your question) simply outputs some text to the console and then exits.
Suggested reading Creating a Console Application
class Program
{
static void Main (string[] args)
{
Console.WriteLine("Hello World");
Console.ReadLine();
}
}
The application is not crashing, it runs and then exits. If you want read the output after it's done you can use Console.ReadLine();
using System;
namespace Hello_World
{
class Program
{
static void Main (string[] args)
{
Console.WriteLine("Hello World");
Console.ReadKey();
}
}
}
The issue is not crashing really but that all the instructions are executed then the program exits. If you desire to pause, you could insert the statement:
Console.ReadKey();
which will wait for you to type a key to exit.
I want to change a WinForms application that way, so it will run without UI with console output if it is called with a command line argument. Therefore I changed the application type to "Console Application" and wrote something like:
my code snippet:
....
[DllImport("kernel32.dll")]
static extern bool FreeConsole();
[STAThread]
static void Main(string[] args)
{
if (args.Length == 0)
{
FreeConsole();
Application.Run(new MyForm());
}
else
Console.WriteLine("Console party");
.....
In debug mode in VS I can see the DOS box popping up and hiding. If I do so via console, the command line keeps attached to the process and is not responding until I've closed the MyForm window. Calling the application with an argument, brings the "Console party" up.
The return value of FreeConsole is true and GetLastError is not telling any error code.
Does anybody knows how to detach the process from the cmd.exe process?
Brainstorming with a colleague brings me to try another way. I've set the application type back to Windows Application and did the following:
...
[DllImport("kernel32.dll")]
static extern bool AttachConsole(int input);
static void Main(string[] args)
{
if (args.Length == 0)
{
Application.Run(new MyForm());
}
else if (args.Length == 1)
{
AttachConsole(-1);
Console.WriteLine("Console party");
...
What happens now is, if I run it from cmd.exe box, the application takes the console(stdin,stdou,stderr) from the parent process and writes to it. When using it without arguments, the console window will not pop up.
I am thinking about, what is better way. Having the parent process dealing with the stdin,stdout and stderr handles or let the application hijack it from its parent!?
In my application, I have an option to start the application when Windows is started. That works great. I also have it so that, when minimized, the application is minimized to the system tray. Is there a way that I could have it be automatically minimized when started up at the same time as Windows? The only way I could think of, is to retrieve the amount of time that they system has been on and use that data to decide whether the machine had recently started. Obviously there are a lot of flaws with that theory. Anybody have any other ideas as to how this could be done?
Implement a command line switch in your program that causes your program to minimize to the tray. When you start the program with Windows startup, just include the switch.
http://msdn.microsoft.com/en-us/library/acy3edy3.aspx
In your Form "Properties" in WindowState change to "Minimized", or in code:
//After this:
InitializeComponent();
//Place this line:
WindowState = FormWindowState.Minimized;
Hope this help!
Use a command line argument, e.g. /startminimised. In your app check for the presence of this switch (using Environment.GetCommandLineArgs) when the app starts, and automatically minimise if the switch is present.
Then in your "run on startup" option, ensure that the app is started with this switch e.g. set the Run registry key or Startup group shortcut to myapp.exe /startminimised.
When the user runs your app, however, they won't (normally!) specify the switch, so the app will appear as a window.
You can call your program with a parameter, for example "-minimized" and then handle that parameter in your program:
In your program.cs, handle the parameter, and then pass that parameter to Form1:
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (args.Length != 0){
Application.Run(new Form1(args[0]));
}
else
{
Application.Run(new Form1("normalState"));
}
}
In your Form1.cs, you can call a function with the passed parameter and minimize the app:
public Form1(string parameter)
{
InitializeComponent();
SetStartup(); //This function will set your app in the registry to run on startup. I'll explain this function below.
MinimizeApp(parameter);
}
For example, with this function i used, if you start the application with the -minimized parameter, then it will start minimized, a notifyicon pops up in the taskbar and a bubble saying the app is started and running in the background.
public void MinimizeApp(string parameter)
{
if (parameter == "-minimized")
{
this.WindowState = FormWindowState.Minimized;
notifyIcon1.Visible = true;
notifyIcon1.BalloonTipText = "Program is started and running in the background...";
notifyIcon1.ShowBalloonTip(500);
Hide();
}
}
The SetStartup function puts your program into the registry, so it'll run on startup.
private void SetStartup(){
Microsoft.Win32.RegistryKey key;
key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");
key.SetValue(AppName, Application.ExecutablePath.ToString());
string ApplicationPath = "\"" + Application.ExecutablePath.ToString() + "\" -minimized";
key.SetValue("MyApplicationName", ApplicationPath);
key.Close();
}
Right now, when you start your program with -minimized parameter, for example: "c:/programs/app.exe" -minimized then it will start minimized, and when you restart your computer, it also starts automatically minimized.
How do I create, execute and control a winform from within a console application?
The easiest option is to start a windows forms project, then change the output-type to Console Application. Alternatively, just add a reference to System.Windows.Forms.dll, and start coding:
using System.Windows.Forms;
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.Run(new Form()); // or whatever
}
The important bit is the [STAThread] on your Main() method, required for full COM support.
I recently wanted to do this and found that I was not happy with any of the answers here.
If you follow Marc's advice and set the output-type to Console Application there are two problems:
1) If you launch the application from Explorer, you get an annoying console window behind your Form which doesn't go away until your program exits. We can mitigate this problem by calling FreeConsole prior to showing the GUI (Application.Run). The annoyance here is that the console window still appears. It immediately goes away, but is there for a moment none-the-less.
2) If you launch it from a console, and display a GUI, the console is blocked until the GUI exits. This is because the console (cmd.exe) thinks it should launch Console apps synchronously and Windows apps asynchronously (the unix equivalent of "myprocess &").
If you leave the output-type as Windows Application, but correctly call AttachConsole, you don't get a second console window when invoked from a console and you don't get the unnecessary console when invoked from Explorer. The correct way to call AttachConsole is to pass -1 to it. This causes our process to attach to the console of our parent process (the console window that launched us).
However, this has two different problems:
1) Because the console launches Windows apps in the background, it immediately displays the prompt and allows further input. On the one hand this is good news, the console is not blocked on your GUI app, but in the case where you want to dump output to the console and never show the GUI, your program's output comes after the prompt and no new prompt is displayed when you're done. This looks a bit confusing, not to mention that your "console app" is running in the background and the user is free to execute other commands while it's running.
2) Stream redirection gets messed up as well, e.g. "myapp some parameters > somefile" fails to redirect. The stream redirection problem requires a significant amount of p/Invoke to fixup the standard handles, but it is solvable.
After many hours of hunting and experimenting, I've come to the conclusion that there is no way to do this perfectly. You simply cannot get all the benefits of both console and window without any side effects. It's a matter of picking which side effects are least annoying for your application's purposes.
Here is the best method that I've found:
First, set your projects output type to "Windows Application", then P/Invoke AllocConsole to create a console window.
internal static class NativeMethods
{
[DllImport("kernel32.dll")]
internal static extern Boolean AllocConsole();
}
static class Program
{
static void Main(string[] args) {
if (args.Length == 0) {
// run as windows app
Application.EnableVisualStyles();
Application.Run(new Form1());
} else {
// run as console app
NativeMethods.AllocConsole();
Console.WriteLine("Hello World");
Console.ReadLine();
}
}
}
It´s very simple to do:
Just add following attribute and code to your Main-method:
[STAThread]
void Main(string[] args])
{
Application.EnableVisualStyles();
//Do some stuff...
while(!Exit)
{
Application.DoEvents(); //Now if you call "form.Show()" your form won´t be frozen
//Do your stuff
}
}
Now you´re fully able to show WinForms :)
You can create a winform project in VS2005/ VS2008 and then change its properties to be a command line application. It can then be started from the command line, but will still open a winform.
All the above answers are great help, but I thought to add some more tips for the absolute beginner.
So, you want to do something with Windows Forms, in a Console Application:
Add a reference to System.Windows.Forms.dll in your Console application project in Solution Explorer. (Right Click on Solution-name->add->Reference...)
Specify the name space in code: using System.Windows.Forms;
Declare the needed properties in your class for the controls you wish to add to the form.
e.g. int Left { get; set; } // need to specify the LEFT position of the button on the Form
And then add the following code snippet in Main():
static void Main(string[] args)
{
Application.EnableVisualStyles();
Form frm = new Form(); // create aForm object
Button btn = new Button()
{
Left = 120,
Width = 130,
Height = 30,
Top = 150,
Text = "Biju Joseph, Redmond, WA"
};
//… more code
frm.Controls.Add(btn); // add button to the Form
// …. add more code here as needed
frm.ShowDialog(); // a modal dialog
}
This worked for my needs...
Task mytask = Task.Run(() =>
{
MyForm form = new MyForm();
form.ShowDialog();
});
This starts the from in a new thread and does not release the thread until the form is closed. Task is in .Net 4 and later.
You should be able to use the Application class in the same way as Winform apps do. Probably the easiest way to start a new project is to do what Marc suggested: create a new Winform project, and then change it in the options to a console application
Its totally depends upon your choice, that how you are implementing.
a. Attached process , ex: input on form and print on console
b. Independent process, ex: start a timer, don't close even if console exit.
for a,
Application.Run(new Form1());
//or -------------
Form1 f = new Form1();
f.ShowDialog();
for b,
Use thread, or task anything,
How to open win form independently?
If you want to escape from Form Freeze and use editing (like text for a button) use this code
Form form = new Form();
Form.Button.Text = "randomText";
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.Run(form);