using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.Threading; using System.Reflection; // Ooganizer Namespaces using Foo.Platform; using Foo.Platform.Interacters; namespace Foo.ClientServices.ButtonWPForm { /// /// This class manages the creation/deletion of a Oogy CaptionButton Instance Exe. /// A CaptionButton Instance hosts the ButtonHook.dll /// [ComVisible(false)] internal class CaptionButtonStarter { // CaptionButton (ButtonHook.dll) Startup Delay private const int CAPTIONBUTTON_STARTUP_DELAY_MILISECONDS = 4000; // Member Variables private static Thread s_ButtonHookKeepAliveThread = null; private static bool s_ButtonHookKeepAliveThreadIsInitialized = false; // Declare the Log4net Variable private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType); /// /// Constructor by default will launch the thread if needed /// static CaptionButtonStarter() { StartButtonHookKeepAliveThreadIfNeeded(); } /// /// Use this property to set the CaptionButton to running / not running /// public static bool Run { get { return s_ButtonHookKeepAliveThreadIsInitialized; } set { if (!value) TerminateButtonHookKeepAliveThreadIfNeeded(); s_ButtonHookKeepAliveThreadIsInitialized = value; } } /// /// ButtonHookKeepAliveThread Thread for ButtonHook.dll - handled internally /// private static void ButtonHookKeepAliveThreadProc() { Thread.Sleep(CAPTIONBUTTON_STARTUP_DELAY_MILISECONDS); while (true) // Make Sure ButtonHook stays alive (No User kills it for any reason) { if (!BHInteracter.IsCaptionButtonRunning()) { Log.Info(string.Format("{0}() - ButtonHookKeepAliveThread - About to call StartCaptionButton()", MethodBase.GetCurrentMethod().Name)); // Launch OogyCaptionButton Process EXE BHInteracter.StartCaptionButton(); // wait a little before checking again... Thread.Sleep(100); if (BHInteracter.IsCaptionButtonRunning()) Log.Info(string.Format("{0}() - StartCaptionButton() Succeeded", MethodBase.GetCurrentMethod().Name)); else Log.Error(string.Format("{0}() - StartCaptionButton() Failed", MethodBase.GetCurrentMethod().Name)); } if (!s_ButtonHookKeepAliveThreadIsInitialized) { s_ButtonHookKeepAliveThreadIsInitialized = true; Log.Info(string.Format("{0}() - ButtonWPForm ButtonHookKeepAliveThread is initialized s_ButtonHookKeepAliveThreadIsInitialized is True", MethodBase.GetCurrentMethod().Name)); } // Checking every 30 seconds (quickly) should be more than enough Thread.Sleep(30000); } } /// /// Use this function to start ThreadProc(above) if needed. COM+ can shutdown the thread anytime, /// we need to make sure that the thread is alive BEFORE calling ButtonForms /// private static void StartButtonHookKeepAliveThreadIfNeeded() { if (s_ButtonHookKeepAliveThread != null && s_ButtonHookKeepAliveThread.IsAlive) { return; } else { s_ButtonHookKeepAliveThreadIsInitialized = false; // Start a new Thread so it can become the Message Loop s_ButtonHookKeepAliveThread = new Thread(new ThreadStart(CaptionButtonStarter.ButtonHookKeepAliveThreadProc)); // GUI components require the thread to be STA; otherwise throws an error s_ButtonHookKeepAliveThread.SetApartmentState(ApartmentState.STA); s_ButtonHookKeepAliveThread.Start(); } } /// /// Terminate the ButtonHook.dll by killing the Process /// private static void TerminateButtonHookKeepAliveThreadIfNeeded() { if (s_ButtonHookKeepAliveThreadIsInitialized) { s_ButtonHookKeepAliveThread.Abort(); s_ButtonHookKeepAliveThreadIsInitialized = false; Log.Info(string.Format("{0}() - ButtonWPForm is ButtonHookKeepAliveThread shutdown s_ButtonHookKeepAliveThreadIsInitialized is False", MethodBase.GetCurrentMethod().Name)); // Kill the OogyCaptionButton Process EXE BHInteracter.StopCaptionButton(); } } } }