tags:

views:

680

answers:

5

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?

+4  A: 

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();
}
Joel Coehoorn
That's a great idea!
Rick
+1  A: 

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.

nikie
+1  A: 

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);
}
Chris S
+1  A: 

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.

Jeff Yates
A: 

The only code I definitely but into every program is my Exception Handler:

At the start:

#If Not Debug Then
        AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf Me.Application_UnhandledException
        AddHandler Application.ThreadException, AddressOf Me.Application_ThreadException
#End If


Private Sub Application_UnhandledException(ByVal sender As Object, ByVal e As System.UnhandledExceptionEventArgs)
    Me.UnhandledExceptionLog(TryCast(e.ExceptionObject, Exception).Message, New StackTrace(TryCast(e.ExceptionObject, Exception), True), e.ExceptionObject)
End Sub
Private Sub Application_ThreadException(ByVal sender As Object, ByVal e As System.Threading.ThreadExceptionEventArgs)
    Me.UnhandledExceptionLog(e.Exception.Source & Environment.NewLine & e.Exception.Message & Environment.NewLine & e.Exception.StackTrace, New StackTrace(e.Exception, True), e.Exception)
End Sub

Public Sub UnhandledExceptionLog(ByVal message As String, ByVal stack As StackTrace, ByVal ex As Object)
    ' write the exception details to a log and inform the user the he screwed something ;) '
End Sub

This will catch every Exception I missed and will write it to a log of my own (asking the client what the error message stated is actually not the wisest thing...).

Bobby

Bobby