在我的 VSIX(VS 扩展)中,我正在读取当前加载的解决方案中每个项目的配置属性'.Value。对于 C# (csproj) 项目:
var configurationManager = project.ConfigurationManager;
if (configurationManager == null) return null;
var configuration = configurationManager.ActiveConfiguration;
if (configuration == null) return null;
var properties = configuration.Properties;
if (properties == null) return null;
foreach (var property in properties.Cast<Property>())
{
// reading property.Name is OK but reading property.Value gives the COMException 'not implemented'
if (property == null) continue;
if (property.Name == "StartWorkingDirectory") workingDir = (string)property.Value;
if (property.Name == "StartAction") startProject = 0 == (int)property.Value;
if (property.Name == "StartProgram") startExtProg = (string)property.Value;
if (property.Name == "StartURL") startBrowser = (string)property.Value;
// etc...
}
对于每个属性,当我尝试读取 .Value 属性时,我都会收到 COMException: '方法或操作未实现',尽管 .Name 没问题。所有搜索到的属性似乎都存在,只是无法读取它们的 .Value。
这是一个使用 VS2022 模板创建的全新 VSIX 项目,其中包含 Microsoft.VisualStudio.SDK 和参考文献中的 Microsoft.VisualStudio.BuildTools。
这似乎包括每个 DTE* 引用、stdole 和其他 VS COM dll,如 VSLangProj* (如果我尝试将这些添加为项目引用,它表示它们已经包含在构建过程中)。因此,我尝试通过 nuget 包添加所有这些引用,但我看不到任何效果,并且错误仍然存在。
所以我找不到任何关于如何在我的 C# 项目 (csproj) 上读取这些属性的信息。它们是简单的 C# 8 控制台应用程序,我刚刚创建的空的。
以下是我的 VSIX 项目的所有参考资料,包括由 nuget 拉入但可能不需要的参考资料:
envdte
envdte80
envdte90
Microsoft.CSharp
Microsoft.VisualStudio.CommandBars
Microsoft.VisualStudio.SDK
Microsoft.VSSDK.BuildTools
NJsonSchema
PresentationCore
PresentationFramework
stdole
System
VSLangProj
VSLangProj100
VSLangProj110
VSLangProj140
VSLangProj150
VSLangProj80
VSLangProj90
WindowsBase
WindowsFormsIntegration
我使用的是 VS2022,截至 2024 年 3 月已完全更新。
有什么想法吗?
编辑:来源:https://github.com/cbordeman/switchstartupproject/pull/4
您提供的错误日志表明问题集中在使用 Visual Studio 扩展的不同方面。
这与您在 VSIX 项目中尝试读取项目配置属性时遇到的
COMException
是不同的问题:它指出加载 Visual Studio 包(即 SwitchStartupProjectPackage
)时失败,因为缺少程序集引用 ( Microsoft.VisualStudio.Shell.15.0, Version=17.0.0.0
)适用于 VS2022。kemmis/switchstartupproject
) 似乎更旧。
错误:
CreateInstance failed for package [SwitchStartupProjectPackage]... Could not load file or assembly 'Microsoft.VisualStudio.Shell.15.0, Version=17.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
它表明您的 VSIX 扩展正在尝试加载未找到的
Microsoft.VisualStudio.Shell.15.0
程序集的版本。
您的 VSIX 项目可能面向的 Visual Studio 版本与您尝试加载的
Microsoft.VisualStudio.Shell.15.0
程序集不匹配。17.0.0.0
) 可能不会随 Visual Studio 安装一起安装。如果扩展适用于不同版本的 Visual Studio,或者扩展的配置中存在错误,指定了错误的版本号,则可能会发生这种情况。Microsoft.VisualStudio.Shell.15.0
应更新为与 Visual Studio 17.x.x.x(Visual Studio 2022 的内部版本号)兼容的版本。
您的分叉中的更改集中在两个主要领域:项目文件的更新(
SwitchStartupProject.csproj
)和SwitchStartupProjectPackage.cs
中的小更新。他们确实使项目与与 Visual Studio 2022 兼容的库和 API 保持一致 (VS 17.x
),这应该有助于解决任何兼容性问题。
但是:
.vsixmanifest
文件,确保 Prerequisites
部分正确指定扩展所针对的 Visual Studio 版本。Microsoft.VisualStudio.Shell.15.0, Version=17.0.0.0
而导致的特定故障。拉取请求似乎并没有直接解决此问题,除非对 Microsoft.VisualStudio.SDK
和 Microsoft.VSSDK.BuildTools
的更新通过确保正确引用 Visual Studio 2022 的所有必要依赖项来间接解决此问题。Microsoft.VisualStudio.Shell
版本是否与 Visual Studio 2022 兼容,并且对旧版本的任何特定引用是否已更新或删除。从 VSIX 扩展访问 CSPROJ 的配置属性有时会导致您遇到的
COMException
。这通常是由于这些属性通过DTE(开发工具环境)和 COM 接口公开的方式造成的。
您可以使用 try-catch 块实现更安全的属性访问策略:
foreach (var property in properties.Cast<Property>())
{
try
{
// Attempt to read property value
if (property.Name == "StartWorkingDirectory") workingDir = (string)property.Value;
if (property.Name == "StartAction") startProject = 0 == (int)property.Value;
if (property.Name == "StartProgram") startExtProg = (string)property.Value;
if (property.Name == "StartURL") startBrowser = (string)property.Value;
// etc
}
catch (COMException ex)
{
// Handle or log the exception as needed
Debug.WriteLine($"Failed to read {property.Name}: {ex.Message}");
}
}
如果由于未实现的属性而抛出
COMException
,它会捕获异常并允许循环继续:它可以防止单个不可访问的属性停止整个进程。
但是,作为一种替代方法,您可以直接将 CSPROJ 文件作为 XML 文档读取,而不是使用 ConfigurationManager 和 COM 接口来访问项目属性。这将绕过通过 COM 与属性交互的需要,避免“未实现”异常。
using System.Xml.Linq;
// Assuming 'project' is a DTE Project object
string projectFilePath = project.FullName;
// Load the CSPROJ file as an XML document
XDocument projectFile = XDocument.Load(projectFilePath);
// Namespace for MSBuild project files
XNamespace msbuild = "http://schemas.microsoft.com/developer/msbuild/2003";
// Example of reading a property directly from the project file
var startAction = projectFile.Element(msbuild + "Project")
.Elements(msbuild + "PropertyGroup")
.Elements(msbuild + "StartAction")
.FirstOrDefault()?.Value;
// Repeat for other properties as needed
+-----------------+ +-----------------------+ +----------------------+
| VSIX Extension | --FS->| Read CSPROJ as XML | --Parse->| Extract Property Data|
+-----------------+ +-----------------------+ +----------------------+
您的情况:
using System.Xml.Linq;
using EnvDTE;
// Make sure to include these namespaces based on your project's context
public static class ProjectConfigurationReader
{
public static void ReadProjectProperties(Project project)
{
if (project == null) return;
string projectFilePath = project.FullName;
XDocument projectFile = XDocument.Load(projectFilePath);
XNamespace msbuild = "http://schemas.microsoft.com/developer/msbuild/2003";
// Assuming you know the property names you are interested in
var startWorkingDirectory = projectFile.Element(msbuild + "Project")
.Elements(msbuild + "PropertyGroup")
.Elements(msbuild + "StartWorkingDirectory")
.FirstOrDefault()?.Value;
var startAction = projectFile.Element(msbuild + "Project")
.Elements(msbuild + "PropertyGroup")
.Elements(msbuild + "StartAction")
.FirstOrDefault()?.Value;
var startProgram = projectFile.Element(msbuild + "Project")
.Elements(msbuild + "PropertyGroup")
.Elements(msbuild + "StartProgram")
.FirstOrDefault()?.Value;
var startURL = projectFile.Element(msbuild + "Project")
.Elements(msbuild + "PropertyGroup")
.Elements(msbuild + "StartURL")
.FirstOrDefault()?.Value;
// Process extracted properties as needed
}
}