VSIX 扩展 - 如何确保引用的 dll 或程序集包含在 VSIX 文件中?
VSIX extension - How can I ensure a referenced dll or assembly is included in the VSIX file?
当用户安装我的扩展,但没有安装最新的 Visual Studio 更新时,扩展无法解析 Microsoft.CodeAnalysis.CSharp.dll 以及以下消息:
Could not load file or assembly 'Microsoft.CodeAnalysis.CSharp,
Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or
one of its dependencies. The system cannot find the file specified.
我确定扩展确实引用了这个程序集,它确实引用了这个程序集,但是为什么这个程序集会被排除在 VSIX 文件之外?
我将 VSIX 文件重命名为 ZIP,查看了内容,但该程序集未发货,即使其他 "Microsoft.CodeAnalysis.*.dll" 程序集包含在 VSIX 文件中。
我还确认了参考文献中的“复制本地”属性是正确的。
我找到了这个问题的解决方案,我可以看到该 dll 现在包含在 VSIX 中,并且用户确认它适用于他。
- 在 Visual Studio 中,打开扩展解决方案,
- 双击 .vsixmanifest 文件
- 打开 "Assets" 选项卡
- 点击"New"
- 将类型设置为 "Microsoft.VisualStudio.Assembly"
- 将源设置为 "A File on FileSystem"
- 单击“浏览”为您的 dll 设置路径,(不用担心引用不会添加为绝对路径,而是添加为相对路径或只是一个强大的程序集名称)
- 您可以将 "Embed in this folder" 留空。
- 点击确定
- 重建解决方案,该文件现在应该在 VSIX 文件中。
然后将此行添加到 vsixmanifest 文件中:
<Asset Type="Microsoft.VisualStudio.Assembly" d:Source="File" Path="Microsoft.CodeAnalysis.CSharp.dll" AssemblyName="Microsoft.CodeAnalysis.CSharp, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
我找到了与 Martin 类似的解决方法,但没有要求 DLL 副本位于项目文件夹中的副作用。 (我还没有想出如何添加丢失的非英语资源程序集。)
第 0 步:如果您有间接依赖项 - vsix 依赖于使用 NuGet 包 C 的项目 B,而 C 依赖于包 D - 确保 C 和 D 的 DLL 包含在您的 vsix 的 bin\Debug 文件夹中.如果没有,为了安全起见,我建议将对包 C 和 D 的引用添加到 vsix 项目中。就我而言,VS 决定在 VSIX 中包含一些间接依赖项,例如 System.Numerics.Vectors.dll 和 System.Threading.Tasks.Extensions.dll,但它决定省略四个间接依赖项:Microsoft.CodeAnalysis.dll、Microsoft.CodeAnalysis.CSharp.dll、System.Reflection.Metadata.dll 和 System.Collections.Immutable.dll.
第 1 步:重建并找出 VSIX 中丢失的文件。您可以将 .vsix 重命名为 .zip 以找出其中的内容,并将其与 vsix 项目文件夹中 bin\Debug 的内容进行比较以查找丢失的项目。
第 2 步:使用“添加 > 现有项目...”和“添加为 Link”将缺少的 DLL 添加到您的项目中(如果您不确定 DLL 的位置,请查找它在您的引用列表中并在“属性”面板中查看其路径 属性。)
第 3 步:对每个缺少的 DLL 重复第 2 步。
第 4 步:Select 新的 DLL,并在“属性”面板中设置“包含在 VSIX 中”标志。
在我的(旧式)csproj 中,我最终得到这样的 ItemGroup
:
<ItemGroup>
<Content Include="..\packages\Microsoft.CodeAnalysis.Common.3.6.0\lib\netstandard2.0\Microsoft.CodeAnalysis.dll">
<Link>Microsoft.CodeAnalysis.dll</Link>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="..\packages\Microsoft.CodeAnalysis.CSharp.3.6.0\lib\netstandard2.0\Microsoft.CodeAnalysis.CSharp.dll">
<Link>Microsoft.CodeAnalysis.CSharp.dll</Link>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="..\packages\System.Collections.Immutable.1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll">
<Link>System.Collections.Immutable.dll</Link>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="..\packages\System.Reflection.Metadata.1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll">
<Link>System.Reflection.Metadata.dll</Link>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
</ItemGroup>
第 5 步:重建并验证文件现在是否包含在 vsix 中。您不需要将文件添加到资产列表中。然后在Visual Studio中进行测试。祝你好运!
P.S. 我突然想到,也许 VSIX 不包含这些文件的原因是因为 VS 知道 Visual Studio 已经有了这些文件安装的文件。但是这个解释并不令人满意,因为,例如,Visual Studio 有 System.Memory.dll 和 System.Numerics.Vectors.dll 的副本,但是VS 仍然选择在我的 VSIX 中包含那些 DLL。
无论如何,我的扩展无法加载 Visual Studio 2019 年的文件副本。我注意到我的 Microsoft.CodeAnalysis.dll 版本是“3.6.0-4.20269.4+...”,而 C:\Program Files (x86)\Microsoft Visual Studio19\Community\Common7\IDE\CommonExtensions\Microsoft\ManagedLanguages\VBCSharp\LanguageServices 中的副本 是“3.5.0-beta4-20153-05+...”(假设这是重要的 - 我不知道,程序文件中还有 5 个其他副本)。通过将我的 VSIX 降级为使用 早于 3.5.0-beta4 的版本(假设 Beta 版本不在 NuGet 上),也许我的扩展可以使用 Visual Studio 的复制。但这是另一天的测试,即使它有效,如果我想同时针对 Visual Studio 2017 和 Visual Studio 2019,我怀疑如果我不这样做,我是否可以同时针对同一个 vsix 的两个版本vsix 中没有包含我需要的所有 DLL。
将此添加到 csproj:
<Target Name="IncludePackageReferenceDependencies" AfterTargets="GetVsixSourceItems">
<ItemGroup>
<!-- <VSIXSourceItem Include="@(ReferencePath)" Condition="$([System.String]::new('%(ReferencePath.FusionName)').EndsWith('.dll'))" /> -->
<VSIXSourceItem Include="@(ReferencePath)" />
</ItemGroup>
</Target>
对于那些不喜欢为丢失的 dll 添加引用的人,我发现以下内容非常有效
https://www.cazzulino.com/include-dlls-in-vsix.html
我在 .csproj 的末尾添加了以下内容,所有丢失的 dll 都在 .vsix
<PropertyGroup>
<GetVsixSourceItemsDependsOn>$(GetVsixSourceItemsDependsOn);IncludeNuGetResolvedAssets</GetVsixSourceItemsDependsOn>
</PropertyGroup>
<Target Name="IncludeNuGetResolvedAssets" DependsOnTargets="ResolveNuGetPackageAssets">
<ItemGroup>
<VSIXCopyLocalReferenceSourceItem Include="@(ReferenceCopyLocalPaths)" />
</ItemGroup>
</Target>
当用户安装我的扩展,但没有安装最新的 Visual Studio 更新时,扩展无法解析 Microsoft.CodeAnalysis.CSharp.dll 以及以下消息:
Could not load file or assembly 'Microsoft.CodeAnalysis.CSharp, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.
我确定扩展确实引用了这个程序集,它确实引用了这个程序集,但是为什么这个程序集会被排除在 VSIX 文件之外?
我将 VSIX 文件重命名为 ZIP,查看了内容,但该程序集未发货,即使其他 "Microsoft.CodeAnalysis.*.dll" 程序集包含在 VSIX 文件中。
我还确认了参考文献中的“复制本地”属性是正确的。
我找到了这个问题的解决方案,我可以看到该 dll 现在包含在 VSIX 中,并且用户确认它适用于他。
- 在 Visual Studio 中,打开扩展解决方案,
- 双击 .vsixmanifest 文件
- 打开 "Assets" 选项卡
- 点击"New"
- 将类型设置为 "Microsoft.VisualStudio.Assembly"
- 将源设置为 "A File on FileSystem"
- 单击“浏览”为您的 dll 设置路径,(不用担心引用不会添加为绝对路径,而是添加为相对路径或只是一个强大的程序集名称)
- 您可以将 "Embed in this folder" 留空。
- 点击确定
- 重建解决方案,该文件现在应该在 VSIX 文件中。
然后将此行添加到 vsixmanifest 文件中:
<Asset Type="Microsoft.VisualStudio.Assembly" d:Source="File" Path="Microsoft.CodeAnalysis.CSharp.dll" AssemblyName="Microsoft.CodeAnalysis.CSharp, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
我找到了与 Martin 类似的解决方法,但没有要求 DLL 副本位于项目文件夹中的副作用。 (我还没有想出如何添加丢失的非英语资源程序集。)
第 0 步:如果您有间接依赖项 - vsix 依赖于使用 NuGet 包 C 的项目 B,而 C 依赖于包 D - 确保 C 和 D 的 DLL 包含在您的 vsix 的 bin\Debug 文件夹中.如果没有,为了安全起见,我建议将对包 C 和 D 的引用添加到 vsix 项目中。就我而言,VS 决定在 VSIX 中包含一些间接依赖项,例如 System.Numerics.Vectors.dll 和 System.Threading.Tasks.Extensions.dll,但它决定省略四个间接依赖项:Microsoft.CodeAnalysis.dll、Microsoft.CodeAnalysis.CSharp.dll、System.Reflection.Metadata.dll 和 System.Collections.Immutable.dll.
第 1 步:重建并找出 VSIX 中丢失的文件。您可以将 .vsix 重命名为 .zip 以找出其中的内容,并将其与 vsix 项目文件夹中 bin\Debug 的内容进行比较以查找丢失的项目。
第 2 步:使用“添加 > 现有项目...”和“添加为 Link”将缺少的 DLL 添加到您的项目中(如果您不确定 DLL 的位置,请查找它在您的引用列表中并在“属性”面板中查看其路径 属性。)
第 3 步:对每个缺少的 DLL 重复第 2 步。
第 4 步:Select 新的 DLL,并在“属性”面板中设置“包含在 VSIX 中”标志。
在我的(旧式)csproj 中,我最终得到这样的 ItemGroup
:
<ItemGroup>
<Content Include="..\packages\Microsoft.CodeAnalysis.Common.3.6.0\lib\netstandard2.0\Microsoft.CodeAnalysis.dll">
<Link>Microsoft.CodeAnalysis.dll</Link>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="..\packages\Microsoft.CodeAnalysis.CSharp.3.6.0\lib\netstandard2.0\Microsoft.CodeAnalysis.CSharp.dll">
<Link>Microsoft.CodeAnalysis.CSharp.dll</Link>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="..\packages\System.Collections.Immutable.1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll">
<Link>System.Collections.Immutable.dll</Link>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="..\packages\System.Reflection.Metadata.1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll">
<Link>System.Reflection.Metadata.dll</Link>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
</ItemGroup>
第 5 步:重建并验证文件现在是否包含在 vsix 中。您不需要将文件添加到资产列表中。然后在Visual Studio中进行测试。祝你好运!
P.S. 我突然想到,也许 VSIX 不包含这些文件的原因是因为 VS 知道 Visual Studio 已经有了这些文件安装的文件。但是这个解释并不令人满意,因为,例如,Visual Studio 有 System.Memory.dll 和 System.Numerics.Vectors.dll 的副本,但是VS 仍然选择在我的 VSIX 中包含那些 DLL。
无论如何,我的扩展无法加载 Visual Studio 2019 年的文件副本。我注意到我的 Microsoft.CodeAnalysis.dll 版本是“3.6.0-4.20269.4+...”,而 C:\Program Files (x86)\Microsoft Visual Studio19\Community\Common7\IDE\CommonExtensions\Microsoft\ManagedLanguages\VBCSharp\LanguageServices 中的副本 是“3.5.0-beta4-20153-05+...”(假设这是重要的 - 我不知道,程序文件中还有 5 个其他副本)。通过将我的 VSIX 降级为使用 早于 3.5.0-beta4 的版本(假设 Beta 版本不在 NuGet 上),也许我的扩展可以使用 Visual Studio 的复制。但这是另一天的测试,即使它有效,如果我想同时针对 Visual Studio 2017 和 Visual Studio 2019,我怀疑如果我不这样做,我是否可以同时针对同一个 vsix 的两个版本vsix 中没有包含我需要的所有 DLL。
将此添加到 csproj:
<Target Name="IncludePackageReferenceDependencies" AfterTargets="GetVsixSourceItems">
<ItemGroup>
<!-- <VSIXSourceItem Include="@(ReferencePath)" Condition="$([System.String]::new('%(ReferencePath.FusionName)').EndsWith('.dll'))" /> -->
<VSIXSourceItem Include="@(ReferencePath)" />
</ItemGroup>
</Target>
对于那些不喜欢为丢失的 dll 添加引用的人,我发现以下内容非常有效
https://www.cazzulino.com/include-dlls-in-vsix.html
我在 .csproj 的末尾添加了以下内容,所有丢失的 dll 都在 .vsix
<PropertyGroup>
<GetVsixSourceItemsDependsOn>$(GetVsixSourceItemsDependsOn);IncludeNuGetResolvedAssets</GetVsixSourceItemsDependsOn>
</PropertyGroup>
<Target Name="IncludeNuGetResolvedAssets" DependsOnTargets="ResolveNuGetPackageAssets">
<ItemGroup>
<VSIXCopyLocalReferenceSourceItem Include="@(ReferenceCopyLocalPaths)" />
</ItemGroup>
</Target>