VSIX extension - How can I ensure a referenced dll or assembly is included in the VSIX file?
Asked Answered
Y

4

12

When a user installs my extension, but does not have the latest Visual Studio update installed, the extension fails to resolve Microsoft.CodeAnalysis.CSharp.dll with the followeing message:

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.

I made sure that the extension does in fact reference this assembly, and it does, but why would this assembly be excluded from the VSIX file?

I renamed the VSIX file to a ZIP, looked at the contents, but this assembly is not shipped, even though other "Microsoft.CodeAnalysis.*.dll" assemblies are included in the VSIX file.

I also confirmed that the "Copy Local" property on the reference is True.

Yama answered 13/2, 2017 at 10:33 Comment(2)
I have the same behavior here. Some assemblies just don't get in the vsix no matter what you do.Stereochromy
Hi @HugoQuintelaRibeiro, please see the solution I found below. Hopefully it can help you too.Yama
Y
9

I found a solution to this problem, and I can see the dll now included in the VSIX and a user confirmed that it works for him.

  1. In Visual Studio, with the extension solution open,
  2. double click the .vsixmanifest file
  3. Open the "Assets" tab
  4. Click "New"
  5. Set Type to "Microsoft.VisualStudio.Assembly"
  6. Set Source to "A File on FileSystem"
  7. Click Browse to set Path to your dll, (don't worry the reference is not added as an absolute path, but added as a relative path or just a strong assembly name)
  8. You can leave "Embed in this folder" empty.
  9. Click OK
  10. Rebuild the solution, and the file should be in the VSIX file now.

enter image description here

This line is then added to the vsixmanifest file:

<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" />
Yama answered 13/2, 2017 at 13:20 Comment(2)
This worked for me, but it should be noted that lots of DLLs, especially the Microsoft ones, come with numerous separate foreign-language resource assemblies. Without those assemblies, which presumably must be arranged in the correct folders, text will always be English. Also VS weirdly copies the new "Asset" DLLs to the root of the project folder; not sure if this can be prevented. Related: #6974744Toiletry
Sadly, removing the extra copies from the project and changing the vsix manually to add paths (e.g. changing Path="Microsoft.CodeAnalysis.dll" to Path="..\packages\Microsoft.CodeAnalysis.Common.3.6.0\lib\netstandard2.0\Microsoft.CodeAnalysis.dll" does not work - as soon as you delete the extra copy, the dll is no longer included in the vsix.Toiletry
L
1

For anyone who doesnt like to add the references for missing dlls i found the following which works perfectly

https://www.cazzulino.com/include-dlls-in-vsix.html

I added the following to end of my .csproj and all missing dlls ended up in the .vsix

<PropertyGroup>
    <GetVsixSourceItemsDependsOn>$(GetVsixSourceItemsDependsOn);IncludeNuGetResolvedAssets</GetVsixSourceItemsDependsOn>
</PropertyGroup>
<Target Name="IncludeNuGetResolvedAssets" DependsOnTargets="ResolveNuGetPackageAssets">
    <ItemGroup>
        <VSIXCopyLocalReferenceSourceItem Include="@(ReferenceCopyLocalPaths)"  />
    </ItemGroup>
</Target>
Limpopo answered 4/3, 2022 at 11:48 Comment(0)
T
0

I found a similar workaround to Martin, but without the side effect of requiring copies of the DLLs to be in your project folder. (I still haven't worked out how to add the missing non-English resource assemblies.)

Step 0: If you have indirect dependencies - vsix depends on project B which uses NuGet package C which depends on package D - make sure that the DLLs of C and D are included in your vsix's bin\Debug folder. If not, just to be safe, I suggest adding references to package C and D to the vsix project. In my case, VS decided to include some indirect dependencies like System.Numerics.Vectors.dll and System.Threading.Tasks.Extensions.dll in the VSIX, but it decided to leave out four indirect dependencies: Microsoft.CodeAnalysis.dll, Microsoft.CodeAnalysis.CSharp.dll, System.Reflection.Metadata.dll and System.Collections.Immutable.dll.

Step 1: Rebuild and find out what files are missing from the VSIX. You can rename your .vsix to .zip to find out what is inside, and compare that to the contents of bin\Debug in your vsix's project folder to find missing items.

Step 2: Use "Add > Existing Item..." with "Add as Link" to add a missing DLL to your project (if you are unsure about where the DLL is located, find it in your list of References and look at its Path property in the Properties panel.)

Step 2a Step 2b

Step 3: Repeat Step 2 for every missing DLL.

Step 4: Select the new DLLs and in the Properties panel, set the "Include in VSIX" flag.

Step 4

In my (old-style) csproj I end up with an ItemGroup like this:

  <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>

Step 5: Rebuild and verify that the files are now included in the vsix. You don't need to add the files to the list of Assets. Then test it in Visual Studio. Good luck!

P.S. It has crossed my mind that perhaps the reason the VSIX does not include these files is because VS knows that Visual Studio already has those files installed. But this explanation is unsatisfying because, for example, Visual Studio has copies of System.Memory.dll and System.Numerics.Vectors.dll but VS still chose to include those DLLs in my VSIX.

In any case, my extension cannot load Visual Studio 2019's copy of the files. I notice that my version of Microsoft.CodeAnalysis.dll is "3.6.0-4.20269.4+..." while the copy in C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\ManagedLanguages\VBCSharp\LanguageServices is "3.5.0-beta4-20153-05+..." (assuming that's the important one - I don't know, there are 5 other copies in Program Files). By downgrading my VSIX to use a version earlier than 3.5.0-beta4 (assuming beta versions are not on NuGet), perhaps my extension would be able to use Visual Studio's copy. But that's a test for another day, and even if it works, if I want to target both Visual Studio 2017 and Visual Studio 2019, I doubt I could target both versions simultaneously with the same vsix if I don't include all the DLLs I need in the vsix.

Toiletry answered 6/7, 2020 at 16:23 Comment(0)
J
0

Add this to the csproj:

  <Target Name="IncludePackageReferenceDependencies" AfterTargets="GetVsixSourceItems">
    <ItemGroup>
      <!-- <VSIXSourceItem Include="@(ReferencePath)" Condition="$([System.String]::new('%(ReferencePath.FusionName)').EndsWith('.dll'))" /> -->
      <VSIXSourceItem Include="@(ReferencePath)" />
    </ItemGroup>
  </Target>
Jeanene answered 17/9, 2021 at 10:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.