This question posted to the VS Extensibility Forum recently caught my attention. Initially, I initially suspected this would have a simple answer, but it turns out the shell pulls this icon directly from a resource in msenv.dll.
After examining the underlying IVsHierarchy implementation of the root solution node, it looked like the icon could be changed by setting the VSHPROPID_IconHandle property on the solution node. The next question to solve was “when” to set this. You cannot set the property from the shell stub, and package assemblies are typically loaded on demand.
So the best solution is to force one of your isolated shell packages to load at startup, by applying a couple of ProvideAutoLoad attributes one of your VSPackage objects. Specifically:
Note, this is generally frowned upon in most instances. To keep startup time and memory footprint to a minimum, packages should be loaded on demand. Especially when targeting the integrated shell. But this is an isolated shell scenario, and it’s certain you’ll have to have at least one package loaded.
Now that we have the package configured to load at startup, we could just set the property from the package’s overridden Initialize method. But that would be a mistake. Various shell services are also implemented with packages, and there is no guarantee to the order in which packages are loaded. So we need to wait until all prescribed packages are loaded.
To do that, we need to wait until the VSSPROPID_ShellInitialized property is set. And this can be done by implementing IVsShellPropertyEvents and calling IVsShell.AdviseShellPropertyChanges.
Below, is a slightly modified AboutBoxPackage (initially generated with the isolated shell project wizard), that I created as a quick proof of concept to verify that the solution icon can actually be changed for an isolated shell application.