I can't seem to get MRU items from VS

Yann Duran 1 Reputation point
2021-05-05T14:38:11.32+00:00

I've tried 2 different ways of trying to get a list of VS's MRU items (projects and solutions) using code from this post: VSSDK Howto Fill MRUList into MRUListBox.

ExternalSettingsManager

   var vsExePath = AppDomain.CurrentDomain.BaseDirectory + "devenv.exe";  
   var mruPath = @"MRUItems\{a9c4a31f-f9cb-47a9-abc0-49ce82d0b3ac}\Items";  
     
   using (ExternalSettingsManager ext = ExternalSettingsManager.CreateForApplication(vsExePath))  
   {  
       var store = ext.GetReadOnlySettingsStore(SettingsScope.UserSettings);  
       var mruList = new ArrayList();  
       var names = store.GetPropertyNames(mruPath);  
     
       foreach (string name in names)  
       {  
           string value = store.GetString(mruPath, name);  
           string[] subValue = value.Split('|');  
           mruList.Add(subValue[0]);  
       }  
    }  

store.GetPropertyNames(mruPath) always throws a "Value does not fall within the expected range" error.

---
IVsMRUItemsStore.GetMRUItems(VSConstants.MruList.Projects, "")

   var maxItems = 50;  
   var guid = VSConstants.MruList.Projects;  
   var mruItems = new string[maxItems];  
   var itemsStore = (IVsMRUItemsStore)await VS.Shell.GetMRUItemsStoreAsync();  
   var projectCount = itemsStore.GetMRUItems(ref guid, "", dwMaxResults: (uint)maxItems, rgbstrItems: mruItems);  

projectCount is always zero, and there are no items in mruItems

---

Sadly I was unable to download the working sample project that @Dylan Zhu-MSFT had kindly uploaded. After I've been made to sign-in, the link returns:

We're sorry, but <my email address> can't be found in the microsoftapc-my.sharepoint.com directory. Please try again later, while we try to automatically fix this for you.

It looks like the sample project is hosted on Dylan's private Microsoft SharePoint site. I'd REALLY like to be able to try out that sample!

94015-image.png

Has anyone successfully been able to use either of these methods to get MRU items from VS? Or can anyone see a flaw in either my code or the original code here?

Not Monitored
Not Monitored
Tag not monitored by Microsoft.
37,800 questions
0 comments No comments
{count} votes

3 answers

Sort by: Most helpful
  1. Dylan Zhu-MSFT 6,406 Reputation points
    2021-05-07T03:25:39.213+00:00

    Hi YannDuran,

    Before getting the mru list, you need to click Test Sub Command to trigger the event at the first time. After that the mru list will auto refresh when you go to Extensions > Test Menu > Sub Menu.

    By the way, since the policy, we cannot share the sample through our onedrive at the moment, I paste the codes here:

        private TestCommand(AsyncPackage package, OleMenuCommandService commandService)
        {
            ....
    
            this.InitMRUMenu(commandService);
        }
    
        private int baseMRUID = (int)TopLevelMenuPackage.cmdidMRUList;
        private ArrayList mruList;
    
        private void InitializeMRUList()
        {
            if (null == this.mruList)
            {
                this.mruList = new ArrayList();
                if (null != this.mruList)
                {
                    string vsExePath = AppDomain.CurrentDomain.BaseDirectory + "devenv.exe";
                    string mruPath = @"MRUItems\{" + VSConstants.MruList.Projects + @"}\Items";
    
                    ExternalSettingsManager ext = ExternalSettingsManager.CreateForApplication(vsExePath);
                    SettingsStore store = ext.GetReadOnlySettingsStore(SettingsScope.UserSettings);
                    foreach (string name in store.GetPropertyNames(mruPath))
                    {
                        string value = store.GetString(mruPath, name);
                        string[] subValue = value.Split('|');
                        this.mruList.Add(subValue[0]);
                    }
                }
            }
        }
    
        private void InitMRUMenu(OleMenuCommandService mcs)
        {
            InitializeMRUList();
            for (int i = 0; i < this.mruList.Count; i++)
            {
                var cmdID = new CommandID(
                    new Guid(TopLevelMenuPackage.guidTopLevelMenuPackageCmdSet), this.baseMRUID + i);
                var mc = new OleMenuCommand(
                    new EventHandler(OnMRUExec), cmdID);
                mc.BeforeQueryStatus += new EventHandler(OnMRUQueryStatus);
                mcs.AddCommand(mc);
            }
        }
    
        private void OnMRUQueryStatus(object sender, EventArgs e)
        {
            OleMenuCommand menuCommand = sender as OleMenuCommand;
            if (null != menuCommand)
            {
                int MRUItemIndex = menuCommand.CommandID.ID - this.baseMRUID;
                if (MRUItemIndex >= 0 && MRUItemIndex < this.mruList.Count)
                {
                    menuCommand.Text = this.mruList[MRUItemIndex] as string;
                }
            }
        }
    
        private void OnMRUExec(object sender, EventArgs e)
        {
            var menuCommand = sender as OleMenuCommand;
            if (null != menuCommand)
            {
                int MRUItemIndex = menuCommand.CommandID.ID - this.baseMRUID;
                if (MRUItemIndex >= 0 && MRUItemIndex < this.mruList.Count)
                {
                    string selection = this.mruList[MRUItemIndex] as string;
                    for (int i = MRUItemIndex; i > 0; i--)
                    {
                        this.mruList[i] = this.mruList[i - 1];
                    }
                    this.mruList[0] = selection;
                    System.Windows.Forms.MessageBox.Show(
                        string.Format(CultureInfo.CurrentCulture,
                                      "Selected {0}", selection));
                }
            }
        }
    

    Hope it could help you.

    Best Regards,
    Dylan

    0 comments No comments

  2. Yann Duran 1 Reputation point
    2021-05-07T03:59:34.757+00:00

    Thanks for you reply @Dylan Zhu-MSFT , but you clearly didn't read where I wrote that store.GetPropertyNames(mruPath) always throws a "Value does not fall within the expected range" error (line 23 in the code that you pasted here).

    I'm the author of the Start Page+ extension. My current method of getting MRU items kind of works, but it gets its values from the registry, and the registry items do not always reflect what the new VS 2019 Start Window shows, so I was looking for a different method to get the MRU items consistently show the same items as those in the Start Window.

    The code that I'm testing is exactly the same as what you've posted in lines 18-27. I know in theory your code should work, but for me line 23 always throws an error.

    Could you please verify that your sample still works in VS 2019 16.9.4, and then add it as an attachment here in this thread so that I can step through those lines on my machine?

    Thanks!


  3. Yann Duran 1 Reputation point
    2021-05-07T11:34:59.417+00:00

    Again, I appreciate your reply. I had already found that repo. The method he uses only returns path strings, I need several of the properties contained in the registry, or in ApplicationPrivateSettings.xml.

    I've bolded the properties that I need below.

    {
            "Key": "c:\\lss\\start-page-plus\\start-page-plus.sln",
            "Value": {
                "LocalProperties": {
                    "FullPath": "c:\\lss\\start-page-plus\\start-page-plus.sln",
                    "Type": 0,**
                    "SourceControl": null
                },
                "CodespaceProperties": null,
                "Remote": null,
                "IsFavorite": true,
                "LastAccessed": "2021-05-03T12:37:16.1096391+00:00",
                "IsLocal": true,
                "IsCodespace": false,
                "HasRemote": false,
                "IsSourceControlled": false
            }
    }