I'm interested in any common routine/procedures/methods that you might use in you Program.cs when creating a .NET project. For instance I commonly use the following code in my desktop applications to allow easy upgrades, single instance execution and friendly and simple reporting of uncaught system application errors.
using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
namespace NameoftheAssembly
{
internal static class Program
{
/// <summary>
/// The main entry point for the application. Modified to check for another running instance on the same computer and to catch and report any errors not explicitly checked for.
/// </summary>
[STAThread]
private static void Main()
{
//for upgrading and installing newer versions
string[] arguments = Environment.GetCommandLineArgs();
if (arguments.GetUpperBound(0) > 0)
{
foreach (string argument in arguments)
{
if (argument.Split('=')[0].ToLower().Equals("/u"))
{
string guid = argument.Split('=')[1];
string path = Environment.GetFolderPath(Environment.SpecialFolder.System);
var si = new ProcessStartInfo(path + "\\msiexec.exe", "/x" + guid);
Process.Start(si);
Application.Exit();
}
}
//end of upgrade
}
else
{
bool onlyInstance = false;
var mutex = new Mutex(true, Application.ProductName, out onlyInstance);
if (!onlyInstance)
{
MessageBox.Show("Another copy of this running");
return;
}
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Application.ThreadException += ApplicationThreadException;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
try
{
var ex = (Exception) e.ExceptionObject;
MessageBox.Show("Whoops! Please contact the developers with the following"
+ " information:\n\n" + ex.Message + ex.StackTrace,
" Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
catch (Exception)
{
//do nothing - Another Exception! Wow not a good thing.
}
finally
{
Application.Exit();
}
}
public static void ApplicationThreadException(object sender, ThreadExceptionEventArgs e)
{
try
{
MessageBox.Show("Whoops! Please contact the developers with the following"
+ " information:\n\n" + e.Exception.Message + e.Exception.StackTrace,
" Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
catch (Exception)
{
//do nothing - Another Exception! Wow not a good thing.
}
}
}
}
I find these routines to be very helpful. What methods have you found helpful in Program.cs?
I try to avoid putting anything significant in the Program.cs file. Anything that I write for a simple Console app could someday be moved to a class library, and so I'll build a separate class for the actual program logic.
That said, there is some generic code that I use over and over. The main thing is using the Trace class to handle the console output, so I don't have to change any important code in the app itself to redirect things to a log file or somewhere else later when the inevitable transition to class library or gui app occurs:
using System;
using System.Diagnostics;
public static void Main(string[] args)
{
Trace.Listeners.Add(new ConsoleTraceListener());
Trace.WriteLine("Program Started - " + DateTime.Now.ToString());Trace.WriteLine("");
//Call into a separate class or method for the actual program logic
DoSomething(); //I'll use Trace for output in here rather than Console
Trace.WriteLine("");Trace.WriteLine("Program Finished - " + DateTime.Now.ToString());
Console.Write("Press a key to exit...");
Console.ReadKey(true);
Console.WriteLine();
}
For argument parsing, the Novell Options class is the best I've seen (via "Best way to parse command line arguments in C#"). I've also adapted it for interactive console applications, for programs that don't just run and quit.
Here's an example of the Options class:
static void Main(string[] args)
{
var p = new new OptionSet ()
.Add ("v|verbose", v=> setVerbose())
.Add ("h|?|help", v=> showHelp())
.Add ("n|name=", v=> showName(v));
p.Parse (args);
}
I usually have a very small Main function that calls another function (e.g. Start) - that way, if some assembly is missing and Start cannot be JITted, I can catch the TypeLoadException and display a human-readable error message.
We usually use main for basic command-line parsing, crash handling setup, license checking, and creation of main form (assuming it's a windows application and not a console application).
However, most of that functionality is handled by other objects that main just instantiates and calls.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With