/// <summary> /// Recycles the existing log file /// </summary> public static void RecycleLog() { lock (ms_hardKill) { if (ms_outputFile == null) { return; } // Generate the new file name DateTime dt = DateTime.Now; string ext = "." + dt.Year + "." + dt.Month + "." + dt.Day + "." + dt.Hour + "." + dt.Minute + "." + dt.Second + "." + dt.Millisecond; string NewFileName = ms_appName + ext + OUTPUTEXT; try { // copy the log file to the new log file File.Copy(ms_outputLogName, NewFileName); WriteToConsole("The output file was saved as: " + NewFileName); } catch (Exception e) { WriteToConsole("Cannot save the existing output file as: " + NewFileName + ". The output file is preserved"); EAException.Report(e); } // truncate the current log file ms_outputFile.SetLength(0); } }
/// <summary> /// The callback function that gets called when the configuration file changes. /// /// NOTE: /// OnChanged gets fired multiple times if changes are made using notepad.. /// this is annoying in terms of performance but otherwise doesn't affect the correctness of /// the program. /// </summary> /// <param name="a"></param> /// <param name="file"></param> public void ConfigurationFileChangedCallBack (object a, FileSystemEventArgs file) { try { //Read the configuration information using External Storage Reader //Read the entire XML file and get our part from the file Global.WriteInfo("Configuration file changed externally..."); ReloadActivatorConfiguration(); } catch (Exception e) { EAException ea = e as EAException; // if the exception was warning then just report it and ignore the update if (ea != null && (int)ea.Error < 0) { EAException.Report(e); Global.WriteWarning( "Configuration file update was ignored because of bad data in it."); } else { Global.DoHardKill(e); } } }
/// <summary> // Installs the Windows NT Service. Uses a transacted installer, so that // if installation fails midstream for some reason, installation is rolled // back. Post installation, the registry settings for the service are modified // to change the command-line parameters (because currently, CLR does not allow it) // If registry modification fails for some reason, uninstall is called on the service. /// </summary> /// <param name="svcname">Service to install</param> /// <param name="username">User name to execute under</param> /// <param name="password">Password of the user</param> public static void Install( string svcname, string username, string password) { bool doUninstall = false; try { Global.WriteStatus("External Activator is installing as NT service '" + svcname + "' ..."); TransactedInstaller ti = new TransactedInstaller(); // Sets information required for installing (might get username and password information from the user) ProjectInstaller mi = new ProjectInstaller(svcname, username, password); ti.Installers.Add(mi); String path = String.Format("/assemblypath={0}", System.Reflection.Assembly.GetExecutingAssembly().Location); String[] cmdline = { path }; InstallContext ctx = new InstallContext(String.Format(svcname + ".InstallLog"), cmdline); ti.Context = ctx; // Starts the installation process ti.Install(new Hashtable()); doUninstall = true; // Registry modification of Command-Line arguments to include (-svc) followed by the service name // to install it as a particular External Activator. RegistryKey key = Registry.LocalMachine.OpenSubKey(String.Format("System\\CurrentControlSet\\Services\\{0}", svcname), true); object ImagePathObject = key.GetValue("ImagePath"); if (ImagePathObject != null) { Global.WriteDebugInfo("Modifying the registry to include command-line parameters after installation."); string ImagePath = String.Format("{0} /{1}:{2}", (string)ImagePathObject, CommandLineArgument.RunAsNTServiceArgument, svcname); key.SetValue("ImagePath", ImagePath); } else { // Calls Uninstall if registry modification not possible throw new EAException("Critical Error : Could not open ImagePath key of NT service '" + svcname + "' in the registry. Uninstalling service", Error.postInstallProblem); } Global.WriteStatus("External Activator is successfully installed as NT service '" + svcname + "' ..."); } catch (Exception e) { if (doUninstall) { try { NTService.Uninstall(svcname); } catch (Exception eNested) { EAException.Report(eNested); } } throw new EAException("External Activation Installation failed", Error.installProblem, e); } }
public static void DoHardKill( Exception e) { ms_logMgr.UncleanShutdown(); EAException.Report(e, true); WriteError("External activator was abruptly terminated."); EAException ea = e as EAException; if (ea != null) { System.Environment.Exit((int)ea.Error); } System.Environment.Exit((int)Error.unexpectedError); }
/// <summary> /// Reports the exception list to the console or the log file /// </summary> /// <param name="e">the exception list</param> public static void Report(Exception e, bool console) { try { string s = ""; EAException ea = e as EAException; if (ea != null) { s += ea.Message; e = ea.InnerException; while (e != null) { s += " because:\n"; ea = e as EAException; if (ea != null) { s += ea.Message; e = ea.InnerException; } else { break; } } if (ea != null) { s += ".\n"; } } if (e != null) { s += "Unexpected exception was caught: " + e.Message + "\n"; s += e.ToString(); } Global.WriteException(s, console); } catch (Exception) { // swallow/ignore } }
/// <summary> /// Performs necessary initialization of the External Activation NT Service so that it can start /// doing its work. /// </summary> /// <param name="args"></param> protected override void OnStart( string[] args) // I optional startup arguments { try { if (Global.Shutdown == false) { Global.BootExternalActivator(); return; } } catch (Exception e) { Global.SetShutdown(); EAException.Report(e); } StopService(new ServiceController(this.ServiceName), new TimeSpan(1)); return; }
/// <summary> /// Connects to the sql server and database and run the service /// </summary> public static void Start( ConfigurationManager configMgr) { Global.WriteDebugInfo("Starting up the Notification service..."); configMgr.GetNotificationService( ref ms_notificationSQLServer, ref ms_notificationDatabase, ref ms_notificationService); ms_connected = false; ms_connecting = false; ms_error = null; NotificationService ns = null; SqlConnection connection = null; int waiting_time = 1000; int retry = 0; while (true) { bool fFailedToConnect = false; // define a connection if needed if (connection == null) { connection = new SqlConnection( String.Format("server={0};Integrated security=true;database={1};Connect Timeout=10;Application Name=External activator", ms_notificationSQLServer, ms_notificationDatabase)); ns = null; } // if connection is up, do not establish again. Else, establish a connection // Always started the first time if (connection.State != ConnectionState.Open) { try { ms_connecting = true; connection.Open(); } catch (SqlException e) { if (ms_error != e.Message) { ms_error = e.Message; Global.WriteWarning( "Failed to connect to Notification SQL Server '" + ms_notificationSQLServer + "' and Database: '" + ms_notificationDatabase + "' because: " + e.Message); } else { Global.WriteDebugInfo( "Failed to connect to Notification SQL Server '" + ms_notificationSQLServer + "' and Database: '" + ms_notificationDatabase + "' because: " + e.Message); } connection.Dispose(); connection = null; fFailedToConnect = true; } ms_connecting = false; if (fFailedToConnect) { // Implement an exponential back-off rate of connecting (else this might // overflow the EventLog and other logs waiting_time *= 2; if (waiting_time > Global.MAX_WAITING_TIME) { waiting_time = Global.MAX_WAITING_TIME; } Thread.Sleep(waiting_time); continue; } Global.WriteInfo("Connection to notification SQL server '" + ms_notificationSQLServer + "' and database '" + ms_notificationDatabase + "' is established."); waiting_time = 1000; ms_error = null; ms_connected = true; } // create a notification service is one does not exist if (ns == null) { try { ns = new NotificationService( ms_notificationService, connection, configMgr); } catch (ArgumentException e) { // if bad parameters were provided then // report the problem and retry later if (ms_error != e.Message) { Global.WriteWarning(e.Message); ms_error = e.Message; } else { Global.WriteDebugInfo(e.Message); } fFailedToConnect = true; } if (fFailedToConnect) { waiting_time *= 2; if (waiting_time > Global.MAX_WAITING_TIME) { waiting_time = Global.MAX_WAITING_TIME; } Thread.Sleep(waiting_time); continue; } waiting_time = 1000; } // now receive all the messages for this service and // end the application ns.WaitforTimeout = TimeSpan.FromSeconds(-1); ns.FetchSize = 1; bool fRestart = false; Global.WriteInfo("Notification service '" + ms_notificationService + "' is started."); try { ns.Run(true, connection, null); } catch (ServiceException e) { Global.WriteWarning("Service exception occured while running. External activator will try to reconnect."); if (retry == 3) { Global.DoHardKill(e); } EAException.Report(e); fRestart = true; } catch (SqlException e) { Global.WriteWarning("Service exception occured while running. External activator will try to reconnect."); if (retry == 3) { Global.DoHardKill(e); } EAException.Report(e); fRestart = true; } catch (Exception e) { Global.DoHardKill(e); } if (fRestart) { retry++; // reset the state and retry again ms_connected = false; ms_connecting = false; ms_error = null; waiting_time = 1000; ns = null; connection.Close(); connection = null; continue; } connection.Close(); return; } }