I finally figured this out. There is a ServiceProvider you can provide to the constructor for the ShellSettingsManager. All the examples i've seen just used:
SettingsManager sm = new ShellSettingsManager(ServiceProvider);
But when I tried that, I got "ServiceProvider is a type, which is not valid in the given context"
I finally found an example that used:
SettingsManager sm = new ShellSettingsManager(ServiceProvider.GlobalProvider);
That same example then went on...
SettingsStore ss = sm.GetReadOnlySettingsStore(SettingsScope.UserSettings);
Here is where I had to figure the rest out for myself.
There are two enumerables in the SettingsStore, GetPropertyNames and GetSubCollectionNames. These are helpful to find the collection and property I need. So first I did this:
string msg = "";
foreach (string s in ss.GetPropertyNames(""))
{
msg += s + "\r\n";
}
MessageBox.Show(msg);
The empty string as the parameter gets the root collection properties, and this had what I need.

So now I finally retrieved the value I needed.
string DefaultNewProjectLocation = Environment.ExpandEnvironmentVariables(ss.GetString("", "DefaultNewProjectLocation"));
The first parameter, the empty string, is the root collection, and the 2nd parameter is the property I want. It returned:
%USERPROFILE%\source\repos
Expanding the environment variable gives me the literal path.
Now on to figuring out how to get the current instance of VS to load a project selected in my tool window.
Edit: After another full day of searching, finally got Visual Studio to load a project in the instance which my extension is running. Several people had told me to use Process.Start and pass the path to the solution file but this started another instance of Visual Studio and loaded it there.
I found the DTE.ExecuteCommand(string Command, string Args) but didn't know if that would be what I needed. Then I read something that said it executes commands available in the Tools/Options/Environment/Keyboard section. I perused through there and found "File.OpenProject" and figured I could send the solution file as the argument. But there was one more problem in the way...
Adding a reference to EnvDTE and trying this:
DTE.ExecuteCommand("File.OpenProject", "\"" + PathToSlnFile + "\"");
Just gave me an error that said,
an object reference is required for the non-static field, method or
Property '_DTE.ExecuteCommand(string, string)'
I tried instantiating it
var dte = new DTE();
But that just gave me some runtime error about not being able to read something about the COM library. I found a million examples of using DTE.ExecuteCommand but not one of them showed how to get a reference to it. I did find this in Google Books, "Mastering Visual Studio .NET: Getting the Most Out of the Visual Studio .NET Environment"
The way in which you obtain a reference to the DTE object will depend
on what type of code you are writing. Macros just use a global
variable provided by the macro environment called DTE. Add-ins are
passed a reference to this object when VS.NET initializes them.
Ok, that still doesn't tell me anything. How do I get that reference?!?
And then I got lucky. I finally stumbled across a random page (i'd link it but I closed it already and don't think I could ever find it again). It gave me what I needed.
private DTE dte = Package.GetGlobalService(typeof(DTE)) as DTE;
And now, I can do this, and it works a treat!
dte.ExecuteCommand("File.OpenProject", "\"" + PathToSolutionFile + "\"");
Hopefully this will save some other poor slob like me from spending three full days searching and finding nothing on their foray into writing a Visual Studio Extension.