{"id":2673,"date":"2010-01-14T21:00:00","date_gmt":"2010-01-14T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/visualstudio\/2010\/01\/14\/how-to-readwrite-the-new-visual-c-project-properties\/"},"modified":"2022-10-17T15:01:52","modified_gmt":"2022-10-17T22:01:52","slug":"how-to-readwrite-the-new-visual-c-project-properties","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/visualstudio\/how-to-readwrite-the-new-visual-c-project-properties\/","title":{"rendered":"How to read\/write the new Visual C++ project properties"},"content":{"rendered":"<p>Visual C++ 2010 introduces several new project and tool properties, and deprecates some old ones.\u00a0 If you\u2019re writing a project template or Visual Studio extension that needs to programmatically read and write the new properties, you will find that these properties are not available on the standard VCConfiguration, VCCLCompilerTool, etc. set of interfaces.\u00a0 These are COM interfaces and cannot be changed.\u00a0 Rather than create new interfaces for the new properties, we\u2019ve introduced a single new interface that will provide access to all project and tool properties: IVCRulePropertyStorage.<\/p>\n<p>Before we dive into IVCRulePropertyStorage, you should take a few minutes to learn about Visual C++ &#8220;Rule\u201d XAML files, as Pavan describes in his post: <a href=\"https:\/\/learn.microsoft.com\/en-us\/archive\/blogs\/vsproject\/platform-extensibility-part-1\">Platform Extensibility \u2013 Part 1<\/a>.<\/p>\n<p>One new property in Visual C++ 2010 is TargetExt, which specifies the filename extension of the primary output of a Visual C++ project.\u00a0 This property isn\u2019t available on VCConfiguration.\u00a0 Let\u2019s read and write it using IVCRulePropertyStorage assuming you\u2019ve got a DTE object for the project.\u00a0 While we\u2019re in there, we\u2019ll read and write a few other properties at the project and file level.\u00a0 I\u2019ve written this code as it might be seen in the IDE Macro Editor.\u00a0 You can try copying and pasting this code into the Macro Editor yourself and running it while you have a new C++ console application open in the IDE.<\/p>\n<p><!-- code formatted by http:\/\/manoli.net\/csharpformat\/ -->\n.csharpcode, .csharpcode pre\n{\nfont-size: small;\ncolor: black;\nfont-family: consolas, &#8220;Courier New&#8221;, courier, monospace;\nbackground-color: #ffffff;\n\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt\n{\nbackground-color: #f4f4f4;\nwidth: 100%;\nmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }<\/p>\n<pre class=\"csharpcode\">    <span class=\"kwrd\">Public<\/span> <span class=\"kwrd\">Sub<\/span> RulePropertyAccess()\r\n        <span class=\"kwrd\">Dim<\/span> vsPrj <span class=\"kwrd\">As<\/span> VSProject = <span class=\"kwrd\">CType<\/span>(DTE.Solution.Projects.Item(1).<span class=\"kwrd\">Object<\/span>, VSProject)\r\n        <span class=\"kwrd\">Dim<\/span> vcproj <span class=\"kwrd\">As<\/span> VCProject = vsPrj.Project.<span class=\"kwrd\">Object<\/span>\r\n        <span class=\"kwrd\">Dim<\/span> vcconfigs <span class=\"kwrd\">As<\/span> IVCCollection = vcproj.Configurations\r\n        <span class=\"kwrd\">Dim<\/span> vcfiles <span class=\"kwrd\">As<\/span> IVCCollection = vcproj.Files\r\n        <span class=\"kwrd\">For<\/span> <span class=\"kwrd\">Each<\/span> vcconfig <span class=\"kwrd\">As<\/span> VCConfiguration <span class=\"kwrd\">In<\/span> vcconfigs\r\n            <span class=\"rem\">' Start by accessing a configuration-level property: TargetExt<\/span>\r\n            <span class=\"rem\">' The \"ConfigurationGeneral\" string comes from the <\/span>\r\n            <span class=\"rem\">' %PROGRAMFILES%\\msbuild\\Microsoft.Cpp\\v4.0\\1033\\general.xml<\/span>\r\n            <span class=\"rem\">' file's &lt;Rule Name=\"ConfigurationGeneral\"&gt; tag.<\/span>\r\n            <span class=\"kwrd\">Dim<\/span> generalRule <span class=\"kwrd\">As<\/span> IVCRulePropertyStorage = vcconfig.Rules.Item(<span class=\"str\">\"ConfigurationGeneral\"<\/span>)\r\n            <span class=\"kwrd\">Dim<\/span> oldExtension <span class=\"kwrd\">As<\/span> <span class=\"kwrd\">String<\/span> = generalRule.GetEvaluatedPropertyValue(<span class=\"str\">\"TargetExt\"<\/span>)\r\n            generalRule.SetPropertyValue(<span class=\"str\">\"TargetExt\"<\/span>, <span class=\"str\">\".dll\"<\/span>)\r\n            Debug.Print(<span class=\"str\">\"TargetExt before: {0} and after {1}\"<\/span>, oldExtension, generalRule.GetEvaluatedPropertyValue(<span class=\"str\">\"TargetExt\"<\/span>))\r\n            <span class=\"rem\">' Now let's access a tool-specific property at the project level: WarnAsError<\/span>\r\n            <span class=\"rem\">' This property isn't new, so it's available both through VCLinkerTool and IVCRulePropertyStorage<\/span>\r\n            <span class=\"rem\">' Note however that its MSBuild property name does not match its name on the interface.<\/span>\r\n            <span class=\"kwrd\">Dim<\/span> vctools <span class=\"kwrd\">As<\/span> IVCCollection = vcconfig.Tools\r\n            <span class=\"kwrd\">Dim<\/span> cl <span class=\"kwrd\">As<\/span> VCCLCompilerTool = vctools.Item(<span class=\"str\">\"VCCLCompilerTool\"<\/span>)\r\n            Debug.Print(<span class=\"str\">\"VCCLCompilerTool::WarnAsError reports {0}\"<\/span>, cl.WarnAsError)\r\n            <span class=\"kwrd\">Dim<\/span> clRule <span class=\"kwrd\">As<\/span> IVCRulePropertyStorage = cl <span class=\"rem\">' we only need to QI for this interface on the same object<\/span>\r\n            clRule.SetPropertyValue(<span class=\"str\">\"TreatWarningAsError\"<\/span>, <span class=\"kwrd\">Not<\/span> cl.WarnAsError) <span class=\"rem\">' invert the value<\/span>\r\n            Debug.Print(<span class=\"str\">\"VCCLCompilerTool::WarnAsError now reports {0}\"<\/span>, cl.WarnAsError)\r\n            <span class=\"rem\">' Now let's set a property for a very specific .cpp file.<\/span>\r\n            <span class=\"kwrd\">Dim<\/span> stdafxFile <span class=\"kwrd\">As<\/span> VCFile = vcfiles.Item(<span class=\"str\">\"stdafx.cpp\"<\/span>)\r\n            <span class=\"kwrd\">Dim<\/span> stdafxFileConfigs <span class=\"kwrd\">As<\/span> IVCCollection = stdafxFile.FileConfigurations\r\n            <span class=\"kwrd\">Dim<\/span> stdafxFileConfig <span class=\"kwrd\">As<\/span> VCFileConfiguration = stdafxFileConfigs.Item(vcconfig.Name)\r\n            <span class=\"kwrd\">Dim<\/span> fileCL <span class=\"kwrd\">As<\/span> VCCLCompilerTool = stdafxFileConfig.Tool\r\n            Debug.Print(<span class=\"str\">\"StdAfx.cpp VCCLCompilerTool::InlineFunctionExpansion reports {0}\"<\/span>, fileCL.InlineFunctionExpansion)\r\n            <span class=\"kwrd\">Dim<\/span> fileCLRule <span class=\"kwrd\">As<\/span> IVCRulePropertyStorage = fileCL\r\n            fileCLRule.SetPropertyValue(<span class=\"str\">\"InlineFunctionExpansion\"<\/span>, <span class=\"str\">\"OnlyExplicitInline\"<\/span>)\r\n            Debug.Print(<span class=\"str\">\"StdAfx.cpp VCCLCompilerTool::InlineFunctionExpansion reports {0}\"<\/span>, fileCL.InlineFunctionExpansion)\r\n        <span class=\"kwrd\">Next<\/span>\r\n    <span class=\"kwrd\">End<\/span> <span class=\"kwrd\">Sub<\/span><\/pre>\n<p>So you see that IVCRulePropertyStorage provides very simple property read\/write access.\u00a0 And exactly where those properties are read from or written to depends on where you acquired the IVCRulePropertyStorage object.\u00a0 As shown above, you can get this object from the VCConfiguration, a VC*Tool at the VCConfiguration level, or a VC*Tool at the VCFileConfiguration level.\u00a0 Not shown above is that you can also get this object from the VCPropertySheet::get_Rules collection, similarly to how we show above using VCConfiguration::get_Rules.\u00a0 As you might expect, IVCRulePropertyStorage objects obtained from VCPropertySheet objects will read and write to that property sheet instead of the project.<\/p>\n<p>The IVCRulePropertyStorage interface can only be used to read and write properties for which a Rule XAML file exists that is imported into the project.\u00a0 If your software requires custom properties that do not exist in a Rule file, you need to create a Rule file that describes those properties and then import that file into your project, as described in Pavan\u2019s <a href=\"http:\/\/blogs.msdn.com\/vsproject\/archive\/2009\/06\/10\/platform-extensibility-part-1.aspx\">Platform Extensibility \u2013 Part 1<\/a> and <a href=\"https:\/\/learn.microsoft.com\/en-us\/archive\/blogs\/vsproject\/platform-extensibility-part-2\">Part 2<\/a>.\u00a0 Why do we require these steps?\u00a0 Because it turns out that project properties have <em>many<\/em> attributes, such as where they should be persisted in the file, in which file (project or .user file), whether they are project properties or metadata on items or item definitions, etc. etc.\u00a0 The Rule file allows you to capture all that per-property detail so that your code that invokes IVCRulePropertyStorage can be free of these implementation-specific details.<\/p>\n<p>Every single property available in the Visual C++ Property Pages dialog has a Rule file associated with it already, guaranteeing you convenient programmatic access to read or write any property you find there.<\/p>\n<h5><\/h5>\n<h4>A note on debugger properties<\/h4>\n<p>There are a couple of interesting points to note with regard to properties that configure the debugger.<\/p>\n<p>Debugger properties are stored in the project user file (*.vcxproj.user) rather than the project itself.\u00a0 This doesn\u2019t require any special coding on your part\u2014you just acquire the IVCRulePropertyStorage object from VCConfiguration the same as you would for other properties.\u00a0 The Rule.DataSource tag in the debugger_*.xml rule files tell the IVCRulePropertyStorage to persist to the .user file instead of the project file so that you don\u2019t have to worry about that detail.<\/p>\n<p>In Visual C++ 2008 and earlier, debugger properties were accessed using VCDebugSettings.\u00a0 This interface had only a small set of properties, many of which were overloaded to control several different debuggers (local, remote, web browser, etc.) so these properties could not be set for a particular debugger without risk of impacting other debuggers.\u00a0 In Visual C++ 2010 we\u2019ve isolated each debugger\u2019s properties so they are independent of one another.\u00a0 The VCDebugSettings interface is still present in Visual C++ 2010, but deprecated since it did not have the isolated set of properties per-debugger.\u00a0 For this reason, we highly recommend you use IVCRulePropertyStorage for getting and setting debugger properties for your Visual C++ 2010 IDE extensions.\u00a0 As with any other properties, you can discover the set of available properties for each debugger and their names and possible values by inspecting these files: %ProgramFiles%\\msbuild\\Microsoft.Cpp\\v4.0\\1033\\debugger_*.xml<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Visual C++ 2010 introduces several new project and tool properties, and deprecates some old ones.\u00a0 If you\u2019re writing a project template or Visual Studio extension that needs to programmatically read and write the new properties, you will find that these properties are not available on the standard VCConfiguration, VCCLCompilerTool, etc. set of interfaces.\u00a0 These are [&hellip;]<\/p>\n","protected":false},"author":2685,"featured_media":255385,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[155],"tags":[5,137,13,133],"class_list":["post-2673","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-visual-studio","tag-csharp","tag-html","tag-visual-studio-2010","tag-xaml"],"acf":[],"blog_post_summary":"<p>Visual C++ 2010 introduces several new project and tool properties, and deprecates some old ones.\u00a0 If you\u2019re writing a project template or Visual Studio extension that needs to programmatically read and write the new properties, you will find that these properties are not available on the standard VCConfiguration, VCCLCompilerTool, etc. set of interfaces.\u00a0 These are [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts\/2673","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/users\/2685"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/comments?post=2673"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts\/2673\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/media\/255385"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/media?parent=2673"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/categories?post=2673"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/tags?post=2673"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}