Visual Studio SDK - Handling File Add, Remove, and

2019-03-29 06:38发布

I'm working on a Visual Studio extension that should listen for events when the user adds, removes, or renames files in the current solution.

The answer to this question notes that VS provides infrastructure for listening to document events like saving, opening and closing through the DocumentEvents interface. For example:

Dte.Events.DocumentEvents.DocumentSaved

Are there similar events that would allow me to listen to the user adding/removing/renaming documents?

2条回答
走好不送
3楼-- · 2019-03-29 07:14

First, don't use DTE if you can help it. It's a very incomplete, shaky abstraction papered over an extremely complex interface. Having said that, I admit that sometimes it's super handy because the equivalent either can't be done without it (rare) or the alternate code would be quite long (less rare).

There are two concepts being conflated here. The first is the Running Document Table (RDT). The RDT represents all the open files (including the open .sln and project files). You can subscribe to RDT events to be notified of files being opened, closed, renamed, etc. But these events are for open files only!

The second concept is the project system. Each project loaded and displayed in the solution explorer is loaded by the project system for that project's type. C++ projects, C# projects, F# projects, WIX installer projects, etc. all have different project systems. There can even be custom project systems implemented by extensions. It sounds like you want to know about events in the project system, and not events for (just) open files. So your focus is the project system. However, since all project systems have different implementations, this becomes very tricky. VS is moving towards a common project system (CPS), but it's not 100% there yet, and even when it is there remains the problem of all the legacy extensions, etc.

You can subscribe to general "hierarchy" events which all project systems must furnish. They'll tell you for example when a file is added or removed (really, when a hierarchy item (node) is added or removed, since there's not necessarily a correspondence between files and hierarchy items). There's also an event that says the entire hierarchy has been invalidated -- a sort of refresh where you have to discard everything you know about the project and gather up new info.

Rename is probably the hardest thing to detect. Every project system implements it differently. In some project systems, a rename will present itself as a node deletion followed by a node addition, with no solid way to identify that it was due to a rename.

To sum up, nothing is as simple as it seems, particularly when it comes to project systems (one of the least extensible parts of Visual Studio). You'll likely end up with code that is specific to one or a handful of project systems, but won't work universally. (After all, not all projects even represent file hierarchies! And those that do still have folders, special reference nodes, etc. that aren't files.)

Some concrete pointers in the right direction:

  • Implement IVsSolutionEvents3 to be notified of a project being loaded/unloaded (and IVsSolutionEvents4 to be notified of a project itself being renamed). Register that object as a listener in your package initialization code (make sure your package is loaded before a solution is opened) via the SVsSolutionBuildManager service (cast to IVsSolutionBuildManager3 and call AdviseUpdateSolutionEvents3 on it).
  • Implement IVsHierarchyEvents to be notified of project changes like node properties changing (use the __VSHPROPID enum to find out which is which), nodes being added, removed, invalidated, etc. Call AdviseHierarchyEvents on the IVsHierarchy object passed to the IVsSolutionEvents3's OnAfterProjectOpen implementation to register the event listener object.
查看更多
登录 后发表回答