예제 #1
0
        string GetVSVersion()
        {
            var version = VisualStudio.Services.Dte.Version;
            var keyPath = String.Format(CultureInfo.InvariantCulture, "{0}\\{1}_Config\\SplashInfo", RegistryRootKey, version);

            try
            {
                using (var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(keyPath))
                {
                    var value = (string)key.GetValue(EnvVersionKey, String.Empty);
                    if (!String.IsNullOrEmpty(value))
                    {
                        return(value);
                    }
                }
                var asm = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName.StartsWith("Microsoft.VisualStudio.CommonIDE", StringComparison.OrdinalIgnoreCase));
                if (asm != null)
                {
                    return(asm.GetName().Version.ToString());
                }
            }
            catch (Exception ex)
            {
                VsOutputLogger.WriteLine(string.Format(CultureInfo.CurrentCulture, "Error getting the Visual Studio version '{0}'", ex));
            }
            return(version);
        }
예제 #2
0
        void EnsureAssemblyLoaded(Uri value)
        {
            try
            {
                var assemblyName = FindAssemblyNameFromPackUri(value);
                if (assemblyName == null)
                {
                    VsOutputLogger.WriteLine(String.Format(CultureInfo.InvariantCulture, "Couldn't find assembly name in '{0}'.", value));
                    return;
                }

                var baseDir      = Path.GetDirectoryName(GetType().Assembly.Location);
                var assemblyFile = Path.Combine(baseDir, assemblyName + ".dll");
                if (assemblyDicts.ContainsKey(assemblyFile))
                {
                    return;
                }

                if (!File.Exists(assemblyFile))
                {
                    VsOutputLogger.WriteLine(String.Format(CultureInfo.InvariantCulture, "Couldn't find assembly at '{0}'.", assemblyFile));
                    return;
                }

                var assembly = Assembly.LoadFrom(assemblyFile);
                assemblyDicts.Add(assemblyFile, assembly);
            }
            catch (Exception e)
            {
                VsOutputLogger.WriteLine(String.Format(CultureInfo.InvariantCulture, "Error loading assembly for '{0}': {1}", value, e));
            }
        }
예제 #3
0
 static IEnumerable <ISimpleRepositoryModel> PokeTheRegistryForRepositoryList()
 {
     using (var key = OpenGitKey("Repositories"))
     {
         return(key.GetSubKeyNames().Select(x =>
         {
             using (var subkey = key.OpenSubKey(x))
             {
                 try
                 {
                     var path = subkey?.GetValue("Path") as string;
                     if (path != null)
                     {
                         return new SimpleRepositoryModel(path);
                     }
                 }
                 catch (Exception ex)
                 {
                     VsOutputLogger.WriteLine(string.Format(CultureInfo.CurrentCulture, "Error loading the repository from the registry '{0}'", ex));
                 }
                 return null;
             }
         })
                .Where(x => x != null)
                .ToList());
     }
 }
예제 #4
0
        static Assembly LoadAssemblyFromRunDir(object sender, ResolveEventArgs e)
        {
            try
            {
                var requestedName = e.Name.TrimSuffix(".dll", StringComparison.OrdinalIgnoreCase);
                var name          = new AssemblyName(requestedName).Name;
                if (!ourAssemblies.Contains(name, StringComparer.OrdinalIgnoreCase))
                {
                    return(null);
                }
                var path     = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                var filename = Path.Combine(path, name + ".dll");
                if (!File.Exists(filename))
                {
                    return(null);
                }

                return(Assembly.LoadFrom(filename));
            }
            catch (Exception ex)
            {
                var log = string.Format(CultureInfo.CurrentCulture,
                                        "Error occurred loading {0} from {1}.{2}{3}{4}",
                                        e.Name,
                                        Assembly.GetExecutingAssembly().Location,
                                        Environment.NewLine,
                                        ex,
                                        Environment.NewLine);
                VsOutputLogger.Write(log);
            }
            return(null);
        }
예제 #5
0
 static Assembly LoadAssemblyFromRunDir(object sender, ResolveEventArgs e)
 {
     try
     {
         var name = new AssemblyName(e.Name);
         if (!ourAssemblies.Contains(name.Name))
         {
             return(null);
         }
         //if (name.Name.Equals("GitHub.TeamFoundation", StringComparison.Ordinal))
         //    name = new AssemblyName("GitHub.TeamFoundation." + VSVersion);
         var path     = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
         var filename = Path.Combine(path, name.Name + ".dll");
         if (!File.Exists(filename))
         {
             return(null);
         }
         return(Assembly.LoadFrom(filename));
     }
     catch (Exception ex)
     {
         var log = string.Format(CultureInfo.CurrentCulture, "Error occurred loading {0} from {1}.{2}{3}{4}", e.Name, Assembly.GetExecutingAssembly().Location, Environment.NewLine, ex, Environment.NewLine);
         VsOutputLogger.Write(log);
     }
     return(null);
 }
예제 #6
0
        public static GitHubPane Activate()
        {
            var windowGuid = new Guid(GitHubPaneGuid);

            IVsWindowFrame frame;

            if (ErrorHandler.Failed(Services.UIShell.FindToolWindow((uint)__VSCREATETOOLWIN.CTW_fForceCreate, ref windowGuid, out frame)))
            {
                VsOutputLogger.WriteLine("Unable to find or create GitHubPane '" + GitHubPaneGuid + "'");
                return(null);
            }
            if (ErrorHandler.Failed(frame.Show()))
            {
                VsOutputLogger.WriteLine("Unable to show GitHubPane '" + GitHubPaneGuid + "'");
                return(null);
            }

            object docView = null;

            if (ErrorHandler.Failed(frame.GetProperty((int)__VSFPROPID.VSFPROPID_DocView, out docView)))
            {
                VsOutputLogger.WriteLine("Unable to grab instance of GitHubPane '" + GitHubPaneGuid + "'");
                return(null);
            }
            return(docView as GitHubPane);
        }
예제 #7
0
        string GetVSVersion()
        {
            var version = typeof(Microsoft.VisualStudio.Shell.ActivityLog).Assembly.GetName().Version;
            var keyPath = String.Format(CultureInfo.InvariantCulture, "{0}\\{1}.{2}_Config\\SplashInfo", RegistryRootKey, version.Major, version.Minor);

            try
            {
                using (var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(keyPath))
                {
                    var value = (string)key.GetValue(EnvVersionKey, String.Empty);
                    if (!String.IsNullOrEmpty(value))
                    {
                        return(value);
                    }
                }
                // fallback to poking the CommonIDE assembly, which most closely follows the advertised version.
                var asm = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName.StartsWith("Microsoft.VisualStudio.CommonIDE", StringComparison.OrdinalIgnoreCase));
                if (asm != null)
                {
                    return(asm.GetName().Version.ToString());
                }
            }
            catch (Exception ex)
            {
                VsOutputLogger.WriteLine(string.Format(CultureInfo.CurrentCulture, "Error getting the Visual Studio version '{0}'", ex));
            }
            return(version.ToString());
        }
            void TrackState(object sender, PropertyChangedEventArgs e)
            {
                if (machine.PermittedTriggers.Contains(e.PropertyName))
                {
#if DEBUG
                    VsOutputLogger.WriteLine(String.Format(CultureInfo.InvariantCulture, "{3} {0} title:{1} busy:{2}", e.PropertyName, ((ITeamExplorerSection)sender).Title, ((ITeamExplorerSection)sender).IsBusy, DateTime.Now));
#endif
                    machine.Fire(e.PropertyName);
                }
            }
예제 #9
0
        public string SetDefaultProjectPath(string path)
        {
            var old = String.Empty;

            try
            {
                var newProjectKey = Registry.CurrentUser.OpenSubKey(NewProjectDialogKeyPath, true) ??
                                    Registry.CurrentUser.CreateSubKey(NewProjectDialogKeyPath);
                Debug.Assert(newProjectKey != null, string.Format(CultureInfo.CurrentCulture, "Could not open or create registry key '{0}'", NewProjectDialogKeyPath));

                using (newProjectKey)
                {
                    var mruKey = newProjectKey.OpenSubKey(MRUKeyPath, true) ??
                                 Registry.CurrentUser.CreateSubKey(MRUKeyPath);
                    Debug.Assert(mruKey != null, string.Format(CultureInfo.CurrentCulture, "Could not open or create registry key '{0}'", MRUKeyPath));

                    using (mruKey)
                    {
                        // is this already the default path? bail
                        old = (string)mruKey.GetValue("Value0", string.Empty, RegistryValueOptions.DoNotExpandEnvironmentNames);
                        if (String.Equals(path.TrimEnd('\\'), old.TrimEnd('\\'), StringComparison.CurrentCultureIgnoreCase))
                        {
                            return(old);
                        }

                        // grab the existing list of recent paths, throwing away the last one
                        var numEntries = (int)mruKey.GetValue("MaximumEntries", 5);
                        var entries    = new List <string>(numEntries);
                        for (int i = 0; i < numEntries - 1; i++)
                        {
                            var val = (string)mruKey.GetValue("Value" + i, String.Empty, RegistryValueOptions.DoNotExpandEnvironmentNames);
                            if (!String.IsNullOrEmpty(val))
                            {
                                entries.Add(val);
                            }
                        }

                        newProjectKey.SetValue("LastUsedNewProjectPath", path);
                        mruKey.SetValue("Value0", path);
                        // bump list of recent paths one entry down
                        for (int i = 0; i < entries.Count; i++)
                        {
                            mruKey.SetValue("Value" + (i + 1), entries[i]);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                VsOutputLogger.WriteLine(string.Format(CultureInfo.CurrentCulture, "Error setting the create project path in the registry '{0}'", ex));
            }
            return(old);
        }
예제 #10
0
 public IEnumerable <ILocalRepositoryModel> GetKnownRepositories()
 {
     try
     {
         return(RegistryHelper.PokeTheRegistryForRepositoryList());
     }
     catch (Exception ex)
     {
         VsOutputLogger.WriteLine(string.Format(CultureInfo.CurrentCulture, "Error loading the repository list from the registry '{0}'", ex));
         return(Enumerable.Empty <ILocalRepositoryModel>());
     }
 }
예제 #11
0
        // The Default Repository Path that VS uses is hidden in an internal
        // service 'ISccSettingsService' registered in an internal service
        // 'ISccServiceHost' in an assembly with no public types that's
        // always loaded with VS if the git service provider is loaded
        public string GetLocalClonePathFromGitProvider()
        {
            string ret = string.Empty;

            try
            {
                ret = RegistryHelper.PokeTheRegistryForLocalClonePath();
            }
            catch (Exception ex)
            {
                VsOutputLogger.WriteLine(string.Format(CultureInfo.CurrentCulture, "Error loading the default cloning path from the registry '{0}'", ex));
            }
            return(ret);
        }
예제 #12
0
        public static bool Activate()
        {
            var            windowGuid = new Guid(GitHubPaneGuid);
            IVsWindowFrame frame;

            if (ErrorHandler.Failed(Services.UIShell.FindToolWindow((uint)__VSCREATETOOLWIN.CTW_fForceCreate, ref windowGuid, out frame)))
            {
                VsOutputLogger.WriteLine("Unable to find or create GitHubPane '" + GitHubPaneGuid + "'");
                return(false);
            }
            if (ErrorHandler.Failed(frame.Show()))
            {
                VsOutputLogger.WriteLine("Unable to show GitHubPane '" + GitHubPaneGuid + "'");
                return(false);
            }
            return(true);
        }
예제 #13
0
        void ShowNotification(ILocalRepositoryModel newrepo, string msg)
        {
            Guard.ArgumentNotNull(newrepo, nameof(newrepo));

            var teServices = ServiceProvider.TryGetService <ITeamExplorerServices>();

            teServices.ClearNotifications();
            teServices.ShowMessage(
                msg,
                new RelayCommand(o =>
            {
                var str = o.ToString();

                /* the prefix is the action to perform:
                 * u: launch browser with url
                 * c: launch create new project dialog
                 * o: launch open existing project dialog
                 */
                var prefix = str.Substring(0, 2);
                if (prefix == "u:")
                {
                    OpenInBrowser(ServiceProvider.TryGetService <IVisualStudioBrowser>(), new Uri(str.Substring(2)));
                }
                else if (prefix == "o:")
                {
                    if (ErrorHandler.Succeeded(ServiceProvider.GetSolution().OpenSolutionViaDlg(str.Substring(2), 1)))
                    {
                        ServiceProvider.TryGetService <ITeamExplorer>()?.NavigateToPage(new Guid(TeamExplorerPageIds.Home), null);
                    }
                }
                else if (prefix == "c:")
                {
                    var vsGitServices = ServiceProvider.TryGetService <IVSGitServices>();
                    vsGitServices.SetDefaultProjectPath(newrepo.LocalPath);
                    if (ErrorHandler.Succeeded(ServiceProvider.GetSolution().CreateNewProjectViaDlg(null, null, 0)))
                    {
                        ServiceProvider.TryGetService <ITeamExplorer>()?.NavigateToPage(new Guid(TeamExplorerPageIds.Home), null);
                    }
                }
            })
                );
#if DEBUG
            VsOutputLogger.WriteLine(String.Format(CultureInfo.InvariantCulture, "{0} Notification", DateTime.Now));
#endif
        }
예제 #14
0
        void TryCleanupSolutionUserFiles(IOperatingSystem os, string repoPath, string slnName)
        {
            var vsTempPath = Path.Combine(repoPath, ".vs", slnName);

            try
            {
                // Clean up the dummy solution's subdirectory inside `.vs`.
                var vsTempDir = os.Directory.GetDirectory(vsTempPath);
                if (vsTempDir.Exists)
                {
                    vsTempDir.Delete(true);
                }
            }
            catch (Exception e)
            {
                VsOutputLogger.WriteLine("Couldn't clean up {0}. {1}", vsTempPath, e);
            }
        }
예제 #15
0
        /// <summary>Open a repository in Team Explorer</summary>
        /// <remarks>
        /// There doesn't appear to be a command that directly opens a target repo.
        /// Our workaround is to create, open and delete a solution in the repo directory.
        /// This triggers an event that causes the target repo to open. ;)
        /// </remarks>
        /// <param name="repoPath">The path to the repository to open</param>
        /// <returns>True if a transient solution was successfully created in target directory (which should trigger opening of repository).</returns>
        public bool TryOpenRepository(string repoPath)
        {
            var os = serviceProvider.TryGetService <IOperatingSystem>();

            if (os == null)
            {
                VsOutputLogger.WriteLine("TryOpenRepository couldn't find IOperatingSystem service.");
                return(false);
            }

            var dte = serviceProvider.TryGetService <DTE>();

            if (dte == null)
            {
                VsOutputLogger.WriteLine("TryOpenRepository couldn't find DTE service.");
                return(false);
            }

            var repoDir = os.Directory.GetDirectory(repoPath);

            if (!repoDir.Exists)
            {
                return(false);
            }

            bool solutionCreated = false;

            try
            {
                dte.Solution.Create(repoPath, TempSolutionName);
                solutionCreated = true;

                dte.Solution.Close(false); // Don't create a .sln file when we close.
            }
            catch (Exception e)
            {
                VsOutputLogger.WriteLine("Error opening repository. {0}", e);
            }
            finally
            {
                TryCleanupSolutionUserFiles(os, repoPath, TempSolutionName);
            }
            return(solutionCreated);
        }
        async void UIContextChanged(bool active, bool refresh)
        {
            Debug.Assert(ServiceProvider != null, "UIContextChanged called before service provider is set");
            if (ServiceProvider == null)
            {
                return;
            }

            if (active)
            {
                GitService = GitService ?? ServiceProvider.GetServiceSafe <IGitExt>();
                if (ActiveRepo == null || refresh)
                {
                    ActiveRepo = await System.Threading.Tasks.Task.Run(() =>
                    {
                        var repos = GitService?.ActiveRepositories;
                        // Looks like this might return null after a while, for some unknown reason
                        // if it does, let's refresh the GitService instance in case something got wonky
                        // and try again. See issue #23
                        if (repos == null)
                        {
                            VsOutputLogger.WriteLine(string.Format(CultureInfo.CurrentCulture, "Error 2001: ActiveRepositories is null. GitService: '{0}'", GitService));
                            GitService = ServiceProvider?.GetServiceSafe <IGitExt>();
                            repos      = GitService?.ActiveRepositories;
                            if (repos == null)
                            {
                                VsOutputLogger.WriteLine(string.Format(CultureInfo.CurrentCulture, "Error 2002: ActiveRepositories is null. GitService: '{0}'", GitService));
                            }
                        }
                        return(repos?.FirstOrDefault()?.ToModel());
                    });
                }
            }
            else
            {
                ActiveRepo = null;
            }
        }
예제 #17
0
        /// <summary>
        /// Gets the currently active text view(s) from Visual Studio.
        /// </summary>
        /// <returns>
        /// Zero, one or two active <see cref="ITextView"/> objects.
        /// </returns>
        /// <remarks>
        /// This method will return a single text view for a normal code window, or a pair of text
        /// views if the currently active text view is a difference view in side by side mode, with
        /// the first item being the side that currently has focus. If there is no active text view,
        /// an empty collection will be returned.
        /// </remarks>
        protected IEnumerable <ITextView> GetCurrentTextViews()
        {
            var result = new List <ITextView>();

            try
            {
                var serviceProvider  = Package;
                var monitorSelection = (IVsMonitorSelection)serviceProvider.GetService(typeof(SVsShellMonitorSelection));
                if (monitorSelection == null)
                {
                    return(result);
                }

                object curDocument;
                if (ErrorHandler.Failed(monitorSelection.GetCurrentElementValue((uint)VSConstants.VSSELELEMID.SEID_DocumentFrame, out curDocument)))
                {
                    return(result);
                }

                IVsWindowFrame frame = curDocument as IVsWindowFrame;
                if (frame == null)
                {
                    return(result);
                }

                object docView = null;
                if (ErrorHandler.Failed(frame.GetProperty((int)__VSFPROPID.VSFPROPID_DocView, out docView)))
                {
                    return(result);
                }

                if (docView is IVsDifferenceCodeWindow)
                {
                    var diffWindow = (IVsDifferenceCodeWindow)docView;

                    switch (diffWindow.DifferenceViewer.ViewMode)
                    {
                    case DifferenceViewMode.Inline:
                        result.Add(diffWindow.DifferenceViewer.InlineView);
                        break;

                    case DifferenceViewMode.SideBySide:
                        switch (diffWindow.DifferenceViewer.ActiveViewType)
                        {
                        case DifferenceViewType.LeftView:
                            result.Add(diffWindow.DifferenceViewer.LeftView);
                            result.Add(diffWindow.DifferenceViewer.RightView);
                            break;

                        case DifferenceViewType.RightView:
                            result.Add(diffWindow.DifferenceViewer.RightView);
                            result.Add(diffWindow.DifferenceViewer.LeftView);
                            break;
                        }
                        result.Add(diffWindow.DifferenceViewer.LeftView);
                        break;

                    case DifferenceViewMode.RightViewOnly:
                        result.Add(diffWindow.DifferenceViewer.RightView);
                        break;
                    }
                }
                else if (docView is IVsCodeWindow)
                {
                    IVsTextView textView;
                    if (ErrorHandler.Failed(((IVsCodeWindow)docView).GetPrimaryView(out textView)))
                    {
                        return(result);
                    }

                    var model          = (IComponentModel)serviceProvider.GetService(typeof(SComponentModel));
                    var adapterFactory = model.GetService <IVsEditorAdaptersFactoryService>();
                    var wpfTextView    = adapterFactory.GetWpfTextView(textView);
                    result.Add(wpfTextView);
                }
            }
            catch (Exception e)
            {
                VsOutputLogger.WriteLine("Exception in InlineCommentNavigationCommand.GetCurrentTextViews(): {0}", e);
            }

            return(result);
        }
예제 #18
0
 static void ForgetWithLogging(Task task)
 {
     task.Catch(e => VsOutputLogger.WriteLine("Exception caught while executing background task: {0}", e)).Forget();
 }
예제 #19
0
        protected override void OnAttached()
        {
            base.OnAttached();

            AssociatedObject.SelectionChanged += (s, e) =>
            {
                if (e.AddedItems.Count > 0)
                {
                    if (previousSelection == null)
                    {
                        previousSelection = AssociatedObject.SelectedItem;
                        if (defaultValue == null)
                        {
                            var binding = GetBinding();
                            Debug.Assert(binding != null, "Cannot find ItemsSource binding. Did you configure it in the target Listbox?");
                            if (binding == null)
                            {
                                return;
                            }
                            defaultValue = PropertyPathHelper.GetValue(binding.ResolvedSource, binding.ResolvedSourcePropertyName);
                        }
                        var list = AssociatedObject.ItemsSource as IList;
                        Debug.Assert(list != null, "ItemsSource data source is not an IList, cannot change it.");
                        if (list == null)
                        {
                            return;
                        }
                        try
                        {
                            list.Insert(0, defaultValue);
                        }
                        catch (Exception ex)
                        {
#if DEBUG
                            throw ex;
#else
                            VsOutputLogger.WriteLine(String.Format(CultureInfo.CurrentCulture, "Could not add default empty item to the bound ItemsSource data source - the collection does not allow insertion (or the type does not match). {0}", ex));
#endif
                        }
                    }
                    else if (AssociatedObject.SelectedIndex == 0)
                    {
                        var list = AssociatedObject.ItemsSource as IList;
                        Debug.Assert(list != null, "ItemsSource data source is not an IList, cannot change it.");
                        Debug.Assert(list.Count > 0, "ItemsSource data source is empty, something went wrong.");
                        if (list == null || list.Count == 0)
                        {
                            return;
                        }
                        if (list[0] == defaultValue)
                        {
                            list.RemoveAt(0);
                        }
                    }
                }
                if (e.RemovedItems.Count > 0)
                {
                    if (e.RemovedItems[0] == defaultValue)
                    {
                        previousSelection             = null;
                        AssociatedObject.SelectedItem = null;
                    }
                }
            };
        }
        void OnPropertyChange(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsVisible" && IsVisible && View == null)
            {
                View = new GitHubConnectContent {
                    DataContext = this
                }
            }
            ;
        }

        async void UpdateRepositoryList(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                // if we're cloning or creating, only one repo will be added to the list
                // so we can handle just one new entry separately
                if (isCloning || isCreating)
                {
                    var newrepo = e.NewItems.Cast <ISimpleRepositoryModel>().First();

                    SelectedRepository = newrepo;
                    if (isCreating)
                    {
                        HandleCreatedRepo(newrepo);
                    }
                    else
                    {
                        HandleClonedRepo(newrepo);
                    }

                    var repo = await ApiFactory.Create(newrepo.CloneUrl).GetRepository();

                    newrepo.SetIcon(repo.Private, repo.Fork);
                }
                // looks like it's just a refresh with new stuff on the list, update the icons
                else
                {
                    e.NewItems
                    .Cast <ISimpleRepositoryModel>()
                    .ForEach(async r =>
                    {
                        if (Equals(Holder.ActiveRepo, r))
                        {
                            SelectedRepository = r;
                        }
                        var repo = await ApiFactory.Create(r.CloneUrl).GetRepository();
                        r.SetIcon(repo.Private, repo.Fork);
                    });
                }
            }
        }

        void HandleCreatedRepo(ISimpleRepositoryModel newrepo)
        {
            var msg = string.Format(CultureInfo.CurrentUICulture, Constants.Notification_RepoCreated, newrepo.Name, newrepo.CloneUrl);

            msg += " " + string.Format(CultureInfo.CurrentUICulture, Constants.Notification_CreateNewProject, newrepo.LocalPath);
            ShowNotification(newrepo, msg);
        }

        void HandleClonedRepo(ISimpleRepositoryModel newrepo)
        {
            var msg = string.Format(CultureInfo.CurrentUICulture, Constants.Notification_RepoCloned, newrepo.Name, newrepo.CloneUrl);

            if (newrepo.HasCommits() && newrepo.MightContainSolution())
            {
                msg += " " + string.Format(CultureInfo.CurrentUICulture, Constants.Notification_OpenProject, newrepo.LocalPath);
            }
            else
            {
                msg += " " + string.Format(CultureInfo.CurrentUICulture, Constants.Notification_CreateNewProject, newrepo.LocalPath);
            }
            ShowNotification(newrepo, msg);
        }

        void ShowNotification(ISimpleRepositoryModel newrepo, string msg)
        {
            var vsservices = ServiceProvider.GetExportedValue <IVSServices>();

            vsservices.ClearNotifications();
            vsservices.ShowMessage(
                msg,
                new RelayCommand(o =>
            {
                var str = o.ToString();

                /* the prefix is the action to perform:
                 * u: launch browser with url
                 * c: launch create new project dialog
                 * o: launch open existing project dialog
                 */
                var prefix = str.Substring(0, 2);
                if (prefix == "u:")
                {
                    OpenInBrowser(ServiceProvider.TryGetService <IVisualStudioBrowser>(), new Uri(str.Substring(2)));
                }
                else if (prefix == "o:")
                {
                    if (ErrorHandler.Succeeded(ServiceProvider.GetSolution().OpenSolutionViaDlg(str.Substring(2), 1)))
                    {
                        ServiceProvider.TryGetService <ITeamExplorer>()?.NavigateToPage(new Guid(TeamExplorerPageIds.Home), null);
                    }
                }
                else if (prefix == "c:")
                {
                    vsservices.SetDefaultProjectPath(newrepo.LocalPath);
                    if (ErrorHandler.Succeeded(ServiceProvider.GetSolution().CreateNewProjectViaDlg(null, null, 0)))
                    {
                        ServiceProvider.TryGetService <ITeamExplorer>()?.NavigateToPage(new Guid(TeamExplorerPageIds.Home), null);
                    }
                }
            })
                );
#if DEBUG
            VsOutputLogger.WriteLine(String.Format(CultureInfo.InvariantCulture, "{0} Notification", DateTime.Now));
#endif
        }

        void RefreshRepositories()
        {
            connectionManager.RefreshRepositories();
            RaisePropertyChanged("Repositories"); // trigger a re-check of the visibility of the listview based on item count
        }