Leveraging Visual Studio .NET Utility Project Types
To help you more easily maintain files within a solution, Visual Studio .NET makes available various utility projects. These utility projects allow you to keep track of files that are not part of any other project that is loaded into a solution. Because any file type can be stored within these projects, such as program source files and Microsoft Word documents, these projects can't be compiled into a program. And because utility projects are part of Visual Studio .NET and are not associated with any particular programming language, they are available to all users of Visual Studio .NET and don't require Visual Basic .NET, C#, or Visual C++ to be installed.
Miscellaneous Files Project
When you're working with a solution, you might need to open files that are not part of an existing project. When you open such a file, it is automatically added to a project called Miscellaneous Files. A project file isn't created on disk for this project, as with other project types, but you get a convenient way of locating files that are open but are not part of any other project that is open within the solution. You can think of the Miscellaneous Files project as a list of most recently used open documentswhen you open a file, an item for that file is added to the project, and when you close the file, it is removed. By default, the Miscellaneous Files project and the files it contains don't appear in the Solution Explorer tree hierarchy, but you can easily make them visible by opening the Tools Options dialog box, selecting the Environment | Documents node, and selecting the Show Miscellaneous Files In Solution Explorer check box.The Miscellaneous Files project has a unique name associated with it that, unlike with other projects, doesn't change over time. This name, "<MiscFiles>", is defined by the constant vsMiscFilesProjectUniqueName. The following macro retrieves the Project object for the Miscellaneous Files project:
Sub FindMiscFilesProject()
Dim project As EnvDTE.Project
Dim projects As EnvDTE.Projects
projects = DTE.Solution.Projects
project = projects.Item(EnvDTE.Constants.vsMiscFilesProjectUniqueName)
End Sub
When the first file is opened within the Miscellaneous Files project, an item is added to the Solution.Projects collection that implements the Project interface. It works just like the Project interface implemented by projects such as Visual Basic .NET or C# projects, except that a few of the properties will return null or Nothing or throw a System.NotImplementedException when called. Table 8-1 lists the methods and properties of the Project object that return a meaningful value for the Miscellaneous Files project and the ProjectItem and ProjectItems objects contained within this project.
Project | ProjectItems | ProjectItem |
---|---|---|
DTE | DTE | DTE |
ProjectItems | Parent | Collection |
Name (read-only) | Item | Name (read-only) |
UniqueName | GetEnumerator / _NewEnum | FileCount |
Kind | Kind | Kind |
FullName | Count | FileNames |
ContainingProject | SaveAs | |
Save | ||
IsOpen | ||
Open | ||
Delete | ||
Remove | ||
ExpandView | ||
ContainingProject | ||
IsDirty |
public EnvDTE.Window NewFile(string Item = "General\Text File",
string Name = ", string ViewKind =
"{00000000-0000-0000-0000-000000000000}")
By applying the techniques we used earlier to calculate the first parameter for the ItemOperations.AddNewItem, we can find the value that should be passed to the NewFile method. The second parameter also has the same meaning as the second parameter of the ItemOperations.AddNewItem methodthe name of the file (with extension) that is to be addedand if the empty string is passed, a default name is calculated. The last argument specifies which view the file should be opened in when it is added. These values can be found within the EnvDTE.Constants class and begin with the name vsViewKind.
Solution Items Project
The Solution Items project works in a similar way to the Miscellaneous Files project but with a few small differences. Files that are opened in the Miscellaneous Files project are removed from that project when the solution is closed; items added to the Solution Items project stay with that project even after the solution is closed. Because these files stay within the project, you can think of the Solution Items project as a housekeeping project because you can keep items such as documentation, notes, and other files you might use in this project for easy access. Like the Miscellaneous Files project, the Solution Items project can't be built but supports an EnvDTE.Project object (with limited functionality, however). The same methods and properties shown in Table 8-1 apply to the Solution Items project. Also like the Miscellaneous Files project, the Solution Items project reserves a unique name for indexing the Solution.Projects collection, so you can find the Solution Items project within the list of projects maintained by the solution. You can use this constant, vsSolutionItemsProjectUniqueName, as shown in the following example:
Sub FindSolutionItemsProject()
Dim project As EnvDTE.Project
Dim projects As EnvDTE.Projects
projects = DTE.Solution.Projects
project = projects.Item( _
EnvDTE.Constants.vsSolutionItemsProjectUniqueName)
End Sub
You add items to the Solution Items project by calling the AddNewItem and AddExistingItem methods of the ItemOperations object. This means you must first select the Solution Items project within Solution Explorer. And because the Solution Items project can be created only by the user manually adding a file to the project, you must be sure that the project exists before you attempt to add an item to it.
Unmodeled Projects
All the project types we've discussed so far have implemented a Project object that can be used by a macro or an add-in. However, a few project types, such as a database project or a project that has been unloaded using the Project | Unload Project command, don't implement the Project object themselves. To allow some programmability for these project types, Visual Studio .NET supports the unmodeled project type. An unmodeled project provides an implementation of the Project object that supports only the properties common among all project types, which are DTE, Kind, and Name. All other properties and methods on this implementation of the Project object return values that have no useful meaning or generate an exception when called and shouldn't be used by a macro or an add-in. You can distinguish an unmodeled project from other project types by checking the Project.Kind property, which returns the constant EnvDTE.Constants.vsProjectKindUnmodeled if the project is an unmodeled project. The following macro enumerates all the projects loaded into a solution and determines which ones are unmodeled:
Sub FindUnmodeledProjects()
Dim i As Integer
For i = 1 To DTE.Solution.Projects.Count
Dim project As EnvDTE.Project
project = DTE.Solution.Projects.Item(i)
If (project.Kind = EnvDTE.Constants.vsProjectKindUnmodeled) Then
MsgBox(project.Name + " is unmodeled")
End If
Next
End Sub
NoteYou might notice that the FindUnmodeledProjects macro uses the numerical indexing method rather than the enumerator to find each project in a solution. It does this because of a bug in Visual Studio .NET that won't return a correct Project object when you use the enumerator. This bug applies only to unmodeled projects; using the enumerator works fine for other project types.