如何在Visual Studio 2015项目文件中动态创建/修改/删除扩展属性,以便XML保持以下构造:
<ProjectExtensions>
<VisualStudio>
<MyProject>
<MyProjectProperty1>3</MyProjectProperty>
<MyProjectProperty2>8</MyProjectProperty>
<MyProjectProperty3>2016</MyProjectProperty>
</MyProject>
</VisualStudio>
</ProjectExtensions>
我已经知道如何使用 EnvDTE.Globals 创建它的变体,然后保留该值并选择性地使用类似于以下内容的代码保存项目:
EnvDTE.Project oProject = dte.Solution.Projects.Item(1);
Globals oGlobals = oProject.Globals;
oGlobals["MyProjectProperty1"] = "3";
这里的问题是此代码产生:
<ProjectExtensions>
<VisualStudio>
<UserProperties MyProjectProperties1="3" MyProjectProperties2="8" MyProjectProperties3="2016" />
</VisualStudio>
</ProjectExtensions>
我想过使用IPersistXMLFragment
和IVsProjectFlavorCfg
组合,但这种方法缺少从项目文件中读取、写入和删除 XML 代码的关键概念。IPersistXMLFragment
load 方法将 XML 代码作为字符串,将值加载到字典中,然后管理这些值。save 方法执行相反的操作,从管理构造返回到基于字符串的 XML 版本。正如我刚才所说,缺少的是读取、写入和删除实际项目文件,而无需手动编辑文件并导致项目重新加载。
我也在使用 IVsHierarchy
和 MSBuild
VSIX 接口/对象,但没有走得很远。
有人有什么想法吗?
IVsBuildPropertyStorage。作为输入,我使用 EnvDTE.Project object.
如果 csproj 文件不存在,SetCsprojProperty
将在 csproj 文件的第一<PropertyGroup>
中设置该属性:
private IVsHierarchy GetIVsHierarchyObject(Project project)
{
string uniqueName = project?.UniqueName;
int ret = Solution.GetProjectOfUniqueName(uniqueName, out IVsHierarchy hierarchyProject);
if (ret != VSConstants.S_OK) return null;
return hierarchyProject;
}
public string GetCsprojProperty(Project project, string name)
{
IVsHierarchy hierarchyProject = GetIVsHierarchyObject(project);
if (hierarchyProject is IVsBuildPropertyStorage buildPropertyStorage)
{
var result = buildPropertyStorage.GetPropertyValue(name, "", (uint)_PersistStorageType.PST_PROJECT_FILE, out string value);
if (result == VSConstants.S_OK)
{
return value;
}
}
return null;
}
public bool SetCsprojProperty(Project project, string name, string value)
{
IVsHierarchy hierarchyProject = GetIVsHierarchyObject(project);
if (hierarchyProject is IVsBuildPropertyStorage buildPropertyStorage)
{
var result = buildPropertyStorage.SetPropertyValue(name, "", (uint)_PersistStorageType.PST_PROJECT_FILE, value);
if (result == VSConstants.S_OK)
{
return true;
}
}
return false;
}