Visual Studio 2022 中的中断性 API 更改

如果要将扩展迁移到 Visual Studio 2022,此处列出的中断性变更可能会影响你。

不再安装引用程序集

你可能引用的许多程序集都不再安装从 Visual Studio 安装目录解析的 MSBuild。 应使用 NuGet 获取所需的 Visual Studio SDK ref 程序集。 有关执行此操作的详细步骤,请参阅 现代化项目

已删除的 API

在 Visual Studio 2022 中,在继续移动 Visual Studio 时,已删除许多 API。 可以在“已删除的 API 列表”页上找到 已删除的 API 列表

互操作中断性变更

我们的许多 API 在 Visual Studio 2022 中已更改,通常只需对代码进行简单的更改即可适应。

为了管理中断性变更,我们计划提供一种用于分发互操作程序集的新机制。 具体而言,对于 Visual Studio 2022 及更高版本,我们提供了一个单一互操作程序集,其中包含许多常见公共 Visual Studio 接口的定义。 该程序集包含许多 Visual Studio 接口的托管定义,这些接口远离多个互操作程序集。 新的互操作程序集通过 Microsoft.VisualStudio.Interop NuGet 包分发。

但是,主要用于本机上下文且具有少量中断性变更的 Visual Studio 组件将继续有自己的互操作程序集(例如,调试器程序集仍将是 VisualStudio.Debugger.Interop.dll,就像今天那样)。 在任何情况下,都可以从应用程序引用程序集,就像现在一样。

这是一项重大更改,这意味着使用此新方法中内置的 API 和程序集的扩展与使用以前的互操作程序集的旧版 Visual Studio 不兼容。

这具有一些非常重要的优势,可更轻松地将扩展更新到 Visual Studio 2022:

  • 任何损坏的 API 都将成为生成时错误,使它们更易于查找和修复。
  • 只需更新使用 Visual Studio 2022 中中断的 API 的代码。
  • 你将无法意外使用旧的,现在损坏的 API。

总的来说,这些更改将导致所有用户的 Visual Studio 版本更加稳定。 此方法的主要缺点是,托管程序集无法在 Visual Studio 2019 和 Visual Studio 2022 中运行,而无需为每个目标 Visual Studio 版本编译代码一次。

由于 Visual Studio 2019 和 Visual Studio 2022 之间的 API 差异,可以发现下面列出的 API 或模式包含有关如何修复它的指南。

intuint预期位置IntPtr

我们预计这是一个非常常见的错误。 若要使 Visual Studio 2022 成为 64 位进程,必须修复一些互操作 API,假设指针可以容纳在 32 位整数中,从而实际使用指针大小的值。

示例错误:

参数 3:无法从“out uint”转换为“out System.IntPtr”

只需将代码更新为预期或提供IntPtrUIntPtr或用于解决中断的位置或uint用于解决中断的位置int

示例修复:

-shell.LoadLibrary(myGuid, myFlags, out uint ptrLib);
+shell.LoadLibrary(myGuid, myFlags, out IntPtr ptrLib);

在两个程序集中定义的互操作类型

当 C# 编译器报告在使用的类型在两个程序集中定义的错误时,可能引用了不应再引用的 SDK 的 Visual Studio 2019 版本的程序集。

示例错误:

错误 CS0433:“Microsoft.VisualStudio.Interop”中都存在类型“IVsDpiAware” Version=17.0.0.0、Culture=neutral、PublicKeyToken=b03f5f7f11d50a3a“ 和 ”Microsoft.VisualStudio.Shell.Interop.16.0.DesignTime, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'

请参阅引用 程序集重新映射表 ,查看 Visual Studio 2022 中哪个程序集名称是首选名称。 考虑到上面示例错误中命名的两个程序集并查看此表,请注意 Microsoft.VisualStudio.Interop ,这是新的程序集名称。 然后修复是删除对项目的引用 Microsoft.VisualStudio.Shell.Interop.16.0.DesignTime

在某些情况下,我们为包含类型转发器的已弃用程序集提供 Visual Studio 2022 版本包。 如果可用,可以选择 升级 对 Visual Studio 2022 版本的包引用,而不是将其删除。 类型转发器将解决编译器中的错误。

请记住,有时这些引用可以通过传递包引用来提供,因此比在项目文件中进行的直接引用更难删除。 在这种情况下,请确保所有直接包引用都使用 Visual Studio 2022 SDK 包本身。 可以引用 project.assets.json 来标识负责引入已弃用程序集的包链。 更新对 Visual Studio 2022 版本的可传递包引用与直接引用一样简单。

如果无法更改依赖项树(例如,因为它涉及第三方依赖项),则可以将直接包引用添加到 Visual Studio 2022 之前的包,并将元数据添加到 ExcludeAssets="compile" 该项 PackageReference 以解决编译器错误。 但请记住,使用此技术,扩展可能会保留对 Visual Studio 2022 前程序集的依赖项,并且扩展在运行时可能会发生故障。

缺少对互操作程序集的引用

引用针对 Visual Studio 2022 SDK 编译的程序集时,可能会遇到有关缺少程序集引用的错误。

示例错误:

错误 CS0012 在未引用的程序集中定义类型“IVsTextViewFilter”。 必须添加对程序集“Microsoft.VisualStudio.TextManager.Interop, Version=7.1.40304.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a” 的引用

使用引用程序集重新映射表,可以确认请求的程序集实际上不是必须引用的程序集。

最佳解决方法是将依赖项更新为针对 Visual Studio 2022 SDK 编译的版本,以便编译器不再请求已删除的互操作程序集。

在某些情况下,我们为包含类型转发器的已弃用程序集提供 Visual Studio 2022 版本包。 如果可用,可以选择添加对已过时包的 Visual Studio 2022 版本的包引用,以便类型转发器能够解决编译器的错误。

IAsyncServiceProvider 缺少

此接口有两个定义,在两个命名空间中。 其中只有一个用于托管消耗。

Visual Studio 2019 命名空间 Visual Studio 2022 命名空间 预期用途
Microsoft.VisualStudio.Shell.IAsyncServiceProvider Microsoft.VisualStudio.Shell.IAsyncServiceProvider 托管代码消耗
Microsoft.VisualStudio.Shell.Interop.IAsyncServiceProvider Microsoft.VisualStudio.Shell.COMAsyncServiceProvider.IAsyncServiceProvider 仅低级别互操作

如果看到有关 IAsyncServiceProvider的错误, 则可能 是你使用的是适用于本机代码(第二行)的错误。 如果是这样,则可以更新到新命名空间,或切换到更易管理的接口。

DTE_DTE 类型强制转换失败

DTE_DTE 两个接口。 一个派生自另一个。 但在 Visual Studio 2022 中,将交换基类型和派生类型。 这使得某些类型分配或强制转换失败。

这也意味着过去使用 new DTE()的位置,现在 new _DTE()必须使用。

若要缓解此问题的大多数问题, DTE2 请改用 EnvDTE80 命名空间。

方法调用缺少参数

一些方法不再为互操作 API 中的可选参数声明默认参数。 如果收到有关 COM 互操作调用缺失参数的错误,以及类型的参数调用 object ,则可能是 ""Visual Studio 2019 互操作 API 定义的以前的默认值,因此请考虑添加 "" 为参数来解决编译错误。

当怀疑默认参数是什么时,请尝试将语言服务上下文从 Visual Studio 2022 切换到 Visual Studio 2019,以便使用较旧的互操作程序集获得 Intellisense,以查看默认参数是什么,然后将其显式添加到代码中。 为 Visual Studio 2019 编译时,它将继续正常工作,但现在将针对 Visual Studio 2022 进行编译。

示例修复:

-process4.Attach2();
+process4.Attach2("");

旧版查找 API 弃用

作为在文件中实现查找现代化工作的一部分,我们已弃用对 VS 2022 中 EnvDTE 接口的以下 API 的支持。

这些 API 将不再适用于 VS 2022 及更高版本。 指导是改用 IFinder 接口(Microsoft.VisualStudio.Text.Operations), 该接口具有查找和替换方法。 可以通过 IFindService.CreateFinderFactory 方法获取对实现 IFinder 接口的对象的访问权限。 可以在此处找到将第三方扩展从旧 API 迁移到新式 IFinder API 到 Visual Studio 的示例: 将 Code Maid 扩展从 EnvDTE 查找和替换模式 API 迁移到新式 IFinder API