public static void SendHeartbeat(string fileName, bool isWrite)
        {
            PythonCliParameters.Key     = ApiKey;
            PythonCliParameters.File    = fileName;
            PythonCliParameters.Plugin  = string.Format("{0}/{1} {2}/{3}", WakaTimeConstants.EditorName, WakaTimeConstants.EditorVersion, WakaTimeConstants.PluginName, WakaTimeConstants.PluginVersion);
            PythonCliParameters.IsWrite = isWrite;
            PythonCliParameters.Project = GetProjectName();

            var pythonBinary = PythonManager.GetPython();

            if (pythonBinary != null)
            {
                var process = new RunProcess(pythonBinary, PythonCliParameters.ToArray());
                if (Debug)
                {
                    Logger.Debug(string.Format("[\"{0}\", \"{1}\"]", pythonBinary, string.Join("\", \"", PythonCliParameters.ToArray(true))));
                    process.Run();
                    Logger.Debug(string.Format("CLI STDOUT: {0}", process.Output));
                    Logger.Debug(string.Format("CLI STDERR: {0}", process.Error));
                }
                else
                {
                    process.RunInBackground();
                }

                if (!process.Success)
                {
                    Logger.Error(string.Format("Could not send heartbeat: {0}", process.Error));
                }
            }
            else
            {
                Logger.Error("Could not send heartbeat because python is not installed");
            }
        }
        public static void SendHeartbeat(string windowTitle)
        {
            PythonCliParameters.Key    = ApiKey;
            PythonCliParameters.Entity = windowTitle;
            PythonCliParameters.Plugin = $"{WakaTimeConstants.PluginName}/{_version}";

            var pythonBinary = PythonManager.GetPython();

            if (pythonBinary != null)
            {
                var process = new RunProcess(pythonBinary, PythonCliParameters.ToArray());
                if (Debug)
                {
                    Logger.Debug($"[\"{pythonBinary}\", \"{string.Join("\", \"", PythonCliParameters.ToArray(true))}\"]");
                    process.Run();
                    Logger.Debug($"CLI STDOUT: {process.Output}");
                    Logger.Debug($"CLI STDERR: {process.Error}");
                }
                else
                {
                    process.RunInBackground();
                }

                if (!process.Success)
                {
                    Logger.Error($"Could not send heartbeat: {process.Error}");
                }
            }
            else
            {
                Logger.Error("Could not send heartbeat because python is not installed");
            }
        }
        public void InitializeAsync()
        {
            try
            {
                Logger.Info(string.Format("Initializing WakaTime v{0}", WakaTimeConstants.PluginVersion));

                // VisualStudio Object
                _docEvents      = ObjDte.Events.DocumentEvents;
                _windowEvents   = ObjDte.Events.WindowEvents;
                _solutionEvents = ObjDte.Events.SolutionEvents;

                // Settings Form
                _settingsForm              = new SettingsForm();
                _settingsForm.ConfigSaved += SettingsFormOnConfigSaved;

                try
                {
                    // Make sure python is installed
                    if (!PythonManager.IsPythonInstalled())
                    {
                        Downloader.DownloadAndInstallPython();
                    }

                    if (!DoesCliExist() || !IsCliLatestVersion())
                    {
                        Downloader.DownloadAndInstallCli();
                    }
                }
                catch (WebException ex)
                {
                    Logger.Error("Are you behind a proxy? Try setting a proxy in iTimeTrack Settings with format https://user:pass@host:port. Exception Traceback:", ex);
                }
                catch (Exception ex)
                {
                    Logger.Error("Error detecting dependencies. Exception Traceback:", ex);
                }

                // Add our command handlers for menu (commands must exist in the .vsct file)
                var mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
                if (mcs != null)
                {
                    // Create the command for the menu item.
                    var menuCommandId = new CommandID(GuidList.GuidWakaTimeCmdSet, (int)PkgCmdIdList.UpdateWakaTimeSettings);
                    var menuItem      = new MenuCommand(MenuItemCallback, menuCommandId);
                    mcs.AddCommand(menuItem);
                }

                // setup event handlers
                _docEvents.DocumentOpened     += DocEventsOnDocumentOpened;
                _docEvents.DocumentSaved      += DocEventsOnDocumentSaved;
                _windowEvents.WindowActivated += WindowEventsOnWindowActivated;
                _solutionEvents.Opened        += SolutionEventsOnOpened;

                Logger.Info(string.Format("Finished initializing WakaTime v{0}", WakaTimeConstants.PluginVersion));
            }
            catch (Exception ex)
            {
                Logger.Error("Error initializing Wakatime", ex);
            }
        }
        static bool IsCliLatestVersion()
        {
            var process = new RunProcess(PythonManager.GetPython(), PythonCliParameters.Cli, "--version");

            process.Run();

            if (process.Success)
            {
                var currentVersion = process.Error.Trim();
                Logger.Info(string.Format("Current wakatime-cli version is {0}", currentVersion));

                Logger.Info("Checking for updates to wakatime-cli...");
                var latestVersion = WakaTimeConstants.LatestWakaTimeCliVersion();

                if (currentVersion.Equals(latestVersion))
                {
                    Logger.Info("wakatime-cli is up to date.");
                    return(true);
                }
                else
                {
                    Logger.Info(string.Format("Found an updated wakatime-cli v{0}", latestVersion));
                }
            }
            return(false);
        }
Example #5
0
        static public void Download()
        {
            string url = PythonManager.GetPythonDownloadUrl();

            www = new WWW(url);
            EditorApplication.update = WhileDownloading;
        }
Example #6
0
        public static void SendHeartbeat(PythonCliParameters cliParameters)
        {
            var pythonBinary = PythonManager.GetPython();

            if (pythonBinary != null)
            {
                var process = new RunProcess(pythonBinary, cliParameters.ToArray());
                if (WakaTimeConfigFile.Debug)
                {
                    Logger.Debug(string.Format("[\"{0}\", \"{1}\"]", pythonBinary, string.Join("\", \"", cliParameters.ToArray(true))));
                    process.Run();
                    Logger.Debug(string.Format("CLI STDOUT: {0}", process.Output));
                    Logger.Debug(string.Format("CLI STDERR: {0}", process.Error));
                }
                else
                {
                    process.RunInBackground();
                }

                if (!process.Success)
                {
                    Logger.Error(string.Format("Could not send heartbeat: {0}", process.Error));
                }
            }
            else
            {
                Logger.Error("Could not send heartbeat because python is not installed");
            }
        }
Example #7
0
        static void DownloadCompleted()
        {
            EditorUtility.ClearProgressBar();

            if (Main.IsDebug)
            {
                UnityEngine.Debug.Log("Python downloaded: " + www.size.ToString());
            }
            string dir       = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
            string localFile = dir + PythonManager.GetPythonFileName();


            try {
                System.IO.FileStream stream = new System.IO.FileStream(localFile, System.IO.FileMode.Create, System.IO.FileAccess.Write);
                stream.Write(www.bytes, 0, www.bytes.Length);

                // close file stream
                stream.Close();

                www = null;
            } catch (Exception ex) {
                if (Main.IsDebug)
                {
                    UnityEngine.Debug.LogError("Python download failed: " + ex.Message);
                }
            }

            Install();
        }
        public void Initialize()
        {
            SetNotifyIconToolTip();
            _version = $"{CoreAssembly.Version.Major}.{CoreAssembly.Version.Minor}.{CoreAssembly.Version.Build}";

            try
            {
                Logger.Info($"Initializing WakaTime v{_version}");

                SettingsForm              = new SettingsForm();
                SettingsForm.ConfigSaved += SettingsFormOnConfigSaved;
                _wakaTimeConfigFile       = new WakaTimeConfigFile();

                // Make sure python is installed
                if (!PythonManager.IsPythonInstalled())
                {
                    var dialogResult = MessageBox.Show(@"Let's download and install Python now?", @"WakaTime requires Python", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                    if (dialogResult == DialogResult.Yes)
                    {
                        var url = PythonManager.PythonDownloadUrl;
                        Downloader.DownloadPython(url, WakaTimeConstants.UserConfigDir);
                    }
                    else
                    {
                        MessageBox.Show(
                            @"Please install Python (https://www.python.org/downloads/) and restart Visual Studio to enable the WakaTime plugin.",
                            @"WakaTime", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }

                if (!DoesCliExist() || !IsCliLatestVersion())
                {
                    try
                    {
                        Directory.Delete($"{WakaTimeConstants.UserConfigDir}\\wakatime-master", true);
                    }
                    catch { /* ignored */ }

                    Downloader.DownloadCli(WakaTimeConstants.CliUrl, WakaTimeConstants.UserConfigDir);
                }

                GetSettings();

                if (string.IsNullOrEmpty(ApiKey))
                {
                    PromptApiKey();
                }

                StartListeningForWindowChanges();

                Logger.Info($"Finished initializing WakaTime v{_version}");
            }
            catch (Exception ex)
            {
                Logger.Error("Error initializing Wakatime", ex);
            }
        }
Example #9
0
        static bool IsCliLatestVersion()
        {
            var process = new RunProcess(PythonManager.GetPython(), PythonCliParameters.Cli, "--version");

            process.Run();

            var wakatimeVersion = WakaTimeConstants.CurrentWakaTimeCliVersion();

            return(process.Success && process.Error.Equals(wakatimeVersion));
        }
Example #10
0
        static bool IsCliLatestVersion()
        {
            var process = new RunProcess(PythonManager.GetPython(), GetCliPath(), "--version");

            process.Run();

            var version = GetLatestWakaTimeCliVersion();

            return(process.Success && process.Error.Equals(version.ToString()));
        }
Example #11
0
        public static void HeartBeat(string apiKey, string file, bool write = false)
        {
            if (!PythonManager.IsPythonInstalled())
            {
                return;
            }

            string arguments = "--key " + apiKey +
                               " --file " + "\"" + file + "\"" +
                               " --plugin " + WakaTimeConstants.PLUGIN_NAME +
                               " --project " + Main.GetProjectName() +
                               " --verbose";

            if (Main.IsDebug)
            {
                UnityEngine.Debug.Log("Sending file: " + PythonManager.GetPythonPath() + " " + GetClientPath() +
                                      " " + arguments);
            }

            Process p = new Process {
                StartInfo =
                {
                    FileName               = PythonManager.GetPythonPath(),
                    Arguments              = "\"" + GetClientPath() + "\" " + arguments,
                    CreateNoWindow         = true,
                    WindowStyle            = ProcessWindowStyle.Hidden,
                    WorkingDirectory       = Application.dataPath,
                    UseShellExecute        = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError  = true
                }
            };

            p.Start();

            if (Main.IsDebug)
            {
                var output = p.StandardOutput.ReadToEnd();
                if (output.Length > 0)
                {
                    UnityEngine.Debug.Log("Wakatime Output: " + output);
                }

                var errors = p.StandardError.ReadToEnd();
                if (errors.Length > 0)
                {
                    UnityEngine.Debug.LogError("Wakatime Error: " + errors);
                }
            }

            p.Close();
        }
Example #12
0
 static public void DownloadAndInstall()
 {
     if (!PythonManager.IsPythonInstalled())
     {
         if (!IsDownloaded())
         {
             Download();
         }
         else
         {
             Install();
         }
     }
 }
Example #13
0
        public static bool CheckPython()
        {
            bool isInstalled = PythonManager.IsPythonInstalled();

            if (IsEnabled && !isInstalled && !PythonInstaller.IsInstalling())
            {
                if (EditorUtility.DisplayDialog("Python is required", "The plugin is about to install Python. Do you want to continue?", "Install Python", "Disable Wakatime"))
                {
                    PythonInstaller.DownloadAndInstall();
                }
                else
                {
                    IsEnabled = false;
                }
            }

            return(isInstalled);
        }
Example #14
0
        private static void InitializeWakaTimeAsync()
        {
            // Make sure python is installed
            if (!PythonManager.IsPythonInstalled())
            {
                Downloader.DownloadAndInstallPython();
            }

            if (!DoesCliExist() || !IsCliLatestVersion())
            {
                Downloader.DownloadAndInstallCli();
            }

            if (string.IsNullOrEmpty(ApiKey))
            {
                PromptApiKey();
            }
        }
Example #15
0
        /// <summary>
        /// Sends a heart-beat to wakatime.
        /// Only works if the client is not installed.
        /// </summary>
        /// <param name="apiKey"></param>
        /// <param name="projectName"></param>
        /// <param name="file"></param>
        /// <param name="dataPath"></param>
        /// <param name="clientPath"></param>
        protected static void MakeRequest(string apiKey, string file, string projectName, string dataPath, string clientPath)
        {
            try
            {
                string arguments = "--key " + apiKey +
                                   " --file " + "\"" + file + "\"" +
                                   " --plugin " + WakaTimeConstants.PLUGIN_NAME +
                                   " --project " + "\"" + projectName + "\"" +
                                   " --verbose";

                if (Main.IsDebug)
                {
                    UnityEngine.Debug.Log("[wakatime] Sending file: " + file);
                }

                Process p = new Process
                {
                    StartInfo =
                    {
                        FileName               = PythonManager.GetPythonPath(),
                        Arguments              = "\"" + clientPath + "\" " + arguments,
                        CreateNoWindow         = true,
                        WindowStyle            = ProcessWindowStyle.Hidden,
                        WorkingDirectory       = dataPath,
                        UseShellExecute        = false,
                        RedirectStandardOutput = true,
                        RedirectStandardError  = true,
                    }
                };

                p.Start();
                p.WaitForExit(5000);

                UnityEngine.Debug.Log("[wakatime] Finished sending file " + file);
            }
            catch (Exception ex)
            {
                if (Main.IsDebug)
                {
                    UnityEngine.Debug.LogError("[wakatime] Error found while sending heartbeat to wakatime for file " + file + ": " + ex);
                }
            }
        }
        public static void HeartBeat(string apiKey, string file, bool write = false)
        {
            if (PythonManager.IsPythonInstalled())
            {
                string arguments = "--key " + apiKey
                                   + " --file " + file
                                   + " --plugin " + WakaTimeConstants.PLUGIN_NAME
                                   + " --project " + Main.GetProjectName()
                                   + " --verbose";

                if (Main.IsDebug)
                {
                    UnityEngine.Debug.Log("Sending file: " + PythonManager.GetPythonPath() + " " + GetClientPath() + " " + arguments);
                }

                Process p = new Process();
                p.StartInfo.FileName  = PythonManager.GetPythonPath();
                p.StartInfo.Arguments = GetClientPath() + " " + arguments;

                p.StartInfo.CreateNoWindow = true;
                p.StartInfo.WindowStyle    = ProcessWindowStyle.Hidden;

                p.StartInfo.WorkingDirectory = Application.dataPath;

#if UNITY_EDITOR_WIN
                p.StartInfo.UseShellExecute = true;
#else
                p.StartInfo.UseShellExecute = false;
#endif


                p.Start();

//			UnityEngine.Debug.Log (p.StandardOutput.ReadToEnd ());
//			UnityEngine.Debug.Log (p.StandardError.ReadToEnd ());

                p.Close();
            }
        }
Example #17
0
 public void CheckPrerequisites()
 {
     PythonManager.Initialize();
 }
Example #18
0
 static string GetFilePath()
 {
     return(GetFileFolder() + PythonManager.GetPythonFileName());
 }
        public void InitializeAsync()
        {
            try
            {
                Logger.Info(string.Format("Initializing WakaTime v{0}", WakaTimeConstants.PluginVersion));

                // VisualStudio Object
                objDte          = (DTE2)GetService(typeof(DTE));
                _docEvents      = objDte.Events.DocumentEvents;
                _windowEvents   = objDte.Events.WindowEvents;
                _solutionEvents = objDte.Events.SolutionEvents;

                // Settings Form
                _settingsForm              = new SettingsForm();
                _settingsForm.ConfigSaved += SettingsFormOnConfigSaved;

                // Load config file
                _wakaTimeConfigFile = new WakaTimeConfigFile();
                GetSettings();

                try
                {
                    // Make sure python is installed
                    if (!PythonManager.IsPythonInstalled())
                    {
                        Downloader.DownloadAndInstallPython();
                    }

                    if (!DoesCliExist() || !IsCliLatestVersion())
                    {
                        try
                        {
                            Directory.Delete(Path.Combine(WakaTimeConstants.UserConfigDir, "wakatime-master"), true);
                        }
                        catch { /* ignored */ }

                        Downloader.DownloadAndInstallCli();
                    }
                }
                catch (System.Net.WebException ex)
                {
                    Logger.Error("Are you behind a proxy? Try setting a proxy in WakaTime Settings with format https://user:pass@host:port. Exception Traceback:", ex);
                }

                if (string.IsNullOrEmpty(ApiKey))
                {
                    PromptApiKey();
                }

                // Add our command handlers for menu (commands must exist in the .vsct file)
                var mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
                if (mcs != null)
                {
                    // Create the command for the menu item.
                    var menuCommandId = new CommandID(GuidList.GuidWakaTimeCmdSet, (int)PkgCmdIdList.UpdateWakaTimeSettings);
                    var menuItem      = new MenuCommand(MenuItemCallback, menuCommandId);
                    mcs.AddCommand(menuItem);
                }

                // setup event handlers
                _docEvents.DocumentOpened     += DocEventsOnDocumentOpened;
                _docEvents.DocumentSaved      += DocEventsOnDocumentSaved;
                _windowEvents.WindowActivated += WindowEventsOnWindowActivated;
                _solutionEvents.Opened        += SolutionEventsOnOpened;

                Logger.Info(string.Format("Finished initializing WakaTime v{0}", WakaTimeConstants.PluginVersion));
            }
            catch (Exception ex)
            {
                Logger.Error("Error initializing Wakatime", ex);
            }
        }
Example #20
0
        public void InitializeAsync()
        {
            _version = string.Format("{0}.{1}.{2}", CoreAssembly.Version.Major, CoreAssembly.Version.Minor, CoreAssembly.Version.Build);

            try
            {
                Logger.Info(string.Format("Initializing WakaTime v{0}", _version));

                base.Initialize();

                _objDte                    = (DTE2)GetService(typeof(DTE));
                _docEvents                 = _objDte.Events.DocumentEvents;
                _windowEvents              = _objDte.Events.WindowEvents;
                _solutionEvents            = _objDte.Events.SolutionEvents;
                _editorVersion             = _objDte.Version;
                _settingsForm              = new SettingsForm();
                _settingsForm.ConfigSaved += SettingsFormOnConfigSaved;
                _wakaTimeConfigFile        = new WakaTimeConfigFile();

                // Make sure python is installed
                if (!PythonManager.IsPythonInstalled())
                {
                    var dialogResult = MessageBox.Show(@"Let's download and install Python now?",
                                                       @"WakaTime requires Python", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                    if (dialogResult == DialogResult.Yes)
                    {
                        var url = PythonManager.PythonDownloadUrl;
                        Downloader.DownloadPython(url, WakaTimeConstants.UserConfigDir);
                    }
                    else
                    {
                        MessageBox.Show(
                            @"Please install Python (https://www.python.org/downloads/) and restart Visual Studio to enable the WakaTime plugin.",
                            @"WakaTime", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }

                if (!DoesCliExist() || !IsCliLatestVersion())
                {
                    try
                    {
                        Directory.Delete(string.Format("{0}\\wakatime-master", WakaTimeConstants.UserConfigDir), true);
                    }
                    catch { /* ignored */ }

                    Downloader.DownloadCli(WakaTimeConstants.CliUrl, WakaTimeConstants.UserConfigDir);
                }

                GetSettings();

                if (string.IsNullOrEmpty(ApiKey))
                {
                    PromptApiKey();
                }

                // Add our command handlers for menu (commands must exist in the .vsct file)
                var mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
                if (mcs != null)
                {
                    // Create the command for the menu item.
                    var menuCommandId = new CommandID(GuidList.GuidWakaTimeCmdSet, (int)PkgCmdIdList.UpdateWakaTimeSettings);
                    var menuItem      = new MenuCommand(MenuItemCallback, menuCommandId);
                    mcs.AddCommand(menuItem);
                }

                // setup event handlers
                _docEvents.DocumentOpened     += DocEventsOnDocumentOpened;
                _docEvents.DocumentSaved      += DocEventsOnDocumentSaved;
                _windowEvents.WindowActivated += WindowEventsOnWindowActivated;
                _solutionEvents.Opened        += SolutionEventsOnOpened;

                Logger.Info(string.Format("Finished initializing WakaTime v{0}", _version));
            }
            catch (Exception ex)
            {
                Logger.Error("Error initializing Wakatime", ex);
            }
        }
Example #21
0
        private static void ProcessHeartbeats()
        {
            var pythonBinary = PythonManager.GetPython();

#if NET35
            if (pythonBinary == null || string.IsNullOrEmpty(pythonBinary.Trim()))
#else
            if (string.IsNullOrWhiteSpace(pythonBinary))
#endif
            {
                Logger.Error("Could not send heartbeat because python is not installed");
                return;
            }

            // get first heartbeat from queue
            var gotOne = heartbeatQueue.TryDequeue(out Heartbeat heartbeat);
            if (!gotOne)
            {
                return;
            }

            // remove all extra heartbeats from queue
            var extraHeartbeats = new List <Heartbeat>();
            while (heartbeatQueue.TryDequeue(out Heartbeat hbOut))
            {
                extraHeartbeats.Add(hbOut.Clone());
            }

            var hasExtraHeartbeats = extraHeartbeats.Any();
            var cliParams          = new PythonCliParameters
            {
                Key                = WakaTimeConfigFile.ApiKey,
                Plugin             = string.Format("{0}/{1} {2}/{3}", editorInfo.Name, editorInfo.Version, editorInfo.PluginKey, editorInfo.PluginVersion),
                File               = heartbeat.FileName,
                Time               = heartbeat.Timestamp,
                IsWrite            = heartbeat.IsWrite,
                HasExtraHeartbeats = hasExtraHeartbeats,
            };

            string extraHeartbeatsJSON = null;
            if (hasExtraHeartbeats)
            {
#if NET45
                var serializer = new JavaScriptSerializer();
                serializer.RegisterConverters(new JavaScriptConverter[] { new DataContractJavaScriptConverter(true) });
                extraHeartbeatsJSON = serializer.Serialize(extraHeartbeats);
#else
                extraHeartbeatsJSON = JsonConvert.SerializeObject(extraHeartbeats, Formatting.None);
#endif
            }

            var process = new RunProcess(pythonBinary, cliParams.ToArray());
            if (WakaTimeConfigFile.Debug)
            {
                Logger.Debug(string.Format("[\"{0}\", \"{1}\"]", pythonBinary, string.Join("\", \"", cliParams.ToArray(true))));
                process.Run(extraHeartbeatsJSON);
                if (process.Output != null && process.Output != "")
                {
                    Logger.Debug(process.Output);
                }
                if (process.Error != null && process.Error != "")
                {
                    Logger.Debug(process.Error);
                }
            }
            else
            {
                process.RunInBackground(extraHeartbeatsJSON);
            }

            if (!process.Success)
            {
                Logger.Error("Could not send heartbeat.");
                if (process.Output != null && process.Output != "")
                {
                    Logger.Error(process.Output);
                }
                if (process.Error != null && process.Error != "")
                {
                    Logger.Error(process.Error);
                }
            }
        }
Example #22
0
        /// <summary>Implements the OnConnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being loaded.</summary>
        /// <param term='application'>Root object of the host application.</param>
        /// <param term='connectMode'>Describes how the Add-in is being loaded.</param>
        /// <param term='addInInst'>Object representing this Add-in.</param>
        /// <seealso class='IDTExtensibility2' />
        public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
        {
            Logger.Info(string.Format("Initializing WakaTime v{0}", _version));

            try
            {
                _applicationObject = (DTE2)application;
                _addInInstance     = (AddIn)addInInst;

                _editorVersion                  = _applicationObject.Version;
                _docEvents                      = _applicationObject.Events.DocumentEvents;
                _docEvents.DocumentOpened      += DocEventsOnDocumentOpened;
                _docEvents.DocumentSaved       += DocEventsOnDocumentSaved;
                _windowsEvents                  = _applicationObject.Events.WindowEvents;
                _windowsEvents.WindowActivated += WindowsEventsOnWindowActivated;

                if (connectMode == ext_ConnectMode.ext_cm_UISetup)
                {
                    object[]  contextGUIDS  = new object[] { };
                    Commands2 commands      = (Commands2)_applicationObject.Commands;
                    string    toolsMenuName = "Tools";

                    //Place the command on the tools menu.
                    //Find the MenuBar command bar, which is the top-level command bar holding all the main menu items:
                    CommandBar menuBarCommandBar = ((CommandBars)_applicationObject.CommandBars)["MenuBar"];

                    //Find the Tools command bar on the MenuBar command bar:
                    CommandBarControl toolsControl = menuBarCommandBar.Controls[toolsMenuName];
                    CommandBarPopup   toolsPopup   = (CommandBarPopup)toolsControl;

                    //This try/catch block can be duplicated if you wish to add multiple commands to be handled by your Add-in,
                    //  just make sure you also update the QueryStatus/Exec method to include the new command names.
                    try
                    {
                        //Add a command to the Commands collection:
                        Command command = commands.AddNamedCommand2(_addInInstance, "WakaTime", "WakaTime", "WakaTime Settings", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);

                        //Add a control for the command to the tools menu:
                        if ((command != null) && (toolsPopup != null))
                        {
                            command.AddControl(toolsPopup.CommandBar, 1);
                        }
                    }
                    catch (ArgumentException)
                    {
                        //If we are here, then the exception is probably because a command with that name
                        //  already exists. If so there is no need to recreate the command and we can
                        //  safely ignore the exception.
                    }
                }

                // Make sure python is installed
                if (!PythonManager.IsPythonInstalled())
                {
                    var url = PythonManager.PythonDownloadUrl;
                    Downloader.DownloadPython(url, WakaTimeConstants.UserConfigDir);
                }

                if (!DoesCliExist() || !IsCliLatestVersion())
                {
                    try
                    {
                        Directory.Delete(string.Format("{0}\\wakatime-master", WakaTimeConstants.UserConfigDir), true);
                    }
                    catch { /* ignored */ }

                    Downloader.DownloadCli(WakaTimeConstants.CliUrl, WakaTimeConstants.UserConfigDir);
                }

                GetSettings();

                if (string.IsNullOrEmpty(ApiKey))
                {
                    PromptApiKey();
                }

                Logger.Info(string.Format("Finished initializing WakaTime v{0}", _version));
            }
            catch (Exception ex)
            {
                Logger.Error("Error initializing Wakatime", ex);
            }
        }