/// <summary> /// Handler that gets called if another instance of the application was started. It passes /// the command line arguments from the other instance on so we can act accordingly here. /// </summary> /// <param name="sender">The sender.</param> /// <param name="args">The instance containing the event data.</param> private static void SingleInstanceCallback(object sender, InstanceCallbackEventArgs args) { if (args == null || mainForm == null || !mainForm.IsHandleCreated) { return; } Action <bool> d = (bool x) => { mainForm.Activate(x); // Parse command line and extract the model file name if there is one. WbOptions options = new WbOptions("", "", false); System.Reflection.Assembly asm = System.Reflection.Assembly.GetEntryAssembly(); options.parse_args(args.CommandLineArgs, asm.Location); wbContext.finished_loading(options); }; mainForm.Invoke(d, true); }
static void Main(string[] Args) { // Connect the application to console to have proper output there if requested. bool consoleRedirectionWorked = Win32Api.RedirectConsole(); // Start with command line parsing. string userDir = System.IO.Path.Combine(System.IO.Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "MySQL"), "Workbench"); Logger.InitLogger(userDir); if (!consoleRedirectionWorked) { Logger.LogError("Workbench", "Console redirection failed.\n"); } System.Reflection.Assembly asm = System.Reflection.Assembly.GetEntryAssembly(); string baseDir = System.IO.Path.GetDirectoryName(asm.Location); WbOptions wbOptions = new WbOptions(baseDir, userDir, true); if (!wbOptions.parse_args(Args, asm.Location)) { Logger.LogInfo("Workbench", "Command line params told us to shut down.\n"); return; } wbOptions.analyzeCommandLineArguments(); PrintInitialLogInfo(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); // Hook into the exception handling to establish our own handling. AppDomain currentDomain = AppDomain.CurrentDomain; // CLR currentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException); Application.ThreadException += // Windows Forms new System.Threading.ThreadExceptionEventHandler(OnGuiUnhandledException); // Read some early values which cannot be stored in the preferences (since they are loaded // later) from registry. bool singleInstance = true; string lastVersion = ""; string currentVersion = GetApplicationMetaInfo(ApplicationMetaInfo.Version); Logger.LogInfo("Workbench", "Current version given by meta info is: " + currentVersion + '\n'); RegistryKey wbKey = Registry.CurrentUser; try { wbKey = wbKey.OpenSubKey(@"Software\Oracle\MySQL Workbench", false); if (wbKey != null) { if (wbKey.GetValue("DisableSingleInstance", 0).ToString() == "1") { singleInstance = false; } lastVersion = wbKey.GetValue("LastStartedAs", "").ToString(); } else { Registry.CurrentUser.CreateSubKey(@"Software\Oracle\MySQL Workbench"); } } catch (Exception e) { Logger.LogError("Workbench", "Error while checking single instance reg key: " + e.Message + '\n'); } finally { if (wbKey != null) { wbKey.Close(); } } // First check if this is the first instance of Workbench (if enabled). // The setting for single-instance is stored in the registry as it is Windows-only // and loading of the application settings happens later. if (singleInstance) { if (!ApplicationInstanceManager.CreateSingleInstance( Assembly.GetExecutingAssembly().GetName().Name, Args, SingleInstanceCallback)) { Logger.LogInfo("Workbench", "Exiting as another instance of WB is already running.\n"); return; } } // Give the main thread a proper name, so we can later check for it when needed. Thread.CurrentThread.Name = "mainthread"; // Change the working dir to to application path. // This is necessary because all our internal data files etc. are located under the app dir // and WB could have been called from a different dir. string workdir = System.IO.Directory.GetCurrentDirectory(); System.IO.Directory.SetCurrentDirectory(baseDir); // Next check if this is the first start of a new version of WB. In this case remove all // compiled python files. They will be automatically recreated and can produce problems // under certain circumstances. if (currentVersion != lastVersion) { Logger.LogInfo("Workbench", "This is the first start of a new version. Doing some clean up.\n"); List <string> failed = new List <string>(); RemoveCompiledPythonFiles(baseDir, failed); // TODO: decide if we wanna ask the user to remove those files manually or just ignore them. } // Some people don't have c:\windows\system32 in PATH, so we need to set it here // for WBA to find the needed commands String systemFolder = Environment.GetFolderPath(Environment.SpecialFolder.System); String cleanedPath = Environment.GetEnvironmentVariable("PATH"); String [] paths = cleanedPath.Split(new char[] { ';' }); cleanedPath = ""; // Strip all python related dirs from PATH to avoid conflicts with other Python installations. foreach (String path in paths) { if (!path.ToLower().Contains("python")) { cleanedPath = cleanedPath + ";" + path; } } Environment.SetEnvironmentVariable("PATH", systemFolder + cleanedPath); Logger.LogInfo("Workbench", "Setting PATH to: " + systemFolder + cleanedPath + '\n'); // Clear PYTHONPATH environment variable, as we do not need it but our python impl // seriously gets confused with it. Environment.SetEnvironmentVariable("PYTHONPATH", workdir + "\\python\\Lib;" + workdir + "\\python\\DLLs;" + workdir + "\\python"); Environment.SetEnvironmentVariable("PYTHONHOME", workdir + "\\python"); // Initialize forms stuff. MySQL.Forms.Manager formsManager = MySQL.Forms.Manager.get_instance(); // Creates the singleton. // init extra mforms things that are delegated to the frontend, indirectly through RecordsetWrapper in wbpublic MySQL.Grt.Db.RecordsetWrapper.init_mforms(MySQL.Grt.Db.RecordsetView.create); #region Runtime path check // Currently WB has trouble running from a path containing non-ASCII characters. // Actually, our third party libraries have (namely lua, python, ctemplate), // as they don't consider Unicode file names (encoded as UTF-8) which leads to file-not-found // errors. Refuse to work in such a path for now. foreach (Char c in baseDir) { if (c > 0x7f) { MessageBox.Show("MySQL Workbench cannot be executed from a path that contains non-ASCII characters.\n" + "This problem is imposed by used third-party libraries.\n" + "Please run this application from the default installation path or at least a path which is all ASCII characters.", "MySQL Workbench Execution Problem", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } } #endregion #region Release check (outdated beta or rc version) // check the date of the executable and suggest to install a new version if this is a beta or rc if (GetApplicationMetaInfo(ApplicationMetaInfo.Configuration).ToUpper().IndexOf("BETA") >= 0 || GetApplicationMetaInfo(ApplicationMetaInfo.Configuration).ToUpper().IndexOf("RC") >= 0) { DateTime fileDate = System.IO.File.GetCreationTime(Application.ExecutablePath); if (DateTime.Now.Subtract(fileDate).TotalDays > 45) { Logger.LogInfo("Workbench", "Found an old WB pre release. Showing warning.\n"); if (MessageBox.Show("This version of MySQL Workbench is older than 45 days and most probably outdated. " + Environment.NewLine + "It is recommended to upgrade to a newer version if available. " + Environment.NewLine + "Press [OK] to check for a new version and exit the application. " + "Press [Cancel] to continue using this version.", "MySQL Workbench Version Outdated", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1) == DialogResult.OK) { CheckForNewVersion(); return; } } } #endregion #region Variables and Splashscreen #endregion #region Initialize GRT // Try to instantiate the Workbench context and the GRT Manager and catch exceptions try { // Create Workbench Context wbContext = new WbContext(wbOptions.Verbose); if (wbContext != null) { // Create the GRT Manager instance grtManager = wbContext.get_grt_manager(); } } catch (Exception ex) { HandleException(ex); } #endregion // If the Workbench Context and GRT Manager were successfully created, // initialize the application if (wbContext != null && grtManager != null) { #region Initialize Callbacks and Mainform mainForm = new MainForm(wbContext); // Initialize the Workbench context ManagedApplication formsApplication = new ManagedApplication( new AppCommandDelegate(mainForm.ApplicationCommand), mainForm.dockDelegate); callbacks = new WbFrontendCallbacks( new WbFrontendCallbacks.StrStrStrStrDelegate(mainForm.ShowFileDialog), new WbFrontendCallbacks.VoidStrDelegate(mainForm.ShowStatusText), new WbFrontendCallbacks.BoolStrStrFloatDelegate(mainForm.ShowProgress), new WbFrontendCallbacks.CanvasViewStringStringDelegate(mainForm.CreateNewDiagram), new WbFrontendCallbacks.VoidCanvasViewDelegate(mainForm.DestroyView), new WbFrontendCallbacks.VoidCanvasViewDelegate(mainForm.SwitchedView), new WbFrontendCallbacks.VoidCanvasViewDelegate(mainForm.ToolChanged), new WbFrontendCallbacks.IntPtrGRTManagerModuleStrStrGrtListFlagsDelegate(mainForm.OpenPlugin), new WbFrontendCallbacks.VoidIntPtrDelegate(mainForm.ShowPlugin), new WbFrontendCallbacks.VoidIntPtrDelegate(mainForm.HidePlugin), new WbFrontendCallbacks.VoidRefreshTypeStringIntPtrDelegate(mainForm.RefreshGUI), new WbFrontendCallbacks.VoidBoolDelegate(mainForm.LockGUI), new WbFrontendCallbacks.VoidStrDelegate(mainForm.PerformCommand), new WbFrontendCallbacks.BoolDelegate(mainForm.QuitApplication)); // TODO: check return value and show error message. // Currently the return value is always true. In case of an error an exception is raised. // That should change. wbContext.init(callbacks, wbOptions, new WbContext.VoidStrUIFormDelegate(mainForm.CreateMainFormView) ); // command registration must be done after WBContext init mainForm.PostInit(); // Set the Application.Idle event handler Application.Idle += new EventHandler(OnApplicationIdle); // Don't call the idle handler too often. timer = new System.Windows.Forms.Timer(); timer.Interval = 100; timer.Tick += new EventHandler(timer_Tick); timer.Start(); // Trigger GRT idle tasks grtManager.perform_idle_tasks(); // Setup Menus wbContext.validate_edit_menu(); mainForm.Show(); Logger.LogInfo("Workbench", "UI is up\n"); // Tell the backend our main UI is ready. This will also load a model if it was given via command line // and opens the overview form for it. wbContext.finished_loading(wbOptions); // Right before we go to work and everything was loaded write the current version to registry // to allow us later to find out if we ran a new version the first time. try { wbKey = Registry.CurrentUser.OpenSubKey(@"Software\Oracle\MySQL Workbench", true); if (wbKey != null) { wbKey.SetValue("LastStartedAs", currentVersion); } } catch (Exception e) { Logger.LogError("Workbench", "Couldn't write regkey LastStartedAs: " + e.Message + '\n'); } finally { if (wbKey != null) { wbKey.Close(); } } // Start the Application if we are not already shutting down. if (!wbContext.is_quitting()) { try { Logger.LogInfo("Workbench", "Running the application\n"); Application.Run(new ApplicationContext(mainForm)); } catch (Exception e) { HandleException(e); } } #endregion Logger.LogInfo("Workbench", "Shutting down Workbench\n"); timer.Stop(); timer.Dispose(); // shutdown wb context if (wbContext != null) { while (wbContext.is_busy()) { wbContext.flush_idle_tasks(); } wbContext.finalize(); wbContext.Dispose(); } formsApplication.Dispose(); formsManager.Dispose(); GC.Collect(); } Win32Api.ReleaseConsole(); Logger.LogInfo("Workbench", "Done\n"); }
static void Main(string[] Args) { // Connect the application to console to have proper output there if requested. bool consoleRedirectionWorked = Win32Api.RedirectConsole(); // Start with command line parsing. string userDir = System.IO.Path.Combine(System.IO.Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "MySQL"), "Workbench"); Logger.InitLogger(userDir); if (!consoleRedirectionWorked) Logger.LogError("Workbench", "Console redirection failed.\n"); System.Reflection.Assembly asm = System.Reflection.Assembly.GetEntryAssembly(); string baseDir = System.IO.Path.GetDirectoryName(asm.Location); WbOptions wbOptions = new WbOptions(baseDir, userDir, true); if (!wbOptions.parse_args(Args, asm.Location)) { Logger.LogInfo("Workbench", "Command line params told us to shut down.\n"); return; } PrintInitialLogInfo(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); // Hook into the exception handling to establish our own handling. AppDomain currentDomain = AppDomain.CurrentDomain; // CLR currentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException); Application.ThreadException += // Windows Forms new System.Threading.ThreadExceptionEventHandler(OnGuiUnhandledException); // Read some early values which cannot be stored in the preferences (since they are loaded // later) from registry. bool singleInstance = true; string lastVersion = ""; string currentVersion = GetApplicationMetaInfo(ApplicationMetaInfo.Version); Logger.LogInfo("Workbench", "Current version given by meta info is: " + currentVersion + '\n'); RegistryKey wbKey = Registry.CurrentUser; try { wbKey = wbKey.OpenSubKey(@"Software\Oracle\MySQL Workbench", false); if (wbKey != null) { if (wbKey.GetValue("DisableSingleInstance", 0).ToString() == "1") singleInstance = false; lastVersion = wbKey.GetValue("LastStartedAs", "").ToString(); } else Registry.CurrentUser.CreateSubKey(@"Software\Oracle\MySQL Workbench"); } catch (Exception e) { Logger.LogError("Workbench", "Error while checking single instance reg key: " + e.Message + '\n'); } finally { if (wbKey != null) wbKey.Close(); } // First check if this is the first instance of Workbench (if enabled). // The setting for single-instance is stored in the registry as it is Windows-only // and loading of the application settings happens later. if (singleInstance) { if (!ApplicationInstanceManager.CreateSingleInstance( Assembly.GetExecutingAssembly().GetName().Name, Args, SingleInstanceCallback)) { Logger.LogInfo("Workbench", "Exiting as another instance of WB is already running.\n"); return; } } // Give the main thread a proper name, so we can later check for it when needed. Thread.CurrentThread.Name = "mainthread"; // Change the working dir to to application path. // This is necessary because all our internal data files etc. are located under the app dir // and WB could have been called from a different dir. string workdir = System.IO.Directory.GetCurrentDirectory(); System.IO.Directory.SetCurrentDirectory(baseDir); // Next check if this is the first start of a new version of WB. In this case remove all // compiled python files. They will be automatically recreated and can produce problems // under certain circumstances. if (currentVersion != lastVersion) { Logger.LogInfo("Workbench", "This is the first start of a new version. Doing some clean up.\n"); List<string> failed = new List<string>(); RemoveCompiledPythonFiles(baseDir, failed); // TODO: decide if we wanna ask the user to remove those files manually or just ignore them. } // Some people don't have c:\windows\system32 in PATH, so we need to set it here // for WBA to find the needed commands String systemFolder = Environment.GetFolderPath(Environment.SpecialFolder.System); String cleanedPath = Environment.GetEnvironmentVariable("PATH"); String []paths= cleanedPath.Split(new char[]{';'}); cleanedPath = ""; // Strip all python related dirs from PATH to avoid conflicts with other Python installations. foreach (String path in paths) { if (!path.ToLower().Contains("python")) cleanedPath = cleanedPath + ";" + path; } Environment.SetEnvironmentVariable("PATH", systemFolder + cleanedPath); Logger.LogInfo("Workbench", "Setting PATH to: " + systemFolder + cleanedPath + '\n'); // Clear PYTHONPATH environment variable, as we do not need it but our python impl // seriously gets confused with it. Environment.SetEnvironmentVariable("PYTHONPATH", workdir + "\\python\\Lib;" + workdir + "\\python\\DLLs;" + workdir + "\\python"); Environment.SetEnvironmentVariable("PYTHONHOME", workdir + "\\python"); // Initialize forms stuff. MySQL.Forms.Manager formsManager = MySQL.Forms.Manager.get_instance(); // Creates the singleton. // init extra mforms things that are delegated to the frontend, indirectly through RecordsetWrapper in wbpublic MySQL.Grt.Db.RecordsetWrapper.init_mforms(MySQL.Grt.Db.RecordsetView.create); #region Runtime path check // Currently WB has trouble running from a path containing non-ASCII characters. // Actually, our third party libraries have (namely lua, python, ctemplate), // as they don't consider Unicode file names (encoded as UTF-8) which leads to file-not-found // errors. Refuse to work in such a path for now. foreach (Char c in baseDir) if (c > 0x7f) { MessageBox.Show("MySQL Workbench cannot be executed from a path that contains non-ASCII characters.\n"+ "This problem is imposed by used third-party libraries.\n" + "Please run this application from the default installation path or at least a path which is all ASCII characters.", "MySQL Workbench Execution Problem", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } #endregion #region Release check (outdated beta or rc version) // check the date of the executable and suggest to install a new version if this is a beta or rc if (GetApplicationMetaInfo(ApplicationMetaInfo.Configuration).ToUpper().IndexOf("BETA") >= 0 || GetApplicationMetaInfo(ApplicationMetaInfo.Configuration).ToUpper().IndexOf("RC") >= 0) { DateTime fileDate = System.IO.File.GetCreationTime(Application.ExecutablePath); if (DateTime.Now.Subtract(fileDate).TotalDays > 45) { Logger.LogInfo("Workbench", "Found an old WB pre release. Showing warning.\n"); if (MessageBox.Show("This version of MySQL Workbench is older than 45 days and most probably outdated. " + Environment.NewLine + "It is recommended to upgrade to a newer version if available. " + Environment.NewLine + "Press [OK] to check for a new version and exit the application. " + "Press [Cancel] to continue using this version.", "MySQL Workbench Version Outdated", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1) == DialogResult.OK) { CheckForNewVersion(); return; } } } #endregion #region Variables and Splashscreen #endregion #region Initialize GRT // Try to instantiate the Workbench context and the GRT Manager and catch exceptions try { // Create Workbench Context wbContext = new WbContext(wbOptions.Verbose); if (wbContext != null) { // Create the GRT Manager instance grtManager = wbContext.get_grt_manager(); } } catch (Exception ex) { HandleException(ex); } #endregion // If the Workbench Context and GRT Manager were successfully created, // initialize the application if (wbContext != null && grtManager != null) { #region Initialize Callbacks and Mainform mainForm = new MainForm(wbContext); // Initialize the Workbench context ManagedApplication formsApplication = new ManagedApplication( new AppCommandDelegate(mainForm.ApplicationCommand), mainForm.dockDelegate); callbacks = new WbFrontendCallbacks( new WbFrontendCallbacks.StrStrStrStrDelegate(mainForm.ShowFileDialog), new WbFrontendCallbacks.VoidStrDelegate(mainForm.ShowStatusText), new WbFrontendCallbacks.BoolStrStrFloatDelegate(mainForm.ShowProgress), new WbFrontendCallbacks.CanvasViewStringStringDelegate(mainForm.CreateNewDiagram), new WbFrontendCallbacks.VoidCanvasViewDelegate(mainForm.DestroyView), new WbFrontendCallbacks.VoidCanvasViewDelegate(mainForm.SwitchedView), new WbFrontendCallbacks.VoidCanvasViewDelegate(mainForm.ToolChanged), new WbFrontendCallbacks.IntPtrGRTManagerModuleStrStrGrtListFlagsDelegate(mainForm.OpenPlugin), new WbFrontendCallbacks.VoidIntPtrDelegate(mainForm.ShowPlugin), new WbFrontendCallbacks.VoidIntPtrDelegate(mainForm.HidePlugin), new WbFrontendCallbacks.VoidRefreshTypeStringIntPtrDelegate(mainForm.RefreshGUI), new WbFrontendCallbacks.VoidBoolDelegate(mainForm.LockGUI), new WbFrontendCallbacks.VoidStrDelegate(mainForm.PerformCommand), new WbFrontendCallbacks.BoolDelegate(mainForm.QuitApplication)); // TODO: check return value and show error message. // Currently the return value is always true. In case of an error an exception is raised. // That should change. wbContext.init(callbacks, wbOptions, new WbContext.VoidStrUIFormDelegate(mainForm.CreateMainFormView) ); // command registration must be done after WBContext init mainForm.PostInit(); // Set the Application.Idle event handler Application.Idle += new EventHandler(OnApplicationIdle); // Don't call the idle handler too often. timer = new System.Windows.Forms.Timer(); timer.Interval = 100; timer.Tick += new EventHandler(timer_Tick); timer.Start(); // Trigger GRT idle tasks grtManager.perform_idle_tasks(); // Setup Menus wbContext.validate_edit_menu(); mainForm.Show(); Logger.LogInfo("Workbench", "UI is up\n"); // Tell the backend our main UI is ready. This will also load a model if it was given via command line // and opens the overview form for it. wbContext.finished_loading(wbOptions); // Right before we go to work and everything was loaded write the current version to registry // to allow us later to find out if we ran a new version the first time. try { wbKey = Registry.CurrentUser.OpenSubKey(@"Software\Oracle\MySQL Workbench", true); if (wbKey != null) wbKey.SetValue("LastStartedAs", currentVersion); } catch (Exception e) { Logger.LogError("Workbench", "Couldn't write regkey LastStartedAs: " + e.Message + '\n'); } finally { if (wbKey != null) wbKey.Close(); } // Start the Application if we are not already shutting down. if (!wbContext.is_quitting()) { try { Logger.LogInfo("Workbench", "Running the application\n"); Application.Run(new ApplicationContext(mainForm)); } catch (Exception e) { HandleException(e); } } #endregion Logger.LogInfo("Workbench", "Shutting down Workbench\n"); timer.Stop(); timer.Dispose(); // shutdown wb context if (wbContext != null) { while (wbContext.is_busy()) wbContext.flush_idle_tasks(); wbContext.finalize(); wbContext.Dispose(); } formsApplication.Dispose(); formsManager.Dispose(); GC.Collect(); } Win32Api.ReleaseConsole(); Logger.LogInfo("Workbench", "Done\n"); }