Another question about cancelling the IWizard when creating a project, this time in the StackOverflow forum that I am visiting now quite often, has prompted me to create a project template with a wizard using the IWizard interface, as explained in the MSDN documentation How to: Use Wizards with Project Templates. The sample certainly doesn’t show how to cancel the wizard and the IWizard interface methods don’t seem to offer that possibility so apparently it is not possible. However, it is possible in a non-intuitive way: there are two exceptions, WizardCancelledException and WizardBackoutException that the wizard can throw to return to before showing the Add Project dialog, or to that dialog, respectively. There seems to be some cleanup to do, as Rory Primrose explains in his post Pitfalls of cancelling a VSIX project template in an IWizard. You may also find useful a long explanation by Ron Petrusha about Developing Visual Studio Project Wizards, which I will add to the Articles section about templates of this site. And remember that if you want full control of the wizard you can always use the old COM-based IDTWizard interface instead.
While I was aware of the StackOverflow Q&A site all these years, my preference has been always the specific MSDN Visual Studio Integrate forum (formerly MSDN Visual Studio Extensibility forum), and I have only answered a couple of questions in StackOverflow, mainly pointed by someone by e-mail.
However, today I have registered in StackOverflow, added my favorited tags (vsx, vs-extensibility, vsix, vspackage, visual-studio-addins, envdte, visual-studio-sdk, etc.) and I hope to get used to that site and visit it as often as I do with the MSDN VSX forum.
I have also added it to the Forums section of this VSX site since I find it a valuable resource to get answers: http://www.visualstudioextensibility.com/forums/
A question in the MSDN VSX forum yesterday about fully customizing the solution creation (not the project creation) with a template made me to investigate to provide a long answer and I discovered something that I had totally forgotten: the old COM-based EnvDTE.IDTWizard that appeared in the first versions of Visual Studio .NET (2002/2003) and that can be used still today. That interface provides a single Execute method that allows you full control over the solution/project creation, on the contrary to the new wizard Microsoft.VisualStudio.TemplateWizard.IWizard that provides many methods to server as hooks in the project creation. Unfortunately I have had these two days very busy at the office and personal life (and the forecast for the next days doesn’t seem much better) so I haven’t had time to write articles with code about these wizards. Interestingly I have found that I wrote a long article with code for a Spanish magazine 8 years ago about the IDTWizard. Anyway, what I have done is to update the Visual Studio Extensibility section and Templates section to include both kinds of wizards.
My new article is to document a bug that a customer of my MZ-Tools add-in reported some days ago, and that is caused by a bug (or problem) in the automation model (EnvDTE). It happens in the following scenario:
- Using the latest versions of Visual Studio (it doesn’t happen with old versions such as VS 2005, 2008)
- You add a .sql file to a project that doesn’t support .sql files, for example to a C# project. The problem doesn’t happen with projects that support .sql files such as database projects.
- If you open the project item to get its (invisible) window, get its text document, modify it and close the window saving the changes, the changes are not persisted to disk.
You have the details and code to reproduce the problem here:
PRB: Window.Close doesn’t save changes if requested for .sql files in non-database projects
I am not sure if this is a bug or not, because the project doesn’t support .sql files. There is an easy workaround, though. You can call:
Sayed Ibrahim tweeted me about TemplateBuilder (a NuGet package which can be used to easily create item and project templates for Visual Studio) and SideWaffle Template Pack (a Visual Studio extension that provides “The ultimate web developer template pack”) so I have added new sections for templates with download URLs and videos:
Download > Templates
Videos > Templates
In my MZ-Tools package I use dynamic localization to avoid the official way to localize .vsct files. So, I use the TextChanges CommandFlag for UI items and I set the text at run-time using the BeforeQueryStatus event handler. While this works fine for most UI items, alas, it doesn’t work for toolbars. I have documented it here:
BUG: TextChanges CommandFlag not honored for toolbars in Visual Studio packages
and this is the Microsoft Connect bug report:
“TextChanges” CommandFlag not honored for toolbars in Visual Studio packages (VS SDK)
A question in the VSX forum has intrigued me enough to test a creative solution: to intercept a command execution to re-execute it with an input parameter that you can retrieve when the execution finishes. This can be useful in a scenario where a command can be executed asynchronously twice and you want to know which/when each execution is finished:
HOWTO: Pass parameters programmatically to a command from a Visual Studio add-in
When creating a Visual Studio add-in, you had full control of the full name of its commands (command prefix + command short name, such as “MyAddIn.MyCommand”), as I explained in the article HOWTO: Create command names without ‘.Connect’ in Visual Studio add-ins. So, when I created my MZ-Tools add-in for Visual Studio, each version used a command prefix such as “MZTools6″ or “MZTools7″, and I could provide that information to the end user to customize the keyboard shortcuts, for example:
Another nice consequence was that, given a Visual Studio version, two versions of the add-in (for example one purchased, next one evaluating) could be loaded at the same time without collisions of add-in command full names, because each one used a different command prefix.
With packages, you lack the control over the command prefix, as I explained in INFO: How a Visual Studio package command is named. So, the commands of a package cannot be named “MyPackage.MyCommand”. And it is perfectly possible that two packages (or two versions of the same package loaded side by side) create two commands with the same full name as in this example:
Therefore, given that a collision of command full names is not really a collision internally in Visual Studio (only in the user interface level), so far so good. But if your add-in assumes that its commands have unique full names (because the command prefix is unique for add-ins) and uses code like this:
EnvDTE.Command command = dte.Commands.Item("MyAddIn.MyCommand");
that will cause problems when migrating to a package:
EnvDTE.Command command = dte.Commands.Item("Tools.MyCommand");
You see, the command full name now uses “Tools” (for example) instead of “MyAddIn”. If you have two versions of your package loaded side by side, that call can return the command of the wrong package version. A similar problem to getting the correct CommandBar as explained in HOWTO: Get a CommandBar by Guid and Id rather than by name from a Visual Studio add-in.
The same can happen if you execute a command by name:
The solution is to stop using command full names in the code to identify commands, and to use the command Guid / Id instead:
- To locate a command, the EnvDTE.Commands.Item method can accept not only a command full name, but also a command guid and a command id.
- To execute a command, you can use the automation way (HOWTO: Execute a command by Guid and Id from a Visual Studio add-in) or the package way (HOWTO: Execute a command by Guid and Id from a Visual Studio package).
In my MZ-Tools extension I use a lot of command stuff, so I have to review/change several areas of the product as part of the migration to a package. Also, the user can create commands for each code template of the Code Library feature (notice the optional Command Name field):
In the code of the add-in, that is done using the EnvDTE80.Commands2.AddNamedCommand2 method. Although you can use automation (EnvDTE) from a package, you can’t use that method because its first parameter is of the type EnvDTE.AddIn. I guess that a package must use the AddNamedCommand methods of the IVsProfferCommands interface. I will post and provide a sample once I try it.
Continuing with the series of articles to show how to do things in a native way in a Visual Studio package instead of using the automation model (EnvDTE), in this new article I show how to get the solution events using the IVsSolutionEvents interface. As I expected, it is more difficult than using the automation model, with more code, and even requires you to use a cookie!:
HOWTO: Get solution events from a Visual Studio package
MSDN documentation about VSX has improved a lot in the past years and now you have HOWTO examples, walkthroughs, etc. However, it seems to me that it still needs improvement in some areas such as navigation and attention to the details. For example, if you read the topics on VSIX deployment, you will find links to a subject “PAVE Visual Studio Extension Deployment.”:
Apart that nobody knows what “PAVE” means, it happens that the links are broken and you get “We’re sorry—the topic that you requested is no longer available.”:
However, if you select Visual Studio 2010 in the Other Versions dropdown you get the content:
And the lack of attention or care that I mentioned: this was reported months ago and nobody has fixed it: