Mastering Visual Studio .NET 1002003 [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Mastering Visual Studio .NET 1002003 [Electronic resources] - نسخه متنی

Jon Flanders, Ian Griffiths, Chris Sells

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید








8.1 The VS.NET Automation Object Model


The IDE exposes an object model that
allows you to automate many of the tasks that would normally be done
manually. The same object model is used by macros, add-ins, and
wizards. (Wizards are discussed in the next chapter.)

At the core of the object model is the DTE object.
(DTE stands for Development Tools
Extensibility. Technically the object's coclass is
DTE, and it implements an interface named
_DTE, with an underscore. However, this COM-level
detail will be hidden from you if you are working with VB.NET.) This
object is the gateway into all of the functionality of the IDE.






The VS.NET object model is COM-based. A set of primary interop
assemblies is provided to allow access to the object model from
managed code.

The way in which you obtain a reference to the
DTE
object will depend on what type of code you are writing. Macros just
use a global variable provided by the macro environment called
DTE. Add-ins are passed a reference to this object
when VS.NET initializes them. (Wizards, which are discussed in the
next chapter, also have access to the DTE object in their script
files through a global object called dte.) The
best way to get a feel for what functionality is available from the
DTE object model is to look at the properties available from the DTE
object. Table 8-1 lists these properties and shows
which sections of this chapter provide further information about the
areas of functionality to which the various properties belong.






































































































































































Table 8-1. DTE object properties

Property


Description


ActiveDocument


The Document object for the document with the
input focus. (See Section 8.1.4.)


ActiveSolutionProjects


A collection of Project objects, representing the
projects currently selected in the Solution Explorer. (See Section 8.1.1.)


ActiveWindow


A Window object representing the window with the
input focus. (See Section 8.1.2.)


AddIns


A collection of AddIn objects representing the
add-ins listed under the VS.NET Add-in Manager. (See Section 8.3.)


CommandBars


A collection of CommandBar objects representing
all of the toolbars and menu bars in the VS.NET UI, including all
those currently hidden. (See Section 8.1.2.)


CommandLineArguments


A string containing everything on the command line after the program
name itself. (Usually empty unless VS.NET was run as part of an
automated build script.)


Commands


A collection of Command objects, representing
actions that can be performed in VS.NET. (See Section 8.1.3.)


ContextAttributes


A collection of ContextAttribute objects that
allows extra items to be added to the Dynamic Help window.


CSharpProjects


A collection of Project objects containing all of
the C# projects in the solution. (See Section 8.1.1.)


Debugger


A Debugger object representing the VS.NET
debugger. (See Section 8.1.5.)


DisplayMode


A member of the vsDisplay enumeration indicating
whether the UI is in Multiple Document Interface (MDI) mode
(vsDisplayMDI) or tabbed mode
(vsDisplayTabs).


Documents


A collection of Document objects, representing all
of the documents currently open in the UI. (See Section 8.1.4.)


DTE


The DTE object. This may seem pointlessthis
property refers back to itself. However, all of the objects in the
DTE object model have a property called DTE
allowing you to get a reference back to the DTE
object. For the sake of consistency, even the DTE
object has this property.


Edition


A string indicating which edition of VS.NET is installed (e.g.,
"Enterprise Architect" for the VS.NET Enterprise
Architect edition).


Events


The Events object, which provides access to a
family of objects that raise event notifications. (See Section 8.1.7.)


Find


The Find object, which can perform global search
operations.


FullName


The full path of the devenv.exe (VS.NET)
executable.


Globals


A Globals object, storing per-user configuration
for add-ins or macros. (Note: there are three objects in the DTE
hierarchy that provide a Globals property: the
DTE object, Solution objects,
and Project objects. They all work in the same
way, the only difference being where the data is stored. Section 8.3.1.1 shows the use of the
Solution object's
Globals property.)


ItemOperations


An ItemOperations object that allows common
operations to be performed on the object currently selected in the
Solution Explorer, such as adding a new or existing item.


LocaleID


The locale ID in which VS.NET is running.


Macros


A Macros object, representing the macros recorder.
(See Section 8.2.1.)


MacrosIDE


Returns the DTE object for the macros IDE. (Macros
have their own IDE, as described in Section 8.2.2. This IDE has its
own DTE object.)


MainWindow


A Window object representing the main VS.NET
window. (See the Section 8.1.2
section.)


Mode


A value from the vsIDEMode enumeration indicating
whether VS.NET is in design mode (vsIDEModeDesign)
or debugging mode (vsIDEModeDebug).


Name


A string whose value is "Microsoft
Development Environment' (unless
this is the DTE object returned by the
MacrosIDE property, in which case the string will
be "Visual Studio Macros").


ObjectExtenders


An ObjectExtenders property that manages the
installed automation extenders. This provides a mechanism by which
third-party vendors can add their own objects into the VS.NET
automation model.


Properties


A parameterized property that returns Properties
objects representing a page of global settings configured in the
VS.NET Options dialog. (See Section 8.1.1.2.)


RegistryRoot


A string of the registry path VS.NET is using to retrieve its
settings.


SelectedItems


A collection of currently selected items. (For treelike views such as
the Solution Explorer, this will be an array of
UIHierarchyItem objectssee Section 8.1.2.)


Solution


The Solution object for the currently loaded
solution. (See the Section 8.1.1
section.)


SourceControl


An object allowing simple source control operations to be performed.
(See Section 8.1.6.)


StatusBar


A StatusBar object representing the status bar at
the bottom of the main VS.NET window. Typically used by long-running
macros or add-ins in order to present progress notifications.


SuppressUI


Flag indicating whether user interface elements should be
suppressedfalse when running VS.NET normally, but true when
running a command-line build.


UndoContext


Allows sets of operations to be grouped so that they can be undone in
a single step. (This is useful for macros that perform lots of
individual stepsby default, everything done to documents
through the automation model will be undoable one step at a time.
This allows higher-level blocks of work to be undone in one step.)


UserControl


Flag returning true if the IDE is being used interactively, false if
it is under automation control. (UserControl
refers to the fact that VS.NET is under the control of the
userit has nothing to do with Windows Forms user controls.)


VBProjects


A collection of Project objects representing all
of the VB.NET projects in the current solution. (See Section 8.1.1.)


Version


A string containing VS.NET's version number
("7.10" for VS.NET 2003, "7.00"
for VS.NET 2002).


WindowConfigurations


A collection of WindowConfiguration objects for
each set of window layouts. VS.NET stores several different layouts
for windows according to the modethe set of tool windows and
toolbars you require tends to be different according to whether you
are debugging, editing code, or designing forms, so VS.NET stores
each layout separately.


Windows


A collection of Window objects representing all of
the open document or tool windows. (See Section 8.1.2.)

The DTE model provides access to many different aspects of
VS.NETsome of the objects deal with solutions and projects,
some deal with the VS.NET user interface, some deal with source
control, and some deal with settings. The most important groups of
objects are described in the following sections.






This chapter is not a reference guide to the
object modelthe MSDN
Library that ships with VS.NET already fulfills that role perfectly
well. The goal of this chapter is to explain what features are
available and how they are used. If you want a comprehensive list of
the members available on each object, consult the MSDN documentation.
To find the relevant section, open the Help Contents using Help
Contents... (Ctrl-Alt-F1) and look for the
"Developing with Visual Studio .NET" section. Underneath this is a
"Reference" topic, containing an
"Automation and Extensibility Reference" section. This describes the whole DTE
object model in full detail.


8.1.1 Solution and Project Objects


As Figure 8-1
illustrates, the DTE model provides an object hierarchy that mirrors
the hierarchy of a solution and its projects in the IDE. The
DTE object represents the IDE (VS.NET itself), and
it has a Solution property, which is an object
that represents the currently loaded solution. The
Solution object contains a collection of
Project objects, one for each project in the
solution. Each Project contains a collection of
ProjectItem objects that represent the files in
the project. Each object in the hierarchy exposes methods and
properties that allow you to carry out actions that you would
normally perform interactively in the IDE. For example, the
Solution object has a Remove
method that allows you to remove a project from the solution. This
method is the programmatic equivalent to right-clicking on the
project in the Solution Explorer and selecting Remove.


Figure 8-1. Solutions, projects, and files in the DTE object model


Example 8-1 shows how to iterate through all of the
items in each project in a solution using C#. (This snippet presumes
that there is a field or variable in scope called
DTE that contains a reference to the DTE object.
Macros have such a property available globally. Add-ins are passed
the DTE object during initialization.)

Example 8-1. Iterating through project items

Solution s = DTE.Solution;
foreach(Project p in s.Projects)
{
foreach(ProjectItem pi in p.ProjectItems)
{
MessageBox.Show("Item {0} in {1} Project of the {2} Solution",
pi.Name, p.Name,s.FullName);
}
}

8.1.1.1 Project objects and VSProject


Although
all project types have a great deal in common, there are certain
features found only in .NET projects. For example, a .NET project has
a list of references to other .NET components, but a Database project
would have no use for such settings. To accommodate project-specific
functionality, the Project object has a property
called Object through which extra features are
exposed, when appropriate.

VS.NET uses this facility with .NET projects to provide an object of
type VSProject. You can retrieve a
VSProject object like this:

Imports EnvDTE
Imports VSLangProj
...
Dim project As Project
project = DTE.Solution.Projects.Item(1)
Dim vsProject As VSProject
vsProject = project.Object

Note the Import statementsmost of the
VS.NET object model is defined in the EnvDTE
namespace, but here we also need to import the
VSLangProj namespace, as this is where
VSProject is defined.






This VSProject object is also available on
unmanaged (non-.NET) C++ projects. This may seem surprising, as you
would think that an unmanaged C++ project would have no use for
.NET-specific features. However, an unmanaged C++ project can be
turned into a managed C++ project by changing a single flag in its
project settings. (The "Use Managed Extensions"
flag in the General settings.) The only real
difference between an unmanaged C++ project and a managed one is the
setting of this switch, so the Project.Object
property always supplies a VSProject object.

The VSProject object provides a
References property, which is a collection of
Reference objects, one for each reference the
project has. It also has a WebReferencesFolder
property for web service references. It provides a
WorkOffline property, which allows you to work on
web projects in a disconnected environment. It also provides a couple
of utility methods for managing web service references.

8.1.1.2 Properties collections


Many of the entities you deal with
in VS.NET have properties associated with them. Solutions,
configurations, projects, and files all present property sets either
in the Properties panel (F4) or the Property Pages dialog (Shift-F4).

Properties present a challenge because the exact set of properties
available can varyfor example, a Project
object's properties will depend on the type of
project. Although in certain special cases this is dealt with by
introducing an extra object such as the VSProject
object described earlier, the DTE object model has a more extensible
way of dealing with properties. All objects that represent items with
property sets have a property called Properties.
This is a collection of Property objects and is
indexed by the name of the property.

The set of properties available depends on the type of
objectthe VS.NET documentation provides the full (and
extensive) lists for each type. Example 8-2 shows
how to use this feature to retrieve the
DefaultNamespace property that is present on C#,
J#, and VB.NET projects.

Example 8-2. Retrieving a project property

Public Function GetNamespace(proj As Project) As String
Dim prop As [Property]
prop = proj.Properties.Item("DefaultNamespace")
Return prop.Value
End Function






The full lists of the members of the various property collections are
linked to from the help page entitled "Properties Property (General Extensibility)," which can be
found here:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsintro7/html/vxlrfPropertiesPropertyGeneralExtensibility.asp

The "See Also" section of this page
contains links to pages that describe what can be found in the
Properties collection for the various objects in
the DTE model that support this property.

The DTE object itself also has a
Properties property, but it works slightly
differently. It contains systemwide settings, as configured in the
Options dialog (Tools Options). But unlike the
other Properties properties, this one is not a
collection object. Instead, it is a parameterized property that takes
two strings, a Category and a
Page. These mostly correspond to the Options
dialog's categories and pages. For example, you can
access the settings in the Environment category's
General page with DTE.Properties("Environment",
"General"). However, there are a few documented
anomalies. For example, although the Fonts and Colors page is in the
Environment category, you must use
DTE.Properties("FontsAndColors",
"TextEditor") to access these settings.


8.1.2 User Interface Objects


The DTE object model has two
main kinds of objects that represent user interface elements:
Window objects and CommandBar
objects. Window objects represent windows, such as
document editor windows, the Toolbox, the Solution Explorer, the
Breakpoint window, and so on. CommandBar objects
represent menu bars and toolbars, such as the main menu.

8.1.2.1 Window objects


For each visible window, whether it is
the main VS.NET window, a document window, or a tool window, there is
a corresponding Window object available in the DTE
object hierarchy. You can obtain these objects in a number of ways.

The DTE object itself provides two properties that
provide direct access to certain windows. Its
MainWindow property refers to the main VS.NET
window. The ActiveWindow property refers to
whichever window currently has the input focus.

The DTE object also provides a Windows property.
This is a collection of Window objects and allows
access to every window in the VS.NET UI. The property is indexed by
the window kind, which is a GUID that indicates
the type of window. This GUID would normally be one of those listed
in the DTE's Constants
enumeration, which defines a series of
vsWindowKindXxx values
for the built-in window types. (The documentation page entitled
"vsWindowKind constants" provides
the full list of built-in windows and their corresponding
vsWindowKind names.) Example 8-3 shows how to use
this collection to obtain the Window object for
the Solution Explorer.

Example 8-3. Obtaining a particular Window object

Dim wnd As Window
wnd = DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer)






If you enumerate through the DTE.Windows
collection using a For Each construct, you may be
surprised by the results. The collection will appear to contain only
entries for windows that have either been made visible at some point
or been explicitly requested from the Windows
collection. This is because the Windows collection
is populated on demand. (This is not a problem if you ask for a
window by name, as Example 8-3 doesif the
relevant window was not already in the collection, it will be added
at that point.)

Once you have a Window object, you can perform
various operations on it. As you would expect, anything that can be
done interactively can also be done through code. The
AutoHides property determines whether the window
disappears when it loses the focusthis corresponds to the
pushpin icon on the window. The IsFloating
property determines whether the window is currently docked. The
Top, Left,
Width, and Height properties
allow the window's size and position to be set when
it is undocked. The Visible property determines
whether it is shown at all. The Activate method
gives the window the focus.

If the window is an editor window, you can access the associated
document through its Document property. Certain
window types provide an extra programming interface, which is
available from the Window
object's Object property. All of
the windows that show a tree view (e.g., the Solution Explorer or the
class view) use this to provide an object of type
UIHierarchy. UIHierarchy
objects provide a GetItem method that allows
access to any item in the tree. It also provides
SelectUp and SelectDown methods
for navigation and a DoDefaultAction method to
allow a double-click to be simulated.

Example 8-4 shows the use of the
UIHierarchy object. It obtains the
Window object for the Solution Explorer and then
retrieves the UIHierarchy object. It then calls
GetItem on this to retrieve the item representing
the MyProject project in the
MySolution solution. It then calls
Select on this, in order to make that the
currently selected item.

Example 8-4. Using the UIHierarchy object

Dim wnd As Window
wnd = DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer)
Dim uih As UIHierarchy
uih = wnd.Object
Dim uihItem as UIHierarchyItem
uihItem = uih.GetItem("MySolution\MyProject")
uihItem.Select(vsUISelectionType.vsUISelectionTypeSelect)

8.1.2.2 CommandBar objects


CommandBar objects represent menus or toolbars. There is
no distinction between a menu bar and a toolbarbuttons can be
dragged onto the menu bar, and menu items can be dragged onto button
bars.






VS.NET uses Microsoft Office toolbars, so the
CommandBar type is defined in the
Microsoft.Office.Core namespace in the
office.dll component. Macro projects and VS.NET
add-in projects have a reference to this component added
automatically.

The DTE object has a
CommandBars property. This is a collection that
contains every command bar in the VS.NET UI. (It includes any that
are currently invisible, as well as all the visible ones.) The
collection is indexed by the name of the command bars. It also
provides an Add method that allows you to create
new command bars.

CommandBar objects provide various properties that
let you control their appearance and contents. Example 8-5 shows how to locate the
Standard command bar (one of the built-in VS.NET
toolbars) from the DTE object's
CommandBars collection. It then toggles the
bar's position between being docked to the top of
the screen and floating.

Example 8-5. Changing a command bar's position

Imports Microsoft.Office.Core
Public Module MyModule
Public Sub AddToolbar( )
Dim cmdBar As CommandBar
cmdBar = DTE.CommandBars.Item("Standard")
If cmdBar.Position = MsoBarPosition.msoBarTop Then
cmdBar.Position = MsoBarPosition.msoBarFloating
Else
cmdBar.Position = MsoBarPosition.msoBarTop
End If
End Sub
End Module

The most interesting property of any CommandBar
object is the Controls property. This is a
collection of CommandBarControl objects, one for
each item on the bar. There are several different types of control.
You can find out which type any particular control is from its
Type property, which will return an item from the
msoControlType enumeration. Menus have a type of
msoControlPopup, and the objects that represent
menus can be cast to the CommandBarPopup type.
Leafs in a menu and buttons on a toolbar both have the type
msoControlButton. Objects in the
bar's Controls collection that
have this type can be cast to the CommandBarButton
type. Example 8-6 shows how to navigate through a
tree of pop ups in a command barin this case we are using the
main menu in VS.NET, which is a command bar called
"MenuBar". Example 8-6 locates
the File menu and then the Source Control submenu, before executing
the Open from Source Control... menu item.

Example 8-6. Navigating through controls in a menu

Imports Microsoft.Office.Core
Public Module MyModule
Public Sub UseCommandbar( )
Dim cmdBar As CommandBar
Dim ctl As CommandBarControl
Dim cmdPopup As CommandBarPopup
Dim cmdButton As CommandBarButton
cmdBar = DTE.CommandBars.Item("MenuBar")
ctl = cmdBar.Controls("File")
If ctl.Type = MsoControlType.msoControlPopup Then
cmdPopup = ctl
ctl = cmdPopup.Controls("Source Control")
If ctl.Type = MsoControlType.msoControlPopup Then
cmdPopup = ctl
ctl = cmdPopup.Controls("Open From Source Control...")
If ctl.Type = MsoControlType.msoControlButton Then
cmdButton = ctl
cmdButton.Execute( )
End If
End If
End If
End Sub
End Module

In fact, this code is unnecessarily complexnavigating through
toolbars is required only if you wish to modify them in some way. If
you merely wish to execute the command they represent, you should
just use the corresponding Command object. You
also need to use a Command object if you want to
add an item to a command bar that actually does somethinga
command bar button must be associated with the command that it
invokes.


8.1.3 Command Objects


Most user
actions in VS.NET are associated with a command. There are commands
for every action in the editor, such as entering text or moving the
cursor. Each dialog has a command that opens it. Every action
accessible through toolbars and menus is associated with a command.






Appendix C lists the names of all of the commands
that have keyboard shortcuts.

Every command has a corresponding Command object,
which can be obtained through the DTE
object's Commands collection.
Commands are identified by name, available from the
Command object's
Name property. This name can also be used to
invoke a command with the DTE
object's ExecuteCommand method.
Example 8-7 shows the more succinct way of invoking
the same command that Example 8-6 executes.

Example 8-7. Executing a command

DTE.ExecuteCommand("File.OpenFromSourceControl")

If you want to add an item to a toolbar menu that invokes a
particular command, you simply obtain the relevant command object and
call its AddControl method, passing in a reference
to the command bar to which you would like to add a control. Example 8-8 shows how to add a button for the
OpenFromSourceControl command as the fourth item
in the Standard toolbar.

Example 8-8. Adding a command to a command bar

Dim cmd As Command
cmd = DTE.Commands.Item("File.OpenFromSourceControl")
cmd.AddControl(DTE.CommandBars("Standard"), 4)

You can create your own custom command objects, although you will
need to write an add-in to provide code that will run when the
command is executed. This is done with the DTE
object's Commands collection,
which has an AddNamedCommand method. This allows
you to create a command, specifying the name, the text that should be
used for this command on command bars, optional tooltip text, and the
bitmap that should be used to represent the command on any command
bar. The VS.NET Add-in Wizard described later in this chapter can
generate code to add a new command and attach it to the Tools menu
for you.


8.1.4 Document Objects


Every
document open for editing in VS.NET has a corresponding
Document object, which allows the
document's contents to be manipulated. If the
document is a text file, the Document
object's Object property will
return a TextDocument object, which provides
operations specific to text files.

The DTE object provides two properties through
which you can obtain a Document object. The
ActiveDocument property returns the document that
has the focus (or, if a tool window currently has the focus, the
document that most recently had the focus). The
Documents property is a collection of all open
documents.

Most manipulation of a document is done through the
document's Selection property.
For a text document, this will be a TextSelection
object. This represents the current selection, or, if there is no
selection, the cursor location. It provides methods equivalent to the
keystrokes for navigating around documentsfor example, the
LineUp, LineDown,
CharLeft, CharRight,
PageUp, PageDown,
StartOfDocument, and
EndOfDocument methods. Each of these takes a
Boolean indicating whether the operation should extend the current
selection or not. (This is equivalent to whether or not you hold down
the Shift key when using the corresponding keystroke.) An
Insert method inserts text at the current cursor
location. Cut, Copy, and
Paste methods correspond to the standard clipboard
operations.


8.1.5 Debugger Object


The
DTE object provides a property called
Debugger. This is an object that allows the
debugger to be controlled. This provides a
Breakpoints collection, allowing breakpoints to be
created, destroyed, or modified. For multiprocess and multithreaded
debugging, it allows the current process and thread to be retrieved
or set using the CurrentProcess and
CurrentThread properties. It provides methods that
correspond to each of the debugger actions. (See Chapter 3 for more information on debugging.) Example 8-9 shows how to use the
Debugger object to step into the current line of
code.

Example 8-9. Using the Debugger object

Dim dbg As EnvDTE.Debugger
dbg = DTE.Debugger
dbg.StepInto( )


8.1.6 Source Control Object


The DTE
object provides a SourceControl property. This is
an object that allows certain source control operations to be
performed. Unfortunately, it is fairly primitive. All operations use
filenamesyou cannot pass a ProjectItem
object in, for example. And you cannot check items inyou can
only perform four source control operations.

You can discover whether items are under source control at all with
the IsItemUnderSCC method. You can call the
IsItemCheckedOut method to discover whether an
item is already checked out. You can exclude items from source
control with ExcludeItem or
ExcludeItems. And you can check items out with the
CheckoutItem or CheckoutItems
methods.


8.1.7 DTE Events


The DTE object model is able to notify us when certain events happen.
These events are raised through the standard COM notification
mechanism (connection points). Events are grouped into categories,
and as Figure 8-2 shows, each category has a
corresponding event source object. (The objects shown with bold names
are event sources. The other objects indicate how to navigate through
the DTE object hierarchy to find the event sources.) Most of these
objects are accessed through the DTE object's
Events property. For example, build events are
raised by the DTE.Events.BuildEvents object.


Figure 8-2. DTE event objects


VSProject objects supply extra events specific to
.NET projects through their VSProjectEvents
objects. (VSProject objects are available on .NET
projects, and are accessed through the associated
Project object's
Object property. Project
objects can be accessed through the
DTE.Solution.Projects collection.) These projects
also provide project-specific events for individual items through the
VSProjectItemEvents objects.

Add-ins can use normal COM event handling to deal with events from
these objects, but macros must use their own technique. This is
discussed in the next section, Section 8.2; see Example 8-13 for an illustration of the technique.

/ 148