Why are there two .Addin files?
The last few days I have been meeting with 3rd party developers, helping them with their VSIP packages and Add-ins, giving talks, and trying to look helpful. One of the questions that we got has been a center of controversy for a while – why are there two .Addin files in a project created by the Add-in wizard? There is a long story behind this, so grab yourself a cool drink, and listen to the story of two .Addin files separated at birth…
Here is the problem. As a requirement, the new format of registering an Add-in with Visual Studio requires that you drop an .Addin file into a special folder on disk. Visual Studio will then find that file, load it, and run the Add-ins it contains as appropriate. But the problem is, during development, how does VS find the assembly implementing the Add-in. We had a few options, we could put the path to the dll into the .Addin file, we could build directly into the directory containing the .Addin file, or we could modify the .Addin file at runtime to point to the assembly. Each of these had pros and cons. And remember that the main goal is to enable the scenario where the user creates a new project and hits F5, everything should just work.
If we would put a hardcoded path into the .Addin file pointing to the assembly then it would get messy for the Add-in developer because if you were to move the project to a different directory then the .Addin file would point to the wrong location. It was also really messy for C# developers because they would need to modify the .Addin file every time they switched to a different project configuration. When you build a VB project, it stores the built assembly into {ProjectDirectory}\Bin, while C# stores the built assembly into {ProjectDirectory}\{ConfigurationName}\Bin. So we would need to modify the C# project to build into a directory structure such as VB.
This would also cause problems if you were using source code control in a group development environment. Suppose I would create an Add-in project, and put it under SCC. If you would then load up the project and hit F5 it would not run because the .Addin file was on the computer where the project was created.
Building directly into the directory containing the .Addin file was not very good, either because users can add or remove the special directories we in for .Addin files, and if the user deleted the default one, then the assembly would be copied into the wrong location. OK, we have this issue when the wizard runs and places the .Addin file, but hard coding the directory to build to would be even worse. Additionally, the SCC scenario is broken because, if the DLL is set to build into “E:\Documents and Settings\craigs\Application Data\Microsoft\MSEnvShared\Addins”, that is not going to work well unless you installed Windows to the E drive, and your user name just happens to also be craigs this would be a problem (according to the volume of mail that I receive that should be sent to other people with the first name Craig and a last name that begins with S, this may not be an much as an issue as you would think).
The last option is to set a build rule or use a new feature called project flavors to modify or generate the XML file during build time. This would be possible, but it seems fragile and prone to mistakes - if we regenerated the file each time, then any modifications you make would be lost simply by building.
We chose the first option; modify the C# build location to build in the \Bin directory rather than \Bin\{ConfigurationName}, and to have the XML file use the path to the assembly. To make it easier for the SCC user, we also create a XML file in the same directory as the project file, if you get the Add-in project from SCC, you simply copy that file into the appropriate directory, change the path, and it will work. There is also a secondary reason for having the .Addin file in the project directory: to make setup easier. Simply grab the .Addin file in the project directory, get the assembly implementing the Add-in, and put it in one of the special folders that we look for .Addin files and you are done. You do not need to worry about modifying that .Addin file because it does not have a hard-coded path, just the assembly DLL name. Because we will do a relative path lookup we will find the assembly.