Visual Studio 2022 中的中断性 API 更改

适用于:yesVisual Studio noVisual Studio for Mac noVisual Studio Code

如果要将扩展迁移到 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,其中一些互操作 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# 编译器报告你正在使用的类型在两个程序集中定义的错误时,你可能从不应再引用的 Visual Studio 2019 版本的 SDK 引用程序集。

示例错误:

错误 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()必须使用。

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

方法调用时缺少参数

几个方法不再声明互操作 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 接口的对象。 可以在此处找到将第三方扩展迁移到 Visual Studio 的示例: 将 Code Maid 扩展从 EnvDTE 查找和替换模式 API 迁移到新式 IFinder API