command line to make winforms run without UI - c#

i am not really sure how to ask this question properly. so apologies in advance.
but it's basically around how to make an existing app, with a UI, run as a scheduled task with no UI.
background..
I have a winforms app written in vs2012 with 2 forms.
the first form is the login, straight forward, but currently expects user interaction of their username and password.
the second is the main form. which does the main work when you hit the "start" button.
what I am trying to achieve it is for me to send it some command line parameters that would run it without any ui as a scheduled task.
so, I'm guessing, I need get rid of needing the user to input login details. and somehow trigger the "start download" button and make it invisible.
I've worked out how to send command line parameters and can see how to get the software to do something different if it hears /silent but how do I hide the forms?
I'm lost.
any help would be much appreciated!

C# still has a Main() function. In a standard winforms solution, all it does is create your Form1 (or whatever it gets renamed to), and start the application event queue with that form.
For example, it should look something like:
public static void Main()
{
Application.Run(new Form1());
}
Modify this function. If you see command line arguments, do whatever you have to. If there are none, let it do its normal magic with the form. When you're done, it would be something like:
public static void Main(string[] args)
{
if (args.Length > 0) {
// log in
// do all the necessary stuff
} else {
Application.Run(new Form1());
}
}

Modify the Main method which should be the entry point to your application. If there are any arguments, you don't need to instantiate and show any forms, just run the code to do your job without UI.
[STAThread]
static void Main(string[] args)
{
if (args.Length > 0)
{
// silent mode - you don't need to instantiate any forms
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}

find static Main method in your solution. Inside that method you will have Application.Run(new Form()) or (form.Show() or ShowDialog()). So they key is to pass a parameter that will tell you now to call this method (Show method on forms)
The key is to have your business logic in a class that is independent of you form and use this class when you want to have GUI or when you want scheduled task

I answered this just other day -- on this question
Pay attention to the difference between code blocks -- the first block runs formless, the 2nd block is standard.
if (ABCFile > 0)
{
var me = new MainForm(); // instantiate the form
me.NoGui(ABCFile); // call the alternate entry point
Environment.Exit(0);
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}

Related

Can't End Execution of a Form Project if I Run Forms From a Class

I am developing an application that requires an initial setup phase (to be run only once) and which then executes the actual program. I did this by instantiating a class in the main file (Program.cs). This class checks if the user has already made the setup and on the basis of this it executes specific Forms or not. The problem is that once the "FormGridScheduler" form is closed with the classic X button, the program does not terminate its execution but it remains running in the background. In the form I create threads but during the "Form_Closing" event I go to abort all the threads, so there should be nothing left in execution. Anyone have any ideas on how to fix this?
This is the "Program.cs" file from which I initialize the "FormManager" class from which, subsequently, I execute the forms
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//I start the form manager
FormManager formManager = new FormManager();
}
}
This is the FormManager class
class FormManager {
public FormManager() {
//I check if the user has already set up the program or not
if (!Settings.Default.SetupDone) {
//If you haven't done the setup yet, I start the corresponding forms
Application.Run(new FormSetup());
//I check if the user has closed the setup screen before completing it
if (Settings.Default.SetupDone) {
//I execute the main form
Application.Run(new FormGridScheduler());
}
} else {
//I execute the main form
Application.Run(new FormGridScheduler());
}
}
}
Thanks for your attention and patience. Any suggestion is welcome!

Where do I put a piece of code that I want to run right before a multi-form Windows form app exits? (no matter how the program exits)

I have a C# application that consists of multiple forms, and there is no particular one which will always be closed last.
Where should I put a piece of code (i.e. dumping some information to a file) to ensure that no matter how the program exits, this happens just before the program closes?
Well one option would be to call a method to do what ever you want right before the main method exits.
ETA:
by default the main method is in the program.cs file.
here is an example of what I mean
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
//** this code will not be reached until form1 closes.
bool blah = true;
doWhatEver(blah);
}

C# hybrid cli and win form app

I have been researching how to create a hybrid winform and CLI app... I started out my app as Winforms, now I am adding CLI to it... It seems to work but has a few issues I want to figure out how to fix and have not been able to do so , probably due to my lack of experience with C#.
If i have output type in VS set to "windows application", and use the code below i am able to run the winform portion for GUI, and also from command line am able to give it parameters and it works, well at least it outputs consolewrites i have coded in, i have a seperate c# class file that has my main code so it is seperate from winform GUI and my eventual cli code, they both will just feed user input to this other "main" c# class.. anyway here is the code.
[STAThreadAttribute]
[DllImport("kernel32.dll")]
static extern bool AttachConsole(int dwProcessId);
private const int ATTACH_PARENT_PROCESS = -1;
static void Main(string[] args)
{
if (args.Length == 0)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new form_Main());
}
else
{
AttachConsole(ATTACH_PARENT_PROCESS);
cli_main cli = new cli_main();
cli.start_cli(args);
}
}
well it works in gui, i can access my menus and create different win forms, moment i click a button to perform an action i get the following exception:
System.Threading.ThreadStateException was unhandled by user code
Message=Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process.
if i then change the output type to "console application", it works perfectly in all manners in cli and GUI, BUT when it opens the winform/GUI portion i get this ugly CMD window that will not go away.. here is the code i used, basically just what i started with before i added the above code.
static void Main(string[] args)
{
if (args.Length == 0)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new form_Main());
}
else
{
cli_main cli = new cli_main();
cli.start_cli(args);
}
}
again with my lack of knowledge on C# i am hoping someone can point me to a solution . I would prefer to keep the app as output "console application" and find a way to hide the console that is opened when i start the winform/gui portion..?? thanks in advance.
Did you do what it said in the error message?
Ensure that your Main function has STAThreadAttribute marked on it
In the code you pasted, the STAThread attribute is not marking the Main method, it is marking the AttachConsole external function. Move that to where it ought to be and you shouldn't have any problems.
If your application is a console application, it will get a console window automatically if there isn't already one attached. That's the point of making it a console application. You can use FindWindow and ShowWindow(SW_HIDE) to hide it at runtime but it will still flash on-screen briefly.
If you plan to start your application from an existing console window most of the time, you should keep it as a console application, since it will inherit the parent process's console window by default. If you plan to start your application from a UI shortcut or from other non-console processes, you should probably make it a Windows application and allocate the console as needed.
Thanks for all, but some changes for previous pattern
It works so:
static void Main(string[] args)
{
// Test pattern
args = new string[] { "-flag1", "value1", "-flag2", "value2", "-flag3", "value3" };
if (args.Length == 0)
MainWinApp();
else
MainCLI(args);
}
[STAThread]
static MainWinApp()
{
// Your code for start GUI application
}
[STAThreadAttribute]
static void MainCLI(string[] args)
{
// Your code for CLI application
}

C# Application.Run without Form

Is it possible to call Application.Run, but to not pass a form parameter, or is there an alternative if there’s no form to call?
The Run method doesn’t seem to have any overloads that don’t accept a form.
For example, if I wanted to instantiate a class first, and then have that call the form, is there way to do the equivalent of:
Application.Run(myClass);
Just to clarify, I do still want the functionality that .Run() provides. That is, establish a loop to keep the application running, but instead of tracking a form, track a class or other object.
This is relating to the compact framework initially. I assume that's why the Run method doesn't have the overload I was looking for.
The Run method doesn’t seem to have any overloads that don’t accept a form.
Uh... http://msdn.microsoft.com/en-us/library/ms157900.aspx
Application.Run Method
Begins running a standard application message loop on the current thread, without a form.
public static void Run()
I'm not clear whether you want to do:
You want to load your form somewhere else other than the Main()
Or Run a console or service application with no UI.
For (1):
static void main()
{
//Your program starts running here<<<
//Do some stuff...
FormRunner a = new FormRunner();
a.RunForm();
} // << And ends here
class FormRunner {
public void RunForm() {
Application.Run(new Form());
}
//You could call which ever form you want from here?
} // << And ends here
What you need to know is your program starts from the first line of the main and ends at the last. However, when you call Application.Run(FORM) it loads up a windows message loop for that form. Its a special loop that keeps the program still in the main and waits for events (they're called Windows Messages in win32 API)
And so the program does not end until the user clicks the close button. When this happens, thats when your program actually will return from its Main.
(2) So now if you just want a pure console app with no forms:
static void main()
{
AcceptInputs()
DrawScreen()
//Do something else.
//Make sure your flow stays within the main
} // << Once you come here you're done.
void AcceptInputs()
{
while(true) {
//Keep accepting input
break; // Call break when you're done. You'll be back in the main
}
}
I hope that helped.
You can use the overload of Application.Run that accepts an application context as its only parameter. An ApplicationContext is basically just a class that you can inherit from and add any functionality you like. See the example in the link for more information.
using System;
using System.Windows.Forms;
static class Program
[STAThread]
static void Main() {
Application.Run(new myClass());
}
internal class myClass : ApplicationContext {
public myClass() {
Application.Run(new myWindow());
}
}
}
The problem here, though, is that something will have to call this instance of myClass and tell it to exit or else the program will just keep running even after all forms are closed. And calling ExitThread() in the constructor is ignored.

How do I need to modify my WinForms app to also run in the console?

I have a .NET WinForms app written in C#. In order to support batch operations, I'd now like to make the app able to run in the console.
Is it possible to have an app that detects on startup whether it is running in the console or not?
What modifications do I need to make in order to achieve this behaviour?
You should have a Program.cs file in your solution, this file contains a:
static void Main()
{
}
You'll notice in this method there is something like:
Application.Run(new Form1());
This is where your form is actually launched, so what you can do is modify your Main() to something like this:
static void Main(string[] args)
{
if(args.Length < 1)
{
Application.Run(new Form1());
return;
}
else
{
// Handle your command line arguments and do work
}
}
So if your program is invoked with no command line arguments, the windows form pops open and does its thing. Otherwise you do what you need to do via the command line and exit without ever showing a form.
You can allocate a Console for your WinForms app using the AllocConsole function. You can find more information about how to call this from C# on it's pinvoke page.
However, this will not make it a true console app and I've heard that there are some limitations, however, it might work depending on your exact needs.
You could use a main method in program.cs and detect whether command line parameters are passed in, if they are do batch processing, if not show the GUI.
public static void Main(string[] args)
{
if (args.count > 0) {
//batch
} else {
//gui
}
}

Categories