// Called to stop the retry and/or self-update timers and to close the WCF service hosts so // the program can terminate (whether it's a console app or a service). internal static void Stop() { using (Log.InfoCall()) { lock (_lock) { if (_selfUpdateTimer != null) { _selfUpdateTimer.Dispose(); _selfUpdateTimer = null; } if (_wcfRetryTimer != null) { _wcfRetryTimer.Dispose(); _wcfRetryTimer = null; } // This can take a while (actually time out) if a client is still connected. // Write a message to the console to explain the delay, which is // obvious when running in console mode. Console.WriteLine("Closing ServiceHosts..."); TracerXServices.Shutdown(timeoutSeconds: 10); } } }
// If the first attempt to start the WCF service fails due to AddressAlreadyInUseException // and retrying is enabled, this will get called every AppArgs.RetryInterval minutes to retry // as long it continues to fail due to AddressAlreadyInUseException. public static void RetryWcfService(object sender, System.Timers.ElapsedEventArgs e) { // This is called via _wcfRetryTimer on a ThreadPool thread. Temporarily change the thread name for logging purposes. using (Log.ThreadNameForCall("TracerX Starter")) { lock (_lock) { if (_wcfRetryTimer != null && _wcfRetryTimer.Enabled) { try { Log.Debug("Attempting to start TracerX WCF services."); TracerXServices.Startup(AppArgs.Port, AppArgs.IsImpersonate); // Getting here means Startup() succeeded (no exception) so we can stop/dispose/release the timer. if (AppArgs.IsConsoleApp) { Console.WriteLine("The TracerX WCF service was started."); } Log.Info("TracerX WCF service was started."); _wcfRetryTimer.Dispose(); _wcfRetryTimer = null; } catch (System.ServiceModel.AddressAlreadyInUseException ex) { Log.Info("The TracerX WCF service port is still in use by another process."); // Schedule another retry. Timer does not AutoReset so we have to start // it explicitly. _wcfRetryTimer.Interval = 60000.0 * AppArgs.RetryInterval; _wcfRetryTimer.Start(); } catch (Exception ex) { // This is unexpected and probably means we'll never be able to // start the TracerX service host so just give up and stop the program. Log.Fatal("Unexpected exception trying to start TracerX WCF service host: ", ex); Stop(); } } } } }
// Whether we're a console app or a Windows service this is called to start the WCF service hosts. // May also start the retry and/or self-update timers. internal static void Start() { using (Log.InfoCall()) { lock (_lock) { MaybeStartSelfUpdateTimer(); if (AppArgs.RetryInterval <= 0) { // Retries are disabled. If this throws an exception, e.g. if the port is in use by another process, we're done. TracerXServices.Startup(AppArgs.Port, AppArgs.IsImpersonate); } else { // If the port is currently in use by another process start a timer to // retry acquiring the port every AppArgs.RetryInterval minutes. try { TracerXServices.Startup(AppArgs.Port, AppArgs.IsImpersonate); } catch (System.ServiceModel.AddressAlreadyInUseException) { if (AppArgs.IsConsoleApp) { Console.WriteLine("Starting the retry timer because the port ({0}) used by the", AppArgs.Port); Console.WriteLine("TracerX WCF service is currently in use by another process."); Console.WriteLine("The retry interval is {0} minutes.", AppArgs.RetryInterval); } Log.Warn("Starting the retry timer because the port used by the TracerX WCF service is currently in use by another process. Port = " + AppArgs.Port); _wcfRetryTimer = new System.Timers.Timer(60000.0 * AppArgs.RetryInterval); _wcfRetryTimer.AutoReset = false; _wcfRetryTimer.Elapsed += RetryWcfService; _wcfRetryTimer.Start(); } } } } }
private void btnStart_Click(object sender, EventArgs e) { int port = 25120; if (radSpecifiedPort.Checked) { if (int.TryParse(txtPort.Text, out port)) { if (port < 0 || port > 65535) { MainForm.ShowMessageBox("The port must be in the range 0 - 65535."); port = -1; } } else { MainForm.ShowMessageBox("The port must be a number in the range 0 - 65535."); port = -1; } } if (port != -1) { try { TracerXServices.Startup(port, radDoImpersonate.Checked); DialogResult = DialogResult.OK; } catch (System.ServiceModel.AddressAlreadyInUseException) { // Another process is using the port. Check if it's the TracerX WCF service. TryConnecting(port); } catch (Exception ex) { MainForm.ShowMessageBox("Could not start the TracerX service due to error: " + ex.Message); } } }