static void Main(string[] args)
        {
#if DEBUG
            //System.Diagnostics.Debugger.Launch();
#endif

            try
            {
                st = DateTime.Now;
                Application.SetCompatibleTextRenderingDefault(false);

                Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
                AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

                // handle setting/overriding the culture information (this has to be done early so that installation dialogs are translated)
                SetCulture(Properties.Settings.Default.CultureCode);

                // launch app
                SingleInstanceApplication app = null;
                try
                {
                    app = new SingleInstanceApplication("GrowlForWindows");
                }
                catch (Exception e)
                {
                    HandleUnhandledException(e, "Growl", "Growl is already running under another session on this computer. Only one instance of Growl can run at a time.");
                    return;
                }

                using (app)
                {
                    // register support for data: uris
                    DataWebRequest.Register();

                    // set global (default) proxy info
                    ProxyHelper.SetProxy();

                    Signal signalFlag  = 0;
                    int    signalValue = 0;
                    appIsAlreadyRunning = app.IsAlreadyRunning;

                    // handle protocol-triggered operations
                    if (args != null && args.Length == 1)
                    {
                        string protocolArgument = args[0];
                        Installation.ProtocolHandler handler = new Growl.Installation.ProtocolHandler(appIsAlreadyRunning);
                        signalFlag = handler.Process(protocolArgument, ref queuedNotifications, ref signalValue);

                        // if for some reason we were told to cancel launching the app, lets honor that
                        if (signalFlag == Signal.CancelLaunching)
                        {
                            return;
                        }
                    }

                    // handle command line options
                    try
                    {
                        Dictionary <string, Parameter> parameters = new Dictionary <string, Parameter>();
                        if (args != null)
                        {
                            foreach (string arg in args)
                            {
                                Parameter p = GetParameterValue(arg);
                                if (p.Argument != null)
                                {
                                    parameters.Add(p.Argument, p);
                                }
                            }
                        }

                        // the 'cmd' option is special in that it may require Growl to *not* launch, depending on the current state and command issued.
                        // we handle it here first - if other parameters are also passed, they will be ignored.
                        if (parameters.ContainsKey("/cmd"))
                        {
                            string cmd = parameters["/cmd"].Value.ToLower();
                            // currently supported values: start, stop, show
                            switch (cmd)
                            {
                            case "start":
                                // 1. Growl is not running. Start it (service will start automatically)
                                // 2. Growl is running and started. do nothing
                                // 3. Growl is running and stopped. start it
                                // TODO: this is not complete. i am not sure if i am going to include this ever or not
                                break;

                            case "stop":
                                // 1. Growl is not running. do not launch it
                                // 2. Growl is running and started. stop it but do not close
                                // 3. Growl is running and stopped. do nothing
                                // TODO: this is not complete. i am not sure if i am going to include this ever or not
                                break;

                            case "show":
                                // 1. Growl is not running. Start it and open Settings window
                                // 2. Growl is running. Show Settings window
                                // 3. Growl is running and Settings window is already open. do nothing
                                if (appIsAlreadyRunning)
                                {
                                    signalFlag = signalFlag | Signal.ShowSettings;
                                    signalFlag = signalFlag | Signal.Silent;        // go silent to suppress the 'Growl is running' notification
                                }
                                else
                                {
                                    showSettingsOnLaunch = true;
                                }
                                break;
                            }
                        }

                        if (parameters.ContainsKey("/log"))
                        {
                            string log = parameters["/log"].Value.ToLower();
                            if (log == "true")
                            {
                                loggingEnabled = true;
                            }
                        }
                        bool debugMode = false;
                        if (parameters.ContainsKey("/debug"))
                        {
                            string debug = parameters["/debug"].Value.ToLower();
                            if (debug == "true")
                            {
                                debugMode = true;
                            }
                            Utility.DebugMode = debugMode;
                            if (debugMode)
                            {
                                MessageBox.Show("growl is now in debug mode");
                            }
                        }
                        if (parameters.ContainsKey("/silent"))
                        {
                            string silent = parameters["/silent"].Value.ToLower();
                            if (silent == "true")
                            {
                                silentMode = true;
                            }
                            if (silentMode)
                            {
                                signalFlag = signalFlag | Signal.Silent;
                            }
                        }
                        string listenUrlFile = null;
                        if (parameters.ContainsKey("/listenurl"))
                        {
                            listenUrlFile = parameters["/listenurl"].Value;
                        }
                        else if (args != null && args.Length == 1)
                        {
                            listenUrlFile = args[0];
                        }
                        if (!String.IsNullOrEmpty(listenUrlFile) && System.IO.File.Exists(listenUrlFile))
                        {
                            string filename = String.Format("{0}.ListenUrl", System.IO.Path.GetFileNameWithoutExtension(listenUrlFile));    // we have to do this since Firefox will rename the temp file to file.ListenUrl-X.txt
                            string dest     = System.IO.Path.Combine(Utility.UserSettingFolder, filename);
                            System.IO.File.Copy(listenUrlFile, dest, true);
                            signalFlag = signalFlag | Signal.HandleListenUrl;
                            signalFlag = signalFlag | Signal.Silent;    // go silent to suppress the 'Growl is running' notification
                        }
                    }
                    catch (Exception ex)
                    {
                        // dont fail on bad arguments
                        Utility.WriteDebugInfo("Bad arguments: " + ex.Message);
                    }

                    if (!appIsAlreadyRunning)
                    {
                        program = new Program();
                        program.ProgramRunning += new EventHandler(program_ProgramRunning);
                        program.Run();
                        app.AnotherInstanceStarted += new SingleInstanceApplication.AnotherInstanceStartedEventHandler(app_AnotherInstanceStarted);
                        app.Run(program);
                        app.AnotherInstanceStarted -= new SingleInstanceApplication.AnotherInstanceStartedEventHandler(app_AnotherInstanceStarted);
                        program.ProgramRunning     -= new EventHandler(program_ProgramRunning);
                        program.Dispose();
                        program = null;
                    }
                    else
                    {
                        InternalNotification.SaveToDisk(ref queuedNotifications);
                        app.SignalFirstInstance((int)signalFlag, signalValue);
                    }
                }
                app.Dispose();
                app = null;
            }
            catch (Exception ex)
            {
                HandleUnhandledException(ex);
            }
        }
        static void Main(string[] args)
        {
            #if DEBUG
            //System.Diagnostics.Debugger.Launch();
            #endif

            try
            {
                st = DateTime.Now;
                Application.SetCompatibleTextRenderingDefault(false);

                Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
                AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

                // handle setting/overriding the culture information (this has to be done early so that installation dialogs are translated)
                SetCulture(Properties.Settings.Default.CultureCode);

                // launch app
                SingleInstanceApplication app = null;
                try
                {
                    app = new SingleInstanceApplication("GrowlForWindows");
                }
                catch(Exception e)
                {
                    HandleUnhandledException(e, "Growl", "Growl is already running under another session on this computer. Only one instance of Growl can run at a time.");
                    return;
                }

                using (app)
                {
                    // register support for data: uris
                    DataWebRequest.Register();

                    // set global (default) proxy info
                    ProxyHelper.SetProxy();

                    Signal signalFlag = 0;
                    int signalValue = 0;
                    appIsAlreadyRunning = app.IsAlreadyRunning;

                    // handle protocol-triggered operations
                    if (args != null && args.Length == 1)
                    {
                        string protocolArgument = args[0];
                        Installation.ProtocolHandler handler = new Growl.Installation.ProtocolHandler(appIsAlreadyRunning);
                        signalFlag = handler.Process(protocolArgument, ref queuedNotifications, ref signalValue);

                        // if for some reason we were told to cancel launching the app, lets honor that
                        if (signalFlag == Signal.CancelLaunching) return;
                    }

                    // handle command line options
                    try
                    {
                        Dictionary<string, Parameter> parameters = new Dictionary<string, Parameter>();
                        if (args != null)
                        {
                            foreach (string arg in args)
                            {
                                Parameter p = GetParameterValue(arg);
                                if (p.Argument != null) parameters.Add(p.Argument, p);
                            }
                        }

                        // the 'cmd' option is special in that it may require Growl to *not* launch, depending on the current state and command issued.
                        // we handle it here first - if other parameters are also passed, they will be ignored.
                        if(parameters.ContainsKey("/cmd"))
                        {
                            string cmd = parameters["/cmd"].Value.ToLower();
                            // currently supported values: start, stop, show
                            switch (cmd)
                            {
                                case "start" :
                                    // 1. Growl is not running. Start it (service will start automatically)
                                    // 2. Growl is running and started. do nothing
                                    // 3. Growl is running and stopped. start it
                                    // TODO: this is not complete. i am not sure if i am going to include this ever or not
                                    break;
                                case "stop" :
                                    // 1. Growl is not running. do not launch it
                                    // 2. Growl is running and started. stop it but do not close
                                    // 3. Growl is running and stopped. do nothing
                                    // TODO: this is not complete. i am not sure if i am going to include this ever or not
                                    break;
                                case "show" :
                                    // 1. Growl is not running. Start it and open Settings window
                                    // 2. Growl is running. Show Settings window
                                    // 3. Growl is running and Settings window is already open. do nothing
                                    if (appIsAlreadyRunning)
                                    {
                                        signalFlag = signalFlag | Signal.ShowSettings;
                                        signalFlag = signalFlag | Signal.Silent;    // go silent to suppress the 'Growl is running' notification
                                    }
                                    else
                                    {
                                        showSettingsOnLaunch = true;
                                    }
                                    break;
                            }
                        }

                        if (parameters.ContainsKey("/log"))
                        {
                            string log = parameters["/log"].Value.ToLower();
                            if (log == "true") loggingEnabled = true;
                        }
                        bool debugMode = false;
                        if (parameters.ContainsKey("/debug"))
                        {
                            string debug = parameters["/debug"].Value.ToLower();
                            if (debug == "true") debugMode = true;
                            Utility.DebugMode = debugMode;
                            if (debugMode) MessageBox.Show("growl is now in debug mode");
                        }
                        if (parameters.ContainsKey("/silent"))
                        {
                            string silent = parameters["/silent"].Value.ToLower();
                            if (silent == "true") silentMode = true;
                            if (silentMode)
                                signalFlag = signalFlag | Signal.Silent;
                        }
                        string listenUrlFile = null;
                        if (parameters.ContainsKey("/listenurl")) listenUrlFile = parameters["/listenurl"].Value;
                        else if (args != null && args.Length == 1) listenUrlFile = args[0];
                        if (!String.IsNullOrEmpty(listenUrlFile) && System.IO.File.Exists(listenUrlFile))
                        {
                            string filename = String.Format("{0}.ListenUrl", System.IO.Path.GetFileNameWithoutExtension(listenUrlFile));    // we have to do this since Firefox will rename the temp file to file.ListenUrl-X.txt
                            string dest = System.IO.Path.Combine(Utility.UserSettingFolder, filename);
                            System.IO.File.Copy(listenUrlFile, dest, true);
                            signalFlag = signalFlag | Signal.HandleListenUrl;
                            signalFlag = signalFlag | Signal.Silent;    // go silent to suppress the 'Growl is running' notification
                        }
                    }
                    catch (Exception ex)
                    {
                        // dont fail on bad arguments
                        Utility.WriteDebugInfo("Bad arguments: " + ex.Message);
                    }

                    if (!appIsAlreadyRunning)
                    {
                        program = new Program();
                        program.ProgramRunning += new EventHandler(program_ProgramRunning);
                        program.Run();
                        app.AnotherInstanceStarted += new SingleInstanceApplication.AnotherInstanceStartedEventHandler(app_AnotherInstanceStarted);
                        app.Run(program);
                        app.AnotherInstanceStarted -= new SingleInstanceApplication.AnotherInstanceStartedEventHandler(app_AnotherInstanceStarted);
                        program.ProgramRunning -= new EventHandler(program_ProgramRunning);
                        program.Dispose();
                        program = null;
                    }
                    else
                    {
                        InternalNotification.SaveToDisk(ref queuedNotifications);
                        app.SignalFirstInstance((int)signalFlag, signalValue);
                    }
                }
                app.Dispose();
                app = null;
            }
            catch (Exception ex)
            {
                HandleUnhandledException(ex);
            }
        }