What common routines do you put in your Program.cs for C#
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)
{
开发者_JS百科 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.
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
精彩评论