SlideShare une entreprise Scribd logo
1  sur  11
Télécharger pour lire hors ligne
Visual	C++	project	model
Author: Paul Eremeev
Date: 29.10.2012
Abstract
This article covers the structure of Visual C++ project model (VCProject). Also included are the cases of
using the project model for enumeration of project elements and obtaining their compilation properties
through the corresponding configurations.
Introduction
Visual C++ project model is a collection of interfaces describing the properties of a compiler, linker and
other build tools, as well as the structure of MSVS-compatible projects themselves, and it is connected
with the Visual Studio Automation Object Model through the VCProjects late-bound properties. Visual
C++ project model extends the standard Visual Studio project model, providing access to the specific
functionality of Visual C++ (vcproj/vcxproj) project types. Visual C++ project model is a stand-alone COM
component available through the VCProjectEngine.dll assembly, which could also be used independently
outside of Visual Studio development environment.
VCProject model structure
Visual Studio provides an extendable project-neutral object model that represents solutions, projects,
code objects, documents, etc. Every MSVS project type has a corresponding project automation
interface. Every tool in the environment that has a project also has an object of the 'Project' type
associated with it. Visual C++ project model also complies with this general automation project model
scheme:
Projects
|- Project -- Object(unique for the project type)
|- ProjectItems (a collection of ProjectItem)
|- ProjectItem (single object) -- ProjectItems (another
collection)
|- Object(unique for the project type)
The 'Projects' interface provides an ensemble of abstract objects of the 'Project' type. The 'Project'
interface defines an abstract project, i.e. it can reference an object from any project model that
complies with the standard scheme. Any peculiar properties of a specific model should be defined
through a special interface which is unique only to this model alone. A reference for such an object
could be acquired through the Project.Object property. For instance, specific properties of Visual C++
project could be obtained through the VCProject interface:
VCProject vcproj = proj.Object as VCProject;
It is possible to obtain a list of all projects loaded in IDE and belonging to any project model type
through the dte.Solution.Projects field; projects belonging to a particular model can be acquired through
the DTE.GetObject method (see the example below for Visual C++ model):
Projects vcprojs = m_dte.GetObject("VCProjects") as Projects;
The ProjectItems interface represents an ensemble of abstract solution tree elements of 'ProjectItem'
type. Similar to the 'Project' interface, the 'ProjectItem' can define any kind of element; it can even
contain the same 'ProjectItems' collection inside itself (accessible through the ProjectItem.ProjectItems)
or it can be a Project altogether. An object unique for a specific project model can be obtained through
the ProjectItem.Object field. For instance, a Visual C++ source code file is represented by a VCFile type:
VCFile file = projectItem.Object as VCFile;
An embedded project can be obtained in a similar manner:
Project proj = projectItem.Object as Project;
Recursively walking all elements of a Solution tree's branch
The interface for controlling hierarchies IVsHierarchy can be used to perform a passing of Solution tree's
branch. This interface provides an access to abstract nodes of a tree, each one of which in turn could be
a leaf, a container of elements or a link to another hierarchy. Each tree node is uniquely identified
through the DWORD identifier VSITEMID. Such identifiers are unique within the scope of a single
hierarchy and possess a limited lifetime within it.
A hierarchy object can be obtained for a tree branch of a single project through the
VsShellUtilities.GetHierarchy method:
public static IVsHierarchy ToHierarchy(EnvDTE.Project project)
{
System.IServiceProvider serviceProvider =
new ServiceProvider(project.DTE as
Microsoft.VisualStudio.OLE.Interop.IServiceProvider);
Guid guid = GetProjectGuid(serviceProvider, project);
if (guid == Guid.Empty)
return null;
return VsShellUtilities.GetHierarchy(serviceProvider, guid);
}
In the example above, the hierarchy was obtained for a project through its GUID identifier. Consider the
example of obtaining this GUID identifier for a project:
private static Guid GetProjectGuid(System.IServiceProvider
serviceProvider, Project project)
{
if (ProjectUnloaded(project))
return Guid.Empty;
IVsSolution solution =
(IVsSolution)serviceProvider.GetService(typeof(SVsSolution)) as
IVsSolution;
IVsHierarchy hierarchy;
solution.GetProjectOfUniqueName(project.FullName, out hierarchy);
if (hierarchy != null)
{
Guid projectGuid;
ErrorHandler.ThrowOnFailure(
hierarchy.GetGuidProperty(
VSConstants.VSITEMID_ROOT,
(int)__VSHPROPID.VSHPROPID_ProjectIDGuid,
out projectGuid));
if (projectGuid != null)
{
return projectGuid;
}
}
return Guid.Empty;
}
The IEnumHierarchies interface permits obtaining all of the hierarchies for projects of a particular type
through the solution. GetProjectEnum method. Here is an example of obtaining the hierarchies for every
Visual C++ project in a solution tree:
IVsSolution solution = PVSStudio._IVsSolution;
if (null != solution)
{
IEnumHierarchies penum;
Guid nullGuid = Guid.Empty;
Guid vsppProjectGuid =
new Guid("8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942");
//You can ask the solution to enumerate projects based on the
//__VSENUMPROJFLAGS flags passed in. For
//example if you want to only enumerate C# projects use
//EPF_MATCHTYPE and pass C# project guid. See
//CommonIDLvsshell.idl for more details.
int hr = solution.GetProjectEnum(
(uint)(__VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION |
__VSENUMPROJFLAGS.EPF_MATCHTYPE),
ref vsppProjectGuid, out penum);
ErrorHandler.ThrowOnFailure(hr);
if ((VSConstants.S_OK == hr) && (penum != null))
{
uint fetched;
IVsHierarchy[] rgelt = new IVsHierarchy[1];
PatternsForActiveConfigurations.Clear();
while (penum.Next(1, rgelt, out fetched) == 0 && fetched == 1)
{
...
}
}
}
As evident by the example above, the GetProjectEnum method provides hierarchies for projects based
on a project kind specified by the GUID identifier. GUID identifiers for regular Visual Studio/MSBuild
project types can be obtained here. The penum.Next() method allows us to enumerate all project
hierarchies we've acquired (the rgelt array). It should be remembered that user-created project models
could possess their own unique identifiers in case they define a new project type for themselves.
But our own experience in developing PVS-Studio IDE plug-in demonstrates that an opposite situation is
quite possible as well, that is, when a user-created project type uses a GUID from one of the stock
project types, usually the one from which it was derived. In particular, we've encountered a VCProject
type that was extended to provide development for Android platform. As a result, this project model
extension had caused crashes in our plug-in because it did not provide several properties which are
otherwise present in VCProject model (OpenMP for example) through the automation API. An intricacy
of this situation is that such an extended project model type cannot be differentiated from a regular
one, and thus, it is quite hard to correctly process it as well. Therefore, when you are extending a
project model through your custom types, to avoid such conflicts with various IDE components
(including other third-party extensions as well), it is always important to remember the necessity of
providing means to uniquely identify your types.
Possessing an IVsHierarchy for the project, we are able to recursively enumerate all the elements of
such solution tree branch through the hierarchy.GetProperty method, which in turn provides us with the
specified properties for each one of the hierarchy nodes:
EnumHierarchyItemsFlat(VSConstants.VSITEMID_ROOT, MyProjectHierarchy,
0, true);
...
public void EnumHierarchyItemsFlat(uint itemid, IVsHierarchy
hierarchy, int recursionLevel, bool visibleNodesOnly)
{
if (hierarchy == null)
return;
int hr; object pVar;
hr = hierarchy.GetProperty(itemid,
(int)__VSHPROPID.VSHPROPID_ExtObject, out pVar);
ProjectItem projectItem = pVar as ProjectItem;
if (projectItem != null)
{
...
}
recursionLevel++;
//Get the first child node of the current hierarchy being walked
hr = hierarchy.GetProperty(itemid,
(visibleNodesOnly ? (int)__VSHPROPID.VSHPROPID_FirstVisibleChild
:(int)__VSHPROPID.VSHPROPID_FirstChild),
out pVar);
Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(hr);
if (VSConstants.S_OK == hr)
{
//We are using Depth first search so at each level we recurse
//to check if the node has any children
// and then look for siblings.
uint childId = GetItemId(pVar);
while (childId != VSConstants.VSITEMID_NIL)
{
EnumHierarchyItemsFlat(childId, hierarchy, recursionLevel,
visibleNodesOnly);
hr = hierarchy.GetProperty(childId,
(visibleNodesOnly ?
(int)__VSHPROPID.VSHPROPID_NextVisibleSibling :
(int)__VSHPROPID.VSHPROPID_NextSibling),
out pVar);
if (VSConstants.S_OK == hr)
{
childId = GetItemId(pVar);
}
else
{
Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(hr);
break;
}
}
}
}
private uint GetItemId(object pvar)
{
if (pvar == null) return VSConstants.VSITEMID_NIL;
if (pvar is int) return (uint)(int)pvar;
if (pvar is uint) return (uint)pvar;
if (pvar is short) return (uint)(short)pvar;
if (pvar is ushort) return (uint)(ushort)pvar;
if (pvar is long) return (uint)(long)pvar;
return VSConstants.VSITEMID_NIL;
}
A ProjectItem object that we've acquired for each one of the tree's nodes will allow us to obtain its
corresponding Visual C++ object through the 'Object' filed, as was described earlier.
Enumerating all projects in solution tree
DTE.Solution.Projects interface can be used to enumerate all projects in the solution:
if (m_DTE.Solution.Projects != null)
{
try
{
foreach (object prj in m_DTE.Solution.Projects)
{
EnvDTE.Project proj = prj as EnvDTE.Project;
if (proj != null)
WalkSolutionFolders(proj);
}
}
}
Besides projects, Solution tree can also contain folder nodes (Solution Folders). They should also be
taken into account while processing each Project element:
public void WalkSolutionFolders(Project prj)
{
VCProject vcprj = prj.Object as VCProject;
if (vcprj != null && prj.Kind.Equals(VCCProjectTypeGUID))
{
if (!ProjectExcludedFromBuild(prj))
{
IVsHierarchy projectHierarchy = ToHierarchy(prj);
EnumHierarchyItemsFlat(VSConstants.VSITEMID_ROOT,
projectHierarchy, 0, false);
}
}
else if (prj.ProjectItems != null)
{
foreach (ProjectItem item in prj.ProjectItems)
{
Project nextlevelprj = item.Object as Project;
if (nextlevelprj != null && !ProjectUnloaded(nextlevelprj))
WalkSolutionFolders(nextlevelprj);
}
}
}
Projects that are excluded from the build should be inspected separately, as they are not accessible
through the automation model after being unloaded from the IDE:
public bool ProjectExcludedFromBuild(Project project)
{
if (project.UniqueName.Equals("<MiscFiles>",
StringComparison.InvariantCultureIgnoreCase))
return true;
Solution2 solution = m_DTE.Solution as Solution2;
SolutionBuild2 solutionBuild =
(SolutionBuild2)solution.SolutionBuild;
SolutionContexts projectContexts =
solutionBuild.ActiveConfiguration.SolutionContexts;
//Skip this project if it is excluded from build.
bool shouldbuild =
projectContexts.Item(project.UniqueName).ShouldBuild;
return !shouldbuild;
}
Enumerating selected elements
The DTE.SelectedItems interface can be used to enumerate solution elements which are selected in the
Solution Explorer window.
foreach (SelectedItem item in items)
{
VCProject vcproj = null;
if (item.Project != null)
{
vcproj = item.Project.Object as VCProject;
if (vcproj != null && item.Project.Kind.Equals("{" +
VSProjectTypes.VCpp + "}"))
{
IVsHierarchy projectHierarchy = ToHierarchy(item.Project);
PatternsForActiveConfigurations.Clear();
EnumHierarchyItemsFlat(VSConstants.VSITEMID_ROOT,
projectHierarchy, 0, false, files, showProgressDialog);
}
else if (item.Project.ProjectItems != null)
{
//solution folder
if (!ProjectUnloaded(item.Project))
WalkSolutionFolders(item.Project);
}
}
else if (item.ProjectItem != null)
{
//walking files
...
else if (item.ProjectItem.ProjectItems != null)
if (item.ProjectItem.ProjectItems.Count > 0)
WalkProjectItemTree(item.ProjectItem);
}
}
private void WalkProjectItemTree(object CurrentItem)
{
Project CurProject = null;
CurProject = CurrentItem as Project;
if (CurProject != null)
{
IVsHierarchy projectHierarchy = ToHierarchy(CurProject);
PatternsForActiveConfigurations.Clear();
EnumHierarchyItemsFlat(VSConstants.VSITEMID_ROOT,
projectHierarchy, 0, false);
return;
}
ProjectItem item = null;
item = CurrentItem as ProjectItem;
if (item != null)
{
...
if (item.ProjectItems != null)
if (item.ProjectItems.Count > 0)
{
foreach (object NextItem in item.ProjectItems)
WalkProjectItemTree(NextItem);
}
}
}
Configurations and properties of projects and files
Visual C++ stores build configurations (compilation and linking parameters, pre-build and post-build
steps, external tool command lines etc.) for C/C++ source files inside its XML-based project files
(vcproj/vcxproj). These settings are available to Visual Studio users through property page dialogs.
Each combination of project's build configuration (Debug, Release, etc.) and a platform (Win32, IA64,
x64, etc.) is associated with a separate collection of settings. Although majority of the settings are
defined at the project level, it is possible to redefine separate properties for each individual file (file
properties are inherited from its project by default). The list of properties which can be redefined at the
file level is dependent upon the type of a file in question. For example, only the ExcludedFromBuild
property can be redefined for header files, but cpp source files permit the redefinition for any of its
compilation properties.
Obtaining configurations
Visual C++ project model presents property pages through the VCConfiguration (for a project) and
VCFileConfiguration (for a file) interfaces. To obtain these objects we will start from a ProjectItem object
which represents an abstract Solution tree element.
ProjectItem item;
VCFile vcfile = item.Object as VCFile;
Project project = item.ContainingProject;
String pattern = "Release|x64";
if (String.IsNullOrEmpty(pattern))
return null;
VCFileConfiguration fileconfig = null;
IVCCollection fileCfgs = (IVCCollection)vcfile.FileConfigurations;
fileconfig = fileCfgs.Item(pattern) as VCFileConfiguration;
if (fileconfig == null)
if (fileCfgs.Count == 1)
fileconfig = (VCFileConfiguration)fileCfgs.Item(0);
In the example above we've acquired a file configuration for VCFile object (which represents a C/C++
header or a source file) by passing a configuration pattern (configuration's name and platform) to the
Item() method. Build configuration pattern is defined on the project level. The following example
demonstrates the acquisition of active configuration (the one that is selected in IDE) of a project.
ConfigurationManager cm = project.ConfigurationManager;
Configuration conf = cm.ActiveConfiguration;
String platformName = conf.PlatformName;
String configName = conf.ConfigurationName;
String pattern = configName + "|" + platformName;
return pattern;
The ActiveConfiguration interface should be handled with care. Quite often we've encountered
exceptions when calling it from our PVS-Studio IDE extension package. In particular, this field sometimes
becomes inaccessible through the automation object model when a user is building a project, or in the
presence of any other heavy user interaction with Visual Studio UI. As there is no assured way of
predicting such user actions, it is advised to provide additional error handlers for such 'bottlenecks'
when accessing settings with automation model. It should be noted that this particular situation is not
related to COM exception handling that was described in the previous article dedicated to EnvDTE
interfaces, and it is probably related to some internal issues within the automation model itself.
Next, let's acquire the configuration for a project that contains the file in question:
VCConfiguration cfg=(VCConfiguration)fileconfig.ProjectConfiguration;
While the interfaces representing configurations themselves contain settings only from the 'General' tab
of the property pages, references for individual build tools can be acquired through the
VCConfiguration.Tools and VCFileConfiguration.Tool interfaces (note that a single file contains settings
respectively for only one build tool). Let's examine the VCCLCompilerTool interface representing the C++
compiler:
ct = ((IVCCollection)cfg.Tools).Item("VCCLCompilerTool") as
VCCLCompilerTool;
ctf = fileconfig.Tool as VCCLCompilerTool;
Now let's acquire the contents of, for example, the AdditionalOptions field belonging to the compiler
tool, using the 'Evaluate' method to process any macros that we can encounter within its value:
String ct_add = fileconfig.Evaluate(ct.AdditionalOptions);
String ctf_add = fileconfig.Evaluate(ctf.AdditionalOptions);
Property Sheets
Property sheets are XML files with a props extension. They allow an independent definition of project's
build properties, i.e. the command line parameters for various building tools, such as a compiler or a
linker. Property sheets also support inheritance and can be used for specifying build configurations for
several projects at once, i.e. the configuration defined inside the project file itself (vcproj/vcxproj) could
inherit some of its properties from single or multiple props files.
To handle property sheets, Visual C++ project model provides the VCPropertySheet interface. A
collection of VCPropertySheet objects can be obtained through the VCConfiguration. PropertySheets
field:
IVCCollection PSheets_all = fileconfig.PropertySheets;
Similarly, the PropertySheets filed of the VCPropertySheet interface provides a reference to a collection
of child property sheet files for this object. Let's examine the recursive enumeration of all of the
project's property sheets:
private void ProcessAllPropertySheets(VCConfiguration cfg,
IVCCollection PSheets)
{
foreach (VCPropertySheet propertySheet in PSheets)
{
VCCLCompilerTool ctPS =
(VCCLCompilerTool)((IVCCollection)propertySheet.Tools).Item(
"VCCLCompilerTool");
if (ctPS != null)
{
...
IVCCollection InherPSS = propertySheet.PropertySheets;
if (InherPSS != null)
if (InherPSS.Count != 0)
ProcessAllPropertySheets(cfg, InherPSS);
}
}
}
In the example above we've obtained an object of VCCLCompilerTool type (that is compilation settings)
for PropertySheet on every level. In this way we could gather all compilation parameters defined in
every property sheet, including the embedded ones.
The VCPropertySheet interface does not contain means to evaluate macros within its fields, so as a
work-around, the Evaluate method from the project's configuration can be used instead. But, such
approach could also lead to the incorrect behavior in case the value of the macro being evaluated is
related to the props file itself. For instance, several MSBuild macros which were introduced in the
MSBuild version 4 could also be utilized inside vcxproj projects from Visual Studio 2010. Let's take the
MSBuildThisFileDirectory macro that evaluates as a path to the directory containing file in which it is
used. Now, evaluating this macro through the cfg.Evaluate will result in a path to the vcxproj file, and
not to props file, which actually does contains this macro.
All of the property sheets in Visual C++ project can be divided between user and system files. By user
files we understand the props files which were created and added to the project by a user himself. But
even an empty template-generated MSVC project often includes several property sheets by default.
These system props files are utilized by the environment to specify various compilation parameters
which were set inside the project's property page interface by the user. For example, setting up the
CharacterSet property to use Unicode manually in the Property Page interface will result in the
appearance of a special property sheet in the 'Property Sheets' window which will define several
preprocessor symbols (Unicode, _Unicode), and this properties subsequently will be inherited by the
project. Therefore when processing properties from inside a Property sheet, one should always
remember that compilation symbols defined in system props files are also returned by their
corresponding property in the project's configuration through the automation API. Evidently, processing
these two simultaneously while gathering compilation arguments can result in a duplication of such
arguments.
References
1. MSDN. Visual C++ Project Model.
2. MSDN. Project Modeling.
3. MSDN. Automation Model Overview.
Other articles in this series
0. Introduction.
1. Creating, debugging and deploying extension packages for Microsoft Visual Studio
2005/2008/2010/2012.
2. Visual Studio Automation Object Model. EnvDTE interfaces.
3. Visual Studio commands.
4. Visual Studio tool windows.
5. Integrating into Visual Studio settings.
6. Visual C++ project model.

Contenu connexe

Tendances

Qt for Beginners Part 3 - QML and Qt Quick
Qt for Beginners Part 3 - QML and Qt QuickQt for Beginners Part 3 - QML and Qt Quick
Qt for Beginners Part 3 - QML and Qt QuickICS
 
Qt on Real Time Operating Systems
Qt on Real Time Operating SystemsQt on Real Time Operating Systems
Qt on Real Time Operating Systemsaccount inactive
 
06 iec t1_s1_oo_ps_session_08
06 iec t1_s1_oo_ps_session_0806 iec t1_s1_oo_ps_session_08
06 iec t1_s1_oo_ps_session_08Niit Care
 
Building the QML Run-time
Building the QML Run-timeBuilding the QML Run-time
Building the QML Run-timeJohan Thelin
 

Tendances (7)

Qt for Beginners Part 3 - QML and Qt Quick
Qt for Beginners Part 3 - QML and Qt QuickQt for Beginners Part 3 - QML and Qt Quick
Qt for Beginners Part 3 - QML and Qt Quick
 
Qt on Real Time Operating Systems
Qt on Real Time Operating SystemsQt on Real Time Operating Systems
Qt on Real Time Operating Systems
 
Ti conf
Ti confTi conf
Ti conf
 
06 iec t1_s1_oo_ps_session_08
06 iec t1_s1_oo_ps_session_0806 iec t1_s1_oo_ps_session_08
06 iec t1_s1_oo_ps_session_08
 
The Future of Qt Widgets
The Future of Qt WidgetsThe Future of Qt Widgets
The Future of Qt Widgets
 
Building the QML Run-time
Building the QML Run-timeBuilding the QML Run-time
Building the QML Run-time
 
iOS Basic
iOS BasiciOS Basic
iOS Basic
 

En vedette

The D language comes to help
The D language comes to helpThe D language comes to help
The D language comes to helpPVS-Studio
 
PVS-Studio advertisement - static analysis of C/C++ code
PVS-Studio advertisement - static analysis of C/C++ codePVS-Studio advertisement - static analysis of C/C++ code
PVS-Studio advertisement - static analysis of C/C++ codePVS-Studio
 
What do static analysis and search engines have in common? A good "top"!
What do static analysis and search engines have in common? A good "top"!What do static analysis and search engines have in common? A good "top"!
What do static analysis and search engines have in common? A good "top"!PVS-Studio
 
Errors detected in C++Builder
Errors detected in C++BuilderErrors detected in C++Builder
Errors detected in C++BuilderPVS-Studio
 
Static analysis should be used regularly
Static analysis should be used regularlyStatic analysis should be used regularly
Static analysis should be used regularlyPVS-Studio
 
Creating, debugging and deploying extension packages for Microsoft Visual Stu...
Creating, debugging and deploying extension packages for Microsoft Visual Stu...Creating, debugging and deploying extension packages for Microsoft Visual Stu...
Creating, debugging and deploying extension packages for Microsoft Visual Stu...PVS-Studio
 
Intel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionIntel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionPVS-Studio
 
Re-checking the ReactOS project - a large report
Re-checking the ReactOS project - a large reportRe-checking the ReactOS project - a large report
Re-checking the ReactOS project - a large reportPVS-Studio
 
Visual Studio tool windows
Visual Studio tool windowsVisual Studio tool windows
Visual Studio tool windowsPVS-Studio
 
How to make fewer errors at the stage of code writing. Part N1.
How to make fewer errors at the stage of code writing. Part N1.How to make fewer errors at the stage of code writing. Part N1.
How to make fewer errors at the stage of code writing. Part N1.PVS-Studio
 
Software diseases: memset
Software diseases: memsetSoftware diseases: memset
Software diseases: memsetPVS-Studio
 
Wade Not in Unknown Waters. Part Four.
Wade Not in Unknown Waters. Part Four.Wade Not in Unknown Waters. Part Four.
Wade Not in Unknown Waters. Part Four.PVS-Studio
 
What comments hide
What comments hideWhat comments hide
What comments hidePVS-Studio
 
100% code coverage by static analysis - is it that good?
100% code coverage by static analysis - is it that good?100% code coverage by static analysis - is it that good?
100% code coverage by static analysis - is it that good?PVS-Studio
 
Difficulties of comparing code analyzers, or don't forget about usability
Difficulties of comparing code analyzers, or don't forget about usabilityDifficulties of comparing code analyzers, or don't forget about usability
Difficulties of comparing code analyzers, or don't forget about usabilityPVS-Studio
 
Comparing static analysis in Visual Studio 2012 (Visual C++ 2012) and PVS-Studio
Comparing static analysis in Visual Studio 2012 (Visual C++ 2012) and PVS-StudioComparing static analysis in Visual Studio 2012 (Visual C++ 2012) and PVS-Studio
Comparing static analysis in Visual Studio 2012 (Visual C++ 2012) and PVS-StudioPVS-Studio
 
Checking Intel IPP Samples for Windows - Continuation
Checking Intel IPP Samples for Windows - ContinuationChecking Intel IPP Samples for Windows - Continuation
Checking Intel IPP Samples for Windows - ContinuationPVS-Studio
 
Myths about static analysis. The fifth myth - a small test program is enough ...
Myths about static analysis. The fifth myth - a small test program is enough ...Myths about static analysis. The fifth myth - a small test program is enough ...
Myths about static analysis. The fifth myth - a small test program is enough ...PVS-Studio
 
Studying methods of attracting people to a software product's website
Studying methods of attracting people to a software product's websiteStudying methods of attracting people to a software product's website
Studying methods of attracting people to a software product's websitePVS-Studio
 

En vedette (20)

The D language comes to help
The D language comes to helpThe D language comes to help
The D language comes to help
 
PVS-Studio advertisement - static analysis of C/C++ code
PVS-Studio advertisement - static analysis of C/C++ codePVS-Studio advertisement - static analysis of C/C++ code
PVS-Studio advertisement - static analysis of C/C++ code
 
What do static analysis and search engines have in common? A good "top"!
What do static analysis and search engines have in common? A good "top"!What do static analysis and search engines have in common? A good "top"!
What do static analysis and search engines have in common? A good "top"!
 
Errors detected in C++Builder
Errors detected in C++BuilderErrors detected in C++Builder
Errors detected in C++Builder
 
Static analysis should be used regularly
Static analysis should be used regularlyStatic analysis should be used regularly
Static analysis should be used regularly
 
Creating, debugging and deploying extension packages for Microsoft Visual Stu...
Creating, debugging and deploying extension packages for Microsoft Visual Stu...Creating, debugging and deploying extension packages for Microsoft Visual Stu...
Creating, debugging and deploying extension packages for Microsoft Visual Stu...
 
Intel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correctionIntel IPP Samples for Windows - error correction
Intel IPP Samples for Windows - error correction
 
Re-checking the ReactOS project - a large report
Re-checking the ReactOS project - a large reportRe-checking the ReactOS project - a large report
Re-checking the ReactOS project - a large report
 
Visual Studio tool windows
Visual Studio tool windowsVisual Studio tool windows
Visual Studio tool windows
 
How to make fewer errors at the stage of code writing. Part N1.
How to make fewer errors at the stage of code writing. Part N1.How to make fewer errors at the stage of code writing. Part N1.
How to make fewer errors at the stage of code writing. Part N1.
 
Software diseases: memset
Software diseases: memsetSoftware diseases: memset
Software diseases: memset
 
Wade Not in Unknown Waters. Part Four.
Wade Not in Unknown Waters. Part Four.Wade Not in Unknown Waters. Part Four.
Wade Not in Unknown Waters. Part Four.
 
What comments hide
What comments hideWhat comments hide
What comments hide
 
100% code coverage by static analysis - is it that good?
100% code coverage by static analysis - is it that good?100% code coverage by static analysis - is it that good?
100% code coverage by static analysis - is it that good?
 
Difficulties of comparing code analyzers, or don't forget about usability
Difficulties of comparing code analyzers, or don't forget about usabilityDifficulties of comparing code analyzers, or don't forget about usability
Difficulties of comparing code analyzers, or don't forget about usability
 
Comparing static analysis in Visual Studio 2012 (Visual C++ 2012) and PVS-Studio
Comparing static analysis in Visual Studio 2012 (Visual C++ 2012) and PVS-StudioComparing static analysis in Visual Studio 2012 (Visual C++ 2012) and PVS-Studio
Comparing static analysis in Visual Studio 2012 (Visual C++ 2012) and PVS-Studio
 
Cppcheck
CppcheckCppcheck
Cppcheck
 
Checking Intel IPP Samples for Windows - Continuation
Checking Intel IPP Samples for Windows - ContinuationChecking Intel IPP Samples for Windows - Continuation
Checking Intel IPP Samples for Windows - Continuation
 
Myths about static analysis. The fifth myth - a small test program is enough ...
Myths about static analysis. The fifth myth - a small test program is enough ...Myths about static analysis. The fifth myth - a small test program is enough ...
Myths about static analysis. The fifth myth - a small test program is enough ...
 
Studying methods of attracting people to a software product's website
Studying methods of attracting people to a software product's websiteStudying methods of attracting people to a software product's website
Studying methods of attracting people to a software product's website
 

Similaire à Visual C++ project model

Building modular software with OSGi - Ulf Fildebrandt
Building modular software with OSGi - Ulf FildebrandtBuilding modular software with OSGi - Ulf Fildebrandt
Building modular software with OSGi - Ulf Fildebrandtmfrancis
 
.NET Portfolio
.NET Portfolio.NET Portfolio
.NET Portfoliomwillmer
 
Use Eclipse technologies to build a modern embedded IDE
Use Eclipse technologies to build a modern embedded IDEUse Eclipse technologies to build a modern embedded IDE
Use Eclipse technologies to build a modern embedded IDEBenjamin Cabé
 
Visual Studio Automation Object Model. EnvDTE interfaces
Visual Studio Automation Object Model. EnvDTE interfacesVisual Studio Automation Object Model. EnvDTE interfaces
Visual Studio Automation Object Model. EnvDTE interfacesPVS-Studio
 
React Native for multi-platform mobile applications
React Native for multi-platform mobile applicationsReact Native for multi-platform mobile applications
React Native for multi-platform mobile applicationsMatteo Manchi
 
HexRaysCodeXplorer: make object-oriented RE easier
HexRaysCodeXplorer: make object-oriented RE easierHexRaysCodeXplorer: make object-oriented RE easier
HexRaysCodeXplorer: make object-oriented RE easierAlex Matrosov
 
Aleksandr Matrosov, Eugene Rodionov - HexRaysCodeXplorer make object-oriented...
Aleksandr Matrosov, Eugene Rodionov - HexRaysCodeXplorer make object-oriented...Aleksandr Matrosov, Eugene Rodionov - HexRaysCodeXplorer make object-oriented...
Aleksandr Matrosov, Eugene Rodionov - HexRaysCodeXplorer make object-oriented...DefconRussia
 
Object Oriented Code RE with HexraysCodeXplorer
Object Oriented Code RE with HexraysCodeXplorerObject Oriented Code RE with HexraysCodeXplorer
Object Oriented Code RE with HexraysCodeXplorerAlex Matrosov
 
DESIGNING A PERSISTENCE FRAMEWORK WITH PATTERNS.ppt
DESIGNING A PERSISTENCE FRAMEWORK WITH PATTERNS.pptDESIGNING A PERSISTENCE FRAMEWORK WITH PATTERNS.ppt
DESIGNING A PERSISTENCE FRAMEWORK WITH PATTERNS.pptAntoJoseph36
 
Patterns (contd)Software Development ProcessDesign patte.docx
Patterns (contd)Software Development ProcessDesign patte.docxPatterns (contd)Software Development ProcessDesign patte.docx
Patterns (contd)Software Development ProcessDesign patte.docxdanhaley45372
 
03 oo with-c-sharp
03 oo with-c-sharp03 oo with-c-sharp
03 oo with-c-sharpNaved khan
 
Extending Groovys Swing User Interface in Builder to Build Richer Applications
Extending Groovys Swing User Interface in Builder to Build Richer ApplicationsExtending Groovys Swing User Interface in Builder to Build Richer Applications
Extending Groovys Swing User Interface in Builder to Build Richer ApplicationsJames Williams
 
OpenERP Technical Memento
OpenERP Technical MementoOpenERP Technical Memento
OpenERP Technical MementoOdoo
 
CodeMash - Building Rich Apps with Groovy SwingBuilder
CodeMash - Building Rich Apps with Groovy SwingBuilderCodeMash - Building Rich Apps with Groovy SwingBuilder
CodeMash - Building Rich Apps with Groovy SwingBuilderAndres Almiray
 
Intro to object oriented programming
Intro to object oriented programmingIntro to object oriented programming
Intro to object oriented programmingDavid Giard
 

Similaire à Visual C++ project model (20)

Building modular software with OSGi - Ulf Fildebrandt
Building modular software with OSGi - Ulf FildebrandtBuilding modular software with OSGi - Ulf Fildebrandt
Building modular software with OSGi - Ulf Fildebrandt
 
.NET Portfolio
.NET Portfolio.NET Portfolio
.NET Portfolio
 
Use Eclipse technologies to build a modern embedded IDE
Use Eclipse technologies to build a modern embedded IDEUse Eclipse technologies to build a modern embedded IDE
Use Eclipse technologies to build a modern embedded IDE
 
Visual Studio Automation Object Model. EnvDTE interfaces
Visual Studio Automation Object Model. EnvDTE interfacesVisual Studio Automation Object Model. EnvDTE interfaces
Visual Studio Automation Object Model. EnvDTE interfaces
 
React Native for multi-platform mobile applications
React Native for multi-platform mobile applicationsReact Native for multi-platform mobile applications
React Native for multi-platform mobile applications
 
HexRaysCodeXplorer: make object-oriented RE easier
HexRaysCodeXplorer: make object-oriented RE easierHexRaysCodeXplorer: make object-oriented RE easier
HexRaysCodeXplorer: make object-oriented RE easier
 
Aleksandr Matrosov, Eugene Rodionov - HexRaysCodeXplorer make object-oriented...
Aleksandr Matrosov, Eugene Rodionov - HexRaysCodeXplorer make object-oriented...Aleksandr Matrosov, Eugene Rodionov - HexRaysCodeXplorer make object-oriented...
Aleksandr Matrosov, Eugene Rodionov - HexRaysCodeXplorer make object-oriented...
 
Object Oriented Code RE with HexraysCodeXplorer
Object Oriented Code RE with HexraysCodeXplorerObject Oriented Code RE with HexraysCodeXplorer
Object Oriented Code RE with HexraysCodeXplorer
 
DESIGNING A PERSISTENCE FRAMEWORK WITH PATTERNS.ppt
DESIGNING A PERSISTENCE FRAMEWORK WITH PATTERNS.pptDESIGNING A PERSISTENCE FRAMEWORK WITH PATTERNS.ppt
DESIGNING A PERSISTENCE FRAMEWORK WITH PATTERNS.ppt
 
201005 accelerometer and core Location
201005 accelerometer and core Location201005 accelerometer and core Location
201005 accelerometer and core Location
 
Patterns (contd)Software Development ProcessDesign patte.docx
Patterns (contd)Software Development ProcessDesign patte.docxPatterns (contd)Software Development ProcessDesign patte.docx
Patterns (contd)Software Development ProcessDesign patte.docx
 
Annotation processing tool
Annotation processing toolAnnotation processing tool
Annotation processing tool
 
Design Patterns
Design PatternsDesign Patterns
Design Patterns
 
03 oo with-c-sharp
03 oo with-c-sharp03 oo with-c-sharp
03 oo with-c-sharp
 
Extending Groovys Swing User Interface in Builder to Build Richer Applications
Extending Groovys Swing User Interface in Builder to Build Richer ApplicationsExtending Groovys Swing User Interface in Builder to Build Richer Applications
Extending Groovys Swing User Interface in Builder to Build Richer Applications
 
OpenERP Technical Memento
OpenERP Technical MementoOpenERP Technical Memento
OpenERP Technical Memento
 
Introduction to Objective - C
Introduction to Objective - CIntroduction to Objective - C
Introduction to Objective - C
 
Objective c
Objective cObjective c
Objective c
 
CodeMash - Building Rich Apps with Groovy SwingBuilder
CodeMash - Building Rich Apps with Groovy SwingBuilderCodeMash - Building Rich Apps with Groovy SwingBuilder
CodeMash - Building Rich Apps with Groovy SwingBuilder
 
Intro to object oriented programming
Intro to object oriented programmingIntro to object oriented programming
Intro to object oriented programming
 

Dernier

New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 

Dernier (20)

New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 

Visual C++ project model

  • 1. Visual C++ project model Author: Paul Eremeev Date: 29.10.2012 Abstract This article covers the structure of Visual C++ project model (VCProject). Also included are the cases of using the project model for enumeration of project elements and obtaining their compilation properties through the corresponding configurations. Introduction Visual C++ project model is a collection of interfaces describing the properties of a compiler, linker and other build tools, as well as the structure of MSVS-compatible projects themselves, and it is connected with the Visual Studio Automation Object Model through the VCProjects late-bound properties. Visual C++ project model extends the standard Visual Studio project model, providing access to the specific functionality of Visual C++ (vcproj/vcxproj) project types. Visual C++ project model is a stand-alone COM component available through the VCProjectEngine.dll assembly, which could also be used independently outside of Visual Studio development environment. VCProject model structure Visual Studio provides an extendable project-neutral object model that represents solutions, projects, code objects, documents, etc. Every MSVS project type has a corresponding project automation interface. Every tool in the environment that has a project also has an object of the 'Project' type associated with it. Visual C++ project model also complies with this general automation project model scheme: Projects |- Project -- Object(unique for the project type) |- ProjectItems (a collection of ProjectItem) |- ProjectItem (single object) -- ProjectItems (another collection) |- Object(unique for the project type) The 'Projects' interface provides an ensemble of abstract objects of the 'Project' type. The 'Project' interface defines an abstract project, i.e. it can reference an object from any project model that complies with the standard scheme. Any peculiar properties of a specific model should be defined through a special interface which is unique only to this model alone. A reference for such an object could be acquired through the Project.Object property. For instance, specific properties of Visual C++ project could be obtained through the VCProject interface: VCProject vcproj = proj.Object as VCProject;
  • 2. It is possible to obtain a list of all projects loaded in IDE and belonging to any project model type through the dte.Solution.Projects field; projects belonging to a particular model can be acquired through the DTE.GetObject method (see the example below for Visual C++ model): Projects vcprojs = m_dte.GetObject("VCProjects") as Projects; The ProjectItems interface represents an ensemble of abstract solution tree elements of 'ProjectItem' type. Similar to the 'Project' interface, the 'ProjectItem' can define any kind of element; it can even contain the same 'ProjectItems' collection inside itself (accessible through the ProjectItem.ProjectItems) or it can be a Project altogether. An object unique for a specific project model can be obtained through the ProjectItem.Object field. For instance, a Visual C++ source code file is represented by a VCFile type: VCFile file = projectItem.Object as VCFile; An embedded project can be obtained in a similar manner: Project proj = projectItem.Object as Project; Recursively walking all elements of a Solution tree's branch The interface for controlling hierarchies IVsHierarchy can be used to perform a passing of Solution tree's branch. This interface provides an access to abstract nodes of a tree, each one of which in turn could be a leaf, a container of elements or a link to another hierarchy. Each tree node is uniquely identified through the DWORD identifier VSITEMID. Such identifiers are unique within the scope of a single hierarchy and possess a limited lifetime within it. A hierarchy object can be obtained for a tree branch of a single project through the VsShellUtilities.GetHierarchy method: public static IVsHierarchy ToHierarchy(EnvDTE.Project project) { System.IServiceProvider serviceProvider = new ServiceProvider(project.DTE as Microsoft.VisualStudio.OLE.Interop.IServiceProvider); Guid guid = GetProjectGuid(serviceProvider, project); if (guid == Guid.Empty) return null; return VsShellUtilities.GetHierarchy(serviceProvider, guid); } In the example above, the hierarchy was obtained for a project through its GUID identifier. Consider the example of obtaining this GUID identifier for a project: private static Guid GetProjectGuid(System.IServiceProvider serviceProvider, Project project) { if (ProjectUnloaded(project)) return Guid.Empty; IVsSolution solution = (IVsSolution)serviceProvider.GetService(typeof(SVsSolution)) as
  • 3. IVsSolution; IVsHierarchy hierarchy; solution.GetProjectOfUniqueName(project.FullName, out hierarchy); if (hierarchy != null) { Guid projectGuid; ErrorHandler.ThrowOnFailure( hierarchy.GetGuidProperty( VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_ProjectIDGuid, out projectGuid)); if (projectGuid != null) { return projectGuid; } } return Guid.Empty; } The IEnumHierarchies interface permits obtaining all of the hierarchies for projects of a particular type through the solution. GetProjectEnum method. Here is an example of obtaining the hierarchies for every Visual C++ project in a solution tree: IVsSolution solution = PVSStudio._IVsSolution; if (null != solution) { IEnumHierarchies penum; Guid nullGuid = Guid.Empty; Guid vsppProjectGuid = new Guid("8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942"); //You can ask the solution to enumerate projects based on the //__VSENUMPROJFLAGS flags passed in. For //example if you want to only enumerate C# projects use //EPF_MATCHTYPE and pass C# project guid. See //CommonIDLvsshell.idl for more details. int hr = solution.GetProjectEnum( (uint)(__VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION | __VSENUMPROJFLAGS.EPF_MATCHTYPE), ref vsppProjectGuid, out penum); ErrorHandler.ThrowOnFailure(hr); if ((VSConstants.S_OK == hr) && (penum != null)) { uint fetched; IVsHierarchy[] rgelt = new IVsHierarchy[1]; PatternsForActiveConfigurations.Clear(); while (penum.Next(1, rgelt, out fetched) == 0 && fetched == 1)
  • 4. { ... } } } As evident by the example above, the GetProjectEnum method provides hierarchies for projects based on a project kind specified by the GUID identifier. GUID identifiers for regular Visual Studio/MSBuild project types can be obtained here. The penum.Next() method allows us to enumerate all project hierarchies we've acquired (the rgelt array). It should be remembered that user-created project models could possess their own unique identifiers in case they define a new project type for themselves. But our own experience in developing PVS-Studio IDE plug-in demonstrates that an opposite situation is quite possible as well, that is, when a user-created project type uses a GUID from one of the stock project types, usually the one from which it was derived. In particular, we've encountered a VCProject type that was extended to provide development for Android platform. As a result, this project model extension had caused crashes in our plug-in because it did not provide several properties which are otherwise present in VCProject model (OpenMP for example) through the automation API. An intricacy of this situation is that such an extended project model type cannot be differentiated from a regular one, and thus, it is quite hard to correctly process it as well. Therefore, when you are extending a project model through your custom types, to avoid such conflicts with various IDE components (including other third-party extensions as well), it is always important to remember the necessity of providing means to uniquely identify your types. Possessing an IVsHierarchy for the project, we are able to recursively enumerate all the elements of such solution tree branch through the hierarchy.GetProperty method, which in turn provides us with the specified properties for each one of the hierarchy nodes: EnumHierarchyItemsFlat(VSConstants.VSITEMID_ROOT, MyProjectHierarchy, 0, true); ... public void EnumHierarchyItemsFlat(uint itemid, IVsHierarchy hierarchy, int recursionLevel, bool visibleNodesOnly) { if (hierarchy == null) return; int hr; object pVar; hr = hierarchy.GetProperty(itemid, (int)__VSHPROPID.VSHPROPID_ExtObject, out pVar); ProjectItem projectItem = pVar as ProjectItem; if (projectItem != null) { ... } recursionLevel++;
  • 5. //Get the first child node of the current hierarchy being walked hr = hierarchy.GetProperty(itemid, (visibleNodesOnly ? (int)__VSHPROPID.VSHPROPID_FirstVisibleChild :(int)__VSHPROPID.VSHPROPID_FirstChild), out pVar); Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(hr); if (VSConstants.S_OK == hr) { //We are using Depth first search so at each level we recurse //to check if the node has any children // and then look for siblings. uint childId = GetItemId(pVar); while (childId != VSConstants.VSITEMID_NIL) { EnumHierarchyItemsFlat(childId, hierarchy, recursionLevel, visibleNodesOnly); hr = hierarchy.GetProperty(childId, (visibleNodesOnly ? (int)__VSHPROPID.VSHPROPID_NextVisibleSibling : (int)__VSHPROPID.VSHPROPID_NextSibling), out pVar); if (VSConstants.S_OK == hr) { childId = GetItemId(pVar); } else { Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(hr); break; } } } } private uint GetItemId(object pvar) { if (pvar == null) return VSConstants.VSITEMID_NIL; if (pvar is int) return (uint)(int)pvar; if (pvar is uint) return (uint)pvar; if (pvar is short) return (uint)(short)pvar; if (pvar is ushort) return (uint)(ushort)pvar; if (pvar is long) return (uint)(long)pvar; return VSConstants.VSITEMID_NIL; } A ProjectItem object that we've acquired for each one of the tree's nodes will allow us to obtain its corresponding Visual C++ object through the 'Object' filed, as was described earlier. Enumerating all projects in solution tree DTE.Solution.Projects interface can be used to enumerate all projects in the solution:
  • 6. if (m_DTE.Solution.Projects != null) { try { foreach (object prj in m_DTE.Solution.Projects) { EnvDTE.Project proj = prj as EnvDTE.Project; if (proj != null) WalkSolutionFolders(proj); } } } Besides projects, Solution tree can also contain folder nodes (Solution Folders). They should also be taken into account while processing each Project element: public void WalkSolutionFolders(Project prj) { VCProject vcprj = prj.Object as VCProject; if (vcprj != null && prj.Kind.Equals(VCCProjectTypeGUID)) { if (!ProjectExcludedFromBuild(prj)) { IVsHierarchy projectHierarchy = ToHierarchy(prj); EnumHierarchyItemsFlat(VSConstants.VSITEMID_ROOT, projectHierarchy, 0, false); } } else if (prj.ProjectItems != null) { foreach (ProjectItem item in prj.ProjectItems) { Project nextlevelprj = item.Object as Project; if (nextlevelprj != null && !ProjectUnloaded(nextlevelprj)) WalkSolutionFolders(nextlevelprj); } } } Projects that are excluded from the build should be inspected separately, as they are not accessible through the automation model after being unloaded from the IDE: public bool ProjectExcludedFromBuild(Project project) { if (project.UniqueName.Equals("<MiscFiles>", StringComparison.InvariantCultureIgnoreCase)) return true; Solution2 solution = m_DTE.Solution as Solution2; SolutionBuild2 solutionBuild = (SolutionBuild2)solution.SolutionBuild;
  • 7. SolutionContexts projectContexts = solutionBuild.ActiveConfiguration.SolutionContexts; //Skip this project if it is excluded from build. bool shouldbuild = projectContexts.Item(project.UniqueName).ShouldBuild; return !shouldbuild; } Enumerating selected elements The DTE.SelectedItems interface can be used to enumerate solution elements which are selected in the Solution Explorer window. foreach (SelectedItem item in items) { VCProject vcproj = null; if (item.Project != null) { vcproj = item.Project.Object as VCProject; if (vcproj != null && item.Project.Kind.Equals("{" + VSProjectTypes.VCpp + "}")) { IVsHierarchy projectHierarchy = ToHierarchy(item.Project); PatternsForActiveConfigurations.Clear(); EnumHierarchyItemsFlat(VSConstants.VSITEMID_ROOT, projectHierarchy, 0, false, files, showProgressDialog); } else if (item.Project.ProjectItems != null) { //solution folder if (!ProjectUnloaded(item.Project)) WalkSolutionFolders(item.Project); } } else if (item.ProjectItem != null) { //walking files ... else if (item.ProjectItem.ProjectItems != null) if (item.ProjectItem.ProjectItems.Count > 0) WalkProjectItemTree(item.ProjectItem); } } private void WalkProjectItemTree(object CurrentItem) { Project CurProject = null; CurProject = CurrentItem as Project; if (CurProject != null) {
  • 8. IVsHierarchy projectHierarchy = ToHierarchy(CurProject); PatternsForActiveConfigurations.Clear(); EnumHierarchyItemsFlat(VSConstants.VSITEMID_ROOT, projectHierarchy, 0, false); return; } ProjectItem item = null; item = CurrentItem as ProjectItem; if (item != null) { ... if (item.ProjectItems != null) if (item.ProjectItems.Count > 0) { foreach (object NextItem in item.ProjectItems) WalkProjectItemTree(NextItem); } } } Configurations and properties of projects and files Visual C++ stores build configurations (compilation and linking parameters, pre-build and post-build steps, external tool command lines etc.) for C/C++ source files inside its XML-based project files (vcproj/vcxproj). These settings are available to Visual Studio users through property page dialogs. Each combination of project's build configuration (Debug, Release, etc.) and a platform (Win32, IA64, x64, etc.) is associated with a separate collection of settings. Although majority of the settings are defined at the project level, it is possible to redefine separate properties for each individual file (file properties are inherited from its project by default). The list of properties which can be redefined at the file level is dependent upon the type of a file in question. For example, only the ExcludedFromBuild property can be redefined for header files, but cpp source files permit the redefinition for any of its compilation properties. Obtaining configurations Visual C++ project model presents property pages through the VCConfiguration (for a project) and VCFileConfiguration (for a file) interfaces. To obtain these objects we will start from a ProjectItem object which represents an abstract Solution tree element. ProjectItem item; VCFile vcfile = item.Object as VCFile; Project project = item.ContainingProject; String pattern = "Release|x64"; if (String.IsNullOrEmpty(pattern)) return null; VCFileConfiguration fileconfig = null; IVCCollection fileCfgs = (IVCCollection)vcfile.FileConfigurations; fileconfig = fileCfgs.Item(pattern) as VCFileConfiguration;
  • 9. if (fileconfig == null) if (fileCfgs.Count == 1) fileconfig = (VCFileConfiguration)fileCfgs.Item(0); In the example above we've acquired a file configuration for VCFile object (which represents a C/C++ header or a source file) by passing a configuration pattern (configuration's name and platform) to the Item() method. Build configuration pattern is defined on the project level. The following example demonstrates the acquisition of active configuration (the one that is selected in IDE) of a project. ConfigurationManager cm = project.ConfigurationManager; Configuration conf = cm.ActiveConfiguration; String platformName = conf.PlatformName; String configName = conf.ConfigurationName; String pattern = configName + "|" + platformName; return pattern; The ActiveConfiguration interface should be handled with care. Quite often we've encountered exceptions when calling it from our PVS-Studio IDE extension package. In particular, this field sometimes becomes inaccessible through the automation object model when a user is building a project, or in the presence of any other heavy user interaction with Visual Studio UI. As there is no assured way of predicting such user actions, it is advised to provide additional error handlers for such 'bottlenecks' when accessing settings with automation model. It should be noted that this particular situation is not related to COM exception handling that was described in the previous article dedicated to EnvDTE interfaces, and it is probably related to some internal issues within the automation model itself. Next, let's acquire the configuration for a project that contains the file in question: VCConfiguration cfg=(VCConfiguration)fileconfig.ProjectConfiguration; While the interfaces representing configurations themselves contain settings only from the 'General' tab of the property pages, references for individual build tools can be acquired through the VCConfiguration.Tools and VCFileConfiguration.Tool interfaces (note that a single file contains settings respectively for only one build tool). Let's examine the VCCLCompilerTool interface representing the C++ compiler: ct = ((IVCCollection)cfg.Tools).Item("VCCLCompilerTool") as VCCLCompilerTool; ctf = fileconfig.Tool as VCCLCompilerTool; Now let's acquire the contents of, for example, the AdditionalOptions field belonging to the compiler tool, using the 'Evaluate' method to process any macros that we can encounter within its value: String ct_add = fileconfig.Evaluate(ct.AdditionalOptions); String ctf_add = fileconfig.Evaluate(ctf.AdditionalOptions); Property Sheets Property sheets are XML files with a props extension. They allow an independent definition of project's build properties, i.e. the command line parameters for various building tools, such as a compiler or a linker. Property sheets also support inheritance and can be used for specifying build configurations for
  • 10. several projects at once, i.e. the configuration defined inside the project file itself (vcproj/vcxproj) could inherit some of its properties from single or multiple props files. To handle property sheets, Visual C++ project model provides the VCPropertySheet interface. A collection of VCPropertySheet objects can be obtained through the VCConfiguration. PropertySheets field: IVCCollection PSheets_all = fileconfig.PropertySheets; Similarly, the PropertySheets filed of the VCPropertySheet interface provides a reference to a collection of child property sheet files for this object. Let's examine the recursive enumeration of all of the project's property sheets: private void ProcessAllPropertySheets(VCConfiguration cfg, IVCCollection PSheets) { foreach (VCPropertySheet propertySheet in PSheets) { VCCLCompilerTool ctPS = (VCCLCompilerTool)((IVCCollection)propertySheet.Tools).Item( "VCCLCompilerTool"); if (ctPS != null) { ... IVCCollection InherPSS = propertySheet.PropertySheets; if (InherPSS != null) if (InherPSS.Count != 0) ProcessAllPropertySheets(cfg, InherPSS); } } } In the example above we've obtained an object of VCCLCompilerTool type (that is compilation settings) for PropertySheet on every level. In this way we could gather all compilation parameters defined in every property sheet, including the embedded ones. The VCPropertySheet interface does not contain means to evaluate macros within its fields, so as a work-around, the Evaluate method from the project's configuration can be used instead. But, such approach could also lead to the incorrect behavior in case the value of the macro being evaluated is related to the props file itself. For instance, several MSBuild macros which were introduced in the MSBuild version 4 could also be utilized inside vcxproj projects from Visual Studio 2010. Let's take the MSBuildThisFileDirectory macro that evaluates as a path to the directory containing file in which it is used. Now, evaluating this macro through the cfg.Evaluate will result in a path to the vcxproj file, and not to props file, which actually does contains this macro. All of the property sheets in Visual C++ project can be divided between user and system files. By user files we understand the props files which were created and added to the project by a user himself. But even an empty template-generated MSVC project often includes several property sheets by default. These system props files are utilized by the environment to specify various compilation parameters
  • 11. which were set inside the project's property page interface by the user. For example, setting up the CharacterSet property to use Unicode manually in the Property Page interface will result in the appearance of a special property sheet in the 'Property Sheets' window which will define several preprocessor symbols (Unicode, _Unicode), and this properties subsequently will be inherited by the project. Therefore when processing properties from inside a Property sheet, one should always remember that compilation symbols defined in system props files are also returned by their corresponding property in the project's configuration through the automation API. Evidently, processing these two simultaneously while gathering compilation arguments can result in a duplication of such arguments. References 1. MSDN. Visual C++ Project Model. 2. MSDN. Project Modeling. 3. MSDN. Automation Model Overview. Other articles in this series 0. Introduction. 1. Creating, debugging and deploying extension packages for Microsoft Visual Studio 2005/2008/2010/2012. 2. Visual Studio Automation Object Model. EnvDTE interfaces. 3. Visual Studio commands. 4. Visual Studio tool windows. 5. Integrating into Visual Studio settings. 6. Visual C++ project model.