Introduction
I have a number of Servers in my Microsoft SQL Server Management Studio Server list that are no longer accessible, and not wanting to completely rebuild my list I began by posting a question on ServerFault about being able to Edit the MRU list for SQL Server Management Studio and being told it was not possible, I investigated whether infact it really would be. So I dug out Reflector and had a look inside the SQL Management Studio DLLs to find out, turns out... you can.
Using the Code
Because this code requires some libraries that are included with Microsoft SQL Server Management Studio, I cannot redistribute them. But if you open the project and add a reference to them, you'll then be able to compile.
References that need to be added can be either from SSMS Express or Full for version 2005. (I have noted the locations in CheckAssembly.vb.)
'Express - 'C:\Program Files\Microsoft SQL Server\90\Tools\Binn\
VSShell\Common7\IDE\Microsoft.SqlServer.Express.ConnectionDlg.dll
'Full - C:\Program Files\Microsoft SQL Server\90\Tools\Binn\
VSShell\Common7\IDE\ConnectiondDlg.dll
Note that to find the information about what properties and objects are used inside the component, we need to use Reflector.
Once we actually know how to find the properties and methods of interest, we need to actually hookup to them so we can make use of them. It is important to note that because a number of the objects are declared privately inside the library, we can't use strong types so we just use GetType
to ensure that things work as we expect.
For Each pp As PropertyInfo In _
GetType(ConnectionDlg.Personalization).GetProperties_
(BindingFlags.Static Or BindingFlags.NonPublic)
If String.Equals(pp.Name, "Instance") Then
t = CType(pp.GetValue(GetType(ConnectionDlg.Personalization), Nothing), _
ConnectionDlg.Personalization)
Exit For
End If
Next
Now that we have found the reflected internal instance of the Object
, we can start to operate on that to build up our Onscreen List of Servers that can be used. The EnumObject
method is how I called the reflected method and then enabled the ability to also delete from the same list.
Dim d As System.Collections.Specialized.HybridDictionary = Nothing
For Each ff As FieldInfo In t.GetType.GetFields_
(BindingFlags.NonPublic Or BindingFlags.Instance)
Debug.Print(ff.Name)
Select Case ff.Name
Case "typeTable"
d = CType(ff.GetValue(t), System.Collections.Specialized.HybridDictionary)
End Select
Next
If d IsNot Nothing Then
sl = d.Item(g)
EnumObject(sl, False)
End If
EnumObject
is recursive because the list is a linked list and we need to be able to traverse the list to find the actual data, because the original object has a String
method which just returns a copy of the data, but not the actual objects.
Private Sub EnumObject(ByVal o As Object, ByVal remove As Boolean)
Dim head As Object
Dim nextitem As Object
If o Is Nothing Then Return
For Each ff As FieldInfo In o.GetType.GetFields_
(BindingFlags.NonPublic Or BindingFlags.Instance)
If String.Equals(ff.Name, "head", StringComparison.OrdinalIgnoreCase) Then
head = ff.GetValue(o)
EnumObject(head, remove)
End If
If String.Equals(ff.Name, "next", StringComparison.OrdinalIgnoreCase) Then
nextitem = ff.GetValue(o)
EnumObject(nextitem, remove)
End If
Next
End Sub
Finally, once we have displayed the list of servers to the user, we allow them to select one in the Listbox and then click Remove. This will then call EnumObjects
again, but enabling the Delete of the record.
Points of Interest
Because all of the methods and classes are Private
inside the SQL libraries, the only real way to access them is using Reflection.
Beware this has only been tested with SQL2005 and is only really something I did to solve my particular issue.
If you choose to run this program, make sure your SQL Server Management Studio is closed before you run it, because I'm not sure exactly who writes the file and when.
History