It seems that as I learn more and more about the IDE services (VS SDK) and how to call them from an add-in, I can’t stop playing with them and wondering if I can solve problems that previously seemed unsolvable. One of them, very old, was how to get the Guid of the project subtype, to identify Test projects (for example), a problem that I posted long time ago in the MSDN VSX forum and I got a partial answer. What I really wanted is, given an EnvDTE.Project, get all its project type/subtype Guids, without using convoluted code. Yesterday I found a promising solution by another MVP, Daniel Cazzulino, but I was not completely satisfied having to read the .vbproj or .csproj files to get the Guid of the project (not to be confused with the Guid of the project type) in order to get the IVsHierarchy object, which is the key piece here to cast it to IVsAggregatableProject and call the GetAggregateProjectTypeGuids method. Finally I got inspired and thanks to the EnvDTE.Project.UniqueName property you can get the IVsHierarchy object calling IVsSolution.GetProjectOfUniqueName. I wrote the detailed solution in this article:
HOWTO: Get the project flavor (subtype) of a Visual Studio project from an add-in
Although I am happy with the new world of IDE services called from add-ins, it is a somewhat bittersweet feeling: on the one hand it is great to be able to call them from an add-in, but, on the other hand, I can’t help thinking that add-ins are second-class citizens in the VS extensibility and that a lot of functionality is not directly available to them and you have to use the complex and intimidating SDK… I wish there was a single, simple, unified and managed (.NET) approach. Do you feel the same? I hope your comments about it.
As I posted in a previous blog entry, where I explained how to reference an assembly in the GAC from an add-in, here is the article explaining how to get a Visual Studio service from an add-in:
HOWTO: Get a Visual Studio service from an add-in
The extensibility model for Visual Studio add-ins sometimes is not enough to meet your needs and you need some service from a Visual Studio package, but you don’t want to transform your add-in into a VSPackage, you just want to get some service only available to VS packages. I will blog about it in another post, but the first thing to understand is that you don’t need in many cases to install the Visual Studio SDK (or VSIP in previous versions) since some assemblies are in the GAC or other Visual Studio folders. If you have the assembly and the SDK documentation (available online), you don’t need to get your computer “dirty” with the SDK or CTPs, etc.
The problem is how to reference assemblies that seem to be only in the GAC (such as Microsoft.VisualStudio.OLE.Interop). You can’t really reference an assembly in the GAC but here is a workaround:
HOWTO: Reference a Visual Studio assembly in the GAC from an add-in
It is said that it takes three iterations to make a software application right and it seems to be correct: it was not until Visual Basic 3.0 when people started to use it in serious applications, it was not until MZ-Tools 3.0 when my add-in was widely used and it was not until .NET Framework 2.0 (which is actually the 3rd iteration after versions 1.0 and 1.1) when Microsoft did it right with .NET Data Providers, making it possible to use provider factories and base classes to write database-independent code. If I was fascinated with source code control providers as I posted recently, I am even more fascinated with data providers, since the times of ODBC around 1995. It happens that for my first job I had to learn Visual Basic 3.0 and ODBC in two weeks…and before becoming interested in the extensibility of IDEs around 2000, I was an expert in ODBC/OLEDB technologies, maybe some of you still remember me in the ODBC newsgroups around 1997-1999… anyway, to the point:
You may have noticed that Visual Studio .NET 2002 and 2003 used OLE DB providers and not the new ADO.NET data providers in the Data Connection dialog of the Server Explorer. Inexplicably, despite the previous experience with ODBC and OLEDB, Microsoft did not provide a standard way to enumerate .NET data providers or to show a standard connection dialog in .NET Frameworks 1.0 and 1.1. It was in .NET Framework 2.0 when the new ADO.NET 2.0 providers provide connection string builders, connection factories, etc. You can learn more about it in What’s new in ADO.NET 2.0. Visual Studio 2005 leverages the new capabilities of ADO.NET 2.0 providers and in turn provides good extensibility to use any ADO.NET 2.0 data provider in the data design-time experience of the IDE, thanks to the Data Designer Extensibility (DDEX). Using DDEX Visual Studio 2005 provides a new Data Connection dialog based on ADO.NET providers, not OLEDB providers. You can read a very good Introduction to Visual Studio Data Designer Extensibility (DDEX) and then you can read the DDEX SDK documentation. With DDEX you can make any ADO.NET 2.0 provider appear in the data connection dialog as explained in those links. Also, you can use that dialog from your own code (an add-in or VS package) and since this is a common question but it does not seem to be addressed in the documentation, I have written an article about it:
HOWTO: Using the Choose Data Source dialog of Visual Studio 2005 from your own code
A common question that appears in forums from time to time is how to guess the type of a project (Windows, Web Application, Web Site, Smart Device, Class Library, Console, etc.). The answer is not so simple and you have to check several properties. I have explained it in my this article:
HOWTO: Guess the type of a Visual Studio project from an add-in or macro
This is an article that I wanted to write long time ago and finally I have written it today. Somehow I am quited fascinated with SCC providers since many years ago and this question has appeared several times in the forums:
HOWTO: Interact with a source code control (SCC) provider from a Visual Studio add-in
A new article of my MZ-Tools articles series about a bug of VS 2005:
BUG: Adding a non-text file to a solution folder from a Visual Studio 2005 add-in or macro opens it
A new article of my MZ-Tools articles series:
HOWTO: Troubleshooting Visual Studio and Office add-ins
A new article of my MZ-Tools articles series about a bug of VS 2005:
BUG: SolutionEvents.BeforeClosing event raised with no solution loaded in Visual Studio 2005 add-ins
I spent quite a few hours yesterday dealing with an intriguing thing that hapenned two days ago while I installed Windows Vista in Spanish on a new computer. To my surprise, every setup that I tried suggested “C:\Program Files” (in English) as the default destination, instead of “C:\Archivos de programa” which is the localized Spanish name. I changed a few things, delete some folders and in the end I had to reformat the hard disk. So, after reformatting I verified that setups insisted on suggesting “C:\Program Files” as destination folder instead of the Spanish localization. How come? I investigated and here are my conclusions:
- Previous to Windows Vista, there were English versions of Windows and localized versions of Windows. For the localized versions the folder names are localized. Windows XP also allowed Multiple User Interface (MUI) where you install a language pack over an English version and you have the user interface localized. This is similar, but not the same (regarding folder names), than a localized Windows version.
- Windows Vista eliminates localized versions and instead uses MUI for all languages (even English). There is a language-neutral base and language packs. A consequence of this is that folder names are no longer localized. So, the folder for programs is always C:\Program Files, even is the language pack is Spanish.
- Until Windows XP, when you call the Shell API functions SHGetSpecialFolderPath, SHGetFolderPath or the System.Environment.GetFolderPath of the .NET Framework it returns the localized folder name. On Windows Vista, it returns the English name (the one actually on disk). For this reason older setups now suggest C:\Program Files always, instead of a localized name. This will confuse the user, of course.
- To complicate things, despite that the actual names of the folders on disk are always on English, the shell of Windows shows them in a localized way. For example, using the Windows explorer the folder “C:\Program Files” is displayed as “C:\Archivos de programa” and “C:\Users” is displayed as “C:\Usuarios”.
- To complicate things even further, there are two hidden “junction points” in the root folder of C:. A junction point is just a link to a folder. One of junctions points is from “C:\Documents and Settings” to “C:\Users” and I guess this is because that location has changed, and there could be legacy setups that used the hardcoded the path “C:\Documents and Settings” instead of calling the Shell API. The other junction point is from “C:\Archivos de programa” to “C:\Program Files” and it is more intriguing because no setup would hardcode a non English folder name. So, which is the purpose of this joint point? I suppose that it only makes sense if you are upgrading from Windows XP to Windows Vista (rather than a clean installation).
- There is a new shell API function in Windows Vista, SHGetLocalizedName, that returns the localized name of a folder, as the Windows Explorer shows it to the user. I hope that new installers and setups become aware of Windows Vista an use this API function to suggest a destination folder like “C:\Archivos de programa” instead of “C:\Program Files” in the textbox for the location of the application. Once the installer gets a localized destination folder, the junction point from “C:\Archivos de programa” to “C:\Program Files” should make it install in the correct location.
Why all these changes? Apart from the new unified MUI approach that dictates non-localized names on disk (only localized when displayed to the user) and that there is a stupid 260 character limit in paths that MS would like to fix and that makes long folders names like “C:\Documents and Settings” not very friendly, it seems that MS preferred safety on folder locations even it that means confusing the user and for that reason they changed the behavior of the Shell functions. So, the implementation model wins over the user mental model. Now we can only hope that new setups aware of this Vista problem fill the gap to show to the user only localized names like the Windows Explorer does, not actual names on disk.