IDictionary<string, object> GetCurrentBadgeInfo()
        {
            #if DEBUG
            if (UIService.IsUIThread)
                throw new InvalidOperationException("For performance reasons this method should never be called on UI thread.");
            #endif

            var result = new CurrentVSStateInfo();

            Dictionary<string, object> properties = new Dictionary<string, object>();

            var dte2 = ServiceProvider.GetDte2();

            var solution = dte2.Solution;

            if (solution != null)
            {
                var solutionBuild = solution.SolutionBuild;

                if (solutionBuild != null)
                {
                    var activeConfig = solutionBuild.ActiveConfiguration as SolutionConfiguration2;

                    if (activeConfig != null)
                    {
                        properties["sln:activeConfig"] = activeConfig.Name;
                        properties["sln:activePlatform"] = activeConfig.PlatformName;
                    }
                }
            }

            var activeDocument = dte2.GetActiveDocument();

            if (activeDocument == null
                || activeDocument.FullName.IsNullOrEmpty())
            {
                properties["activeDocument:fileName"] = "";
                properties["activeDocument:fullPath"] = "";
            }
            else
            {
                var active_document_path = activeDocument.Name;

                properties["activeDocument:fullPath"] = active_document_path;
                properties["activeDocument:fileName"] = Path.GetFileName(activeDocument.Name);
            }

            var solution_full_path = solution.FullName;

            if (solution_full_path == string.Empty)
            {
                properties["sln:isOpen"] = false;
            }
            else
            {
                properties["sln:isOpen"] = true;

                // todo:    allow user to override solution name
                //var custom_solution_name = SettingsService.GetSetting<string>("SolutionBadges.SolutionName", VscSettingScope.Solution, () => null);

                properties["sln:fullPath"] = solution_full_path;
                properties["sln:fileName"] = Path.GetFileNameWithoutExtension(solution_full_path);
            }

            foreach(var scip in SourceControlInfoProviders)
            {
                var sc_properties = (IDictionary<string, object>)null;

                try
                {
                    if (scip.TryGetSourceControlInfo(solution.FullName, out sc_properties))
                    {
                        properties.AddOrUpdateFrom(sc_properties);
                    }
                }
                catch(Exception ex)
                {
                    // todo: log
                }
            }

            return properties;
        }
        IDictionary <string, object> GetCurrentBadgeInfo()
        {
#if DEBUG
            if (UIService.IsUIThread)
            {
                throw new InvalidOperationException("For performance reasons this method should never be called on UI thread.");
            }
#endif

            var result = new CurrentVSStateInfo();

            Dictionary <string, object> properties = new Dictionary <string, object>();

            var dte2 = ServiceProvider.GetDte2();

            var solution = dte2.Solution;

            if (solution != null)
            {
                var solutionBuild = solution.SolutionBuild;

                if (solutionBuild != null)
                {
                    var activeConfig = solutionBuild.ActiveConfiguration as SolutionConfiguration2;

                    if (activeConfig != null)
                    {
                        properties["sln:activeConfig"]   = activeConfig.Name;
                        properties["sln:activePlatform"] = activeConfig.PlatformName;
                    }
                }
            }

            var activeDocument = dte2.GetActiveDocument();

            if (activeDocument == null ||
                activeDocument.FullName.IsNullOrEmpty())
            {
                properties["activeDocument:fileName"] = "";
                properties["activeDocument:fullPath"] = "";
            }
            else
            {
                var active_document_path = activeDocument.Name;

                properties["activeDocument:fullPath"] = active_document_path;
                properties["activeDocument:fileName"] = Path.GetFileName(activeDocument.Name);
            }

            var solution_full_path = solution.FullName;

            if (solution_full_path == string.Empty)
            {
                properties["sln:isOpen"] = false;
            }
            else
            {
                properties["sln:isOpen"] = true;

                // todo:    allow user to override solution name
                //var custom_solution_name = SettingsService.GetSetting<string>("SolutionBadges.SolutionName", VscSettingScope.Solution, () => null);

                properties["sln:fullPath"] = solution_full_path;
                properties["sln:fileName"] = Path.GetFileNameWithoutExtension(solution_full_path);
            }

            foreach (var scip in SourceControlInfoProviders)
            {
                var sc_properties = (IDictionary <string, object>)null;

                try
                {
                    if (scip.TryGetSourceControlInfo(solution.FullName, out sc_properties))
                    {
                        properties.AddOrUpdateFrom(sc_properties);
                    }
                }
                catch (Exception ex)
                {
                    // todo: log
                }
            }

            return(properties);
        }