Search code examples
c#visual-studiomsbuildvsix

Using MSBuild at command-line to produce VSIX does not error, does not build VSIX - but IDE does. How to debug?


I have a VSIX extension which I have migrated to a new solution (basically to remove older projects targeting older VS versions no longer supported by my company) and to simplify the codebase for ease of maintenance.

Within the IDE, it does not matter if I set the active configuration to Debug|x86 or Release|x86, it will build a VSIX artifact OK. All good so far.

If I use MSBuuild /t:Build /p:Configuration=Release /p:Platform=x86 -restore -detailedSummary MyExtension.sln it will build without any errors, but no VSIX is produced.

I have poured over the terminal output and there are no warnings/errors and the DLL output of projects in the solution are produced.

I did read the following: Project not selected to build for this solution configuration The option to click deploy from the above link is not available for my VSIX - all the deploy options are disabled.

I have searched S.O. for similar issues regarding a VSIX not being produced, but none seem apt.

How should I debug this? What is different about a command-line MSBuild from the in-IDE build? Hopefully somebody has had a similar experience and can let me know what was causal for them, so that I can give something a try.

Update 1: It transpired that although I was targeting .NET Framework 4.6, some .csproj references copied over from the migrated project had entries for net472, despite NuGet packages themselves being selected for compatibility with .NET Framework 4.6.

I had to manually edit a few .csproj files. There were some reference issues in associated projects that then needed fixing.

The residual issue now is as follows: The in-IDE build fails with a single error... A PackageReference to Microsoft.Build.* without ExcludeAssets="runtime" exists in your project. This will cause MSBuild assemblies to be copied to your output directory, causing your application to load them at runtime. To use the copy of MSBuild registered by MSBuildLocator, set ExcludeAssets="runtime" on the MSBuild PackageReferences. To disable this check, set the property DisableMSBuildAssemblyCopyCheck=true in your project file (not recommended as you must distributed all of MSBuild + associated toolset). Package(s) referenced: Microsoft.Build.Framework

So I grepped my source code folder for <PackageReference Include="Microsoft.Build and only a single project was in the result list. When I checked this project file, the entry in question did have ExcludeAssets="runtime" so I am unsure why the error is reported. I have tried project cleans followed by rebuild, or deleting bin and obj folders before building, to no avail.

I guess my question now is whether <Package Include="Microsoft.Build are relevant, since these are not <ReferencePackage Include elements as mentioned in the error message.

Update 2: I hang my head in shame. PBKAC regarding Update 1 error. I had sent a copy of the code to a build engineer who committed it to a branch in our VCS. I then cloned this branch to a different location, and copy+pasted my more recent changes over the top. However, the grep tool (AstroGrep) I was using was still pointing at the older location not in the VCS. The older location contained package references with ExcludeAssets="runtime" as required. However, the newer location did not. Once I noticed this, I corrected it by editing the faulty .csproj file and the error from Update 1 went away.

However, I still appear to have the original issue the question is about.

I am awaiting my company's security team to approve the use of MSBuildLog so that I can get more detail and hopefully find the cause.

One other commenter suggest moving to solution PackageReference build rather than using packages.config. There is a question as to why this is needed. I am aware this seems like it could create a significant amount of extra work due to: this for which there are workarounds, but the commenter mentioned a "need" to use NuGet this way, when I think it is optional. I wish to understand more before committing to such a change.


Solution

  • Unfortunately, this is one of those things where it's a case of user beware.

    When using NuGet, it is possible for it to appear to have succeeded in updating a NuGet reference, but unless one checks the underlying packages.config meticulously, you may not be getting what you think.

    As I am migrating a solution that used packages.config instead of <Project Reference .../> elements in .csproj files, I have been caught out by IDE default behaviour changes.

    NuGet seems to update the .csproj using <PacakageReference.../> elements by default. But this does not amend the packages.config entries that may already exist. As such, I ended up with a mish-mash that MSBuild seemed confused about at build time. Rather than throw an error, it just did not build what was expected.

    The old packages.config files had entries targeting .NET Framework of net472 in some cases. I was adding NuGet references to earlier versions for net46 since this is what I need to target now, and this resulted in the problem behaviour, since any unchanged net472 entries were no good for producing the build output.

    Since the project needs to support VS2015 also, I need to rely on packages.config approach and not <PackageReference.../> approach, which was not updating older references in the expected way.

    As such, I had to remove the NuGet <PacakgeReference.../> and re-introduce correct package versions in packages.config. Once these were all correct, the VSIX built OK.