Introduction
This post is to explain how to read read Visual Studio 2012 SSDT project properties programmatically using a DTE project.Problem Domain - Visual Studio 2010
In Visual Studio 2010, the SSDT projects are loaded using the Microsoft.VisualStudio.Data.Schema.Package.Project namespace. this namespace contains a public API where you can read and write properties of the loaded SSDT project. the Visual Studio SSDT projects featuring the .dbproj project types which integrated with the Microsoft.VisualStudio.Data.Schema.* namespace. You need to cast the project in to a IDatabaseProjectNode type and read the configurations using the IDatabaseProjectConfiguration interface type.The IDatabaseProjectConfiguration interface exposes public methods such as GetConfigurationProperty and SetConfigurationProperty where you can read and write SSDT configuration properties programmatically.
The Problem - Visual Studio 2012
When it comes to the Visual Studio 2012 SSDT projects, the project type is converted into the .sqlproj types. The project is featured using the Microsoft.VisualStudio.Data.Tools.Package.Project instead of Microsoft.VisualStudio.Data.Schema.Package.Project. Unfortunately, the Microsoft.VisualStudio.Data.Tools.Package.Project name space removed public APIs where we can read and write SSDT properties. I do not know Microsoft's rationale behind this. Hence there is no straight forward way to read and write properties in VS2012 SSDT projects.The Solution
First thing I did was decompile the Microsoft.VisualStudio.Data.Schema.Package.Project dll. The same GetConfigurationProperty and SetConfigurationProperty methods are still existing but not as public methods.This is why we cannot access these methods directly.
So the solution is use reflection to access these non public properties and methods.
Following is the sample code you can use to achieve this objective.
Dim dte As EnvDTE.DTE Dim configuration As EnvDTE.Configuration Dim projectConfigProperties As Microsoft.VisualStudio.Data.Tools.Package.Project.Internal.ProjectConfigProperties Dim databaseProjectConfig As Microsoft.VisualStudio.Data.Tools.Package.Project.DatabaseProjectConfig configuration = project.ConfigurationManager.ActiveConfiguration
Now we need to load the Microsoft.VisualStudio.Data.Tools.Package.Project assembly and load its types.
Dim name As AssemblyName = New AssemblyName() name.CodeBase = "file://C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\Microsoft\SQLDB\Microsoft.VisualStudio.Data.Tools.Package.dll" Dim assembly As Assembly = AppDomain.CurrentDomain.Load(name)
There are enums that we need to pass in to the GetConfigurationProperty and SetConfigurationProperty methods. But these enums are also not public. Hence we need to acquire them using reflection as well as follows.
Dim fields As FieldInfo() = dbProjectType.GetFields((BindingFlags.Public Or BindingFlags.Static Or BindingFlags.NonPublic)) '' Get Internal enum DatabaseProjectEventPropagation using reflection Dim dbeventPropagationType As Type = assembly.GetType("Microsoft.VisualStudio.Data.Tools.Package.Project.DatabaseProjectEventPropagation", True, True) Dim dbEventPropgationFields As FieldInfo() = dbeventPropagationType.GetFields((BindingFlags.Public Or BindingFlags.Static Or BindingFlags.NonPublic)) Dim readTypes As Type() = New Type() {GetType(String), GetType(Boolean), dbProjectType} Dim writeTypes As Type() = New Type() {GetType(String), GetType(String), dbeventPropagationType, GetType(Microsoft.VisualStudio.Shell.Interop._PersistStorageType)}
projectConfigProperties = CType(configuration.Object, Microsoft.VisualStudio.Data.Tools.Package.Project.Internal.ProjectConfigProperties) projectConfigObject = projectConfigProperties.GetType().GetProperty("ProjectConfig", System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance).GetValue(projectConfigProperties) databaseProjectConfig = CType(projectConfigObject, Microsoft.VisualStudio.Data.Tools.Package.Project.DatabaseProjectConfig) Dim getPropertyMethod As MethodInfo = databaseProjectConfig.GetType().GetMethod("GetConfigurationProperty", BindingFlags.NonPublic Or BindingFlags.Instance, Nothing, readTypes, Nothing) Dim setPropertyMethod As MethodInfo = databaseProjectConfig.GetType().GetMethod("SetConfigurationProperty", BindingFlags.NonPublic Or BindingFlags.Instance, Nothing, writeTypes, Nothing)
Please note that if we do not pass in exact types which are compatible to method signatures, the MethodInfo objects returns as Null.
Next thing is we need to Invoke the reflected method and access properties.
Dim val = getPropertyMethod.Invoke(projectConfigObject, New Object() {"AnsiNulls", False, fields(0).GetValue(Nothing)}) setPropertyMethod.Invoke(projectConfigObject, New Object() {"AnsiNulls", "False", dbEventPropgationFields(0).GetValue(Nothing), Microsoft.VisualStudio.Shell.Interop._PersistStorageType.PST_PROJECT_FILE})
No comments:
Post a Comment