Migrate the VS extension to an SDK-style VSIX (dotnet build) and retire the VS2017/2019 add-in#3808
Merged
Merged
Conversation
Following Microsoft's "SDK-style support for extension projects" guidance, this drops the hybrid Sdk.props/Sdk.targets plus the legacy Microsoft.VsSDK.targets import in favour of VSSDKBuildToolsAutoSetup and a CreateVsixContainer capability, so the VSIX now builds with plain dotnet build instead of full msbuild. Microsoft.VSSDK.BuildTools is bumped to 18.5.x, which is the floor for that auto-setup. Three problems the reference migrations do not hit, all scoped to this project so the still-hybrid legacy VS2017/2019 add-in is unaffected: - VSPackage.resx resource 400 (the Help/About package icon) is a binary System.Drawing.Icon. The dotnet CLI GenerateResource task cannot BinaryFormatter-serialize it the way full msbuild does, so it needs GenerateResourceUsePreserializedResources and System.Resources.Extensions. - The VSSDK CTO merger reads VSPackage.resources with the classic reader and rejects that preserialized format, so MergeWithCTO is turned off here; VSCTCompile already embeds Menus.ctmenu as its own resource. - System.Design (MenuCommandService) was supplied implicitly by full msbuild and must be referenced explicitly under the SDK. The solution is migrated to ILSpy.VSExtensions.slnx (the .sln is kept so the existing msbuild-based CI step keeps resolving) with a Deploy entry on the VS2022 project for F5 deploy in VS 18.5+. Assisted-by: Claude:claude-opus-4-8:Claude Code
The VS2017/2019 extension was the last remaining hybrid project that could only be built with full msbuild. It is obsolete now that the VS2022 add-in is the supported integration, so this removes the ILSpy.AddIn project and everything that fed it: the solution entries, its VSIX manifest template generation in update-assemblyinfo.ps1, the committed vsix filelist, the dead SortResX glob in ILSpy.csproj, and the CI build step rename plus the VS2017/2019 artifact upload. The shared project's VSPackage.resx referenced the package icon by a path into the legacy project; it now points at the byte-identical copy under ILSpy.AddIn.VS2022. With the legacy project gone, the entire ILSpy.VSExtensions solution builds end to end with dotnet build. Assisted-by: Claude:claude-opus-4-8:Claude Code
With the legacy add-in retired, the VS2022 extension is the only project left in the VS extensions solution and it builds as a true SDK-style VSIX, so full msbuild is no longer required. Drop ILSpy.VSExtensions.sln in favour of the slnx and have CI build it with dotnet build, matching how the rest of the repo builds. Update the README and CLAUDE.md references to the renamed solution. Assisted-by: Claude:claude-opus-4-8:Claude Code
Contributor
There was a problem hiding this comment.
Pull request overview
Migrates the Visual Studio integration to a single SDK-style VSIX project (ILSpy.AddIn.VS2022) that can be built with dotnet build, removes the legacy VS2017/2019 add-in project, and updates the VS extensions solution/CI to use .slnx + dotnet build instead of full msbuild.
Changes:
- Convert
ILSpy.AddIn.VS2022to a true SDK-style VSIX build (VSSDK auto-setup, preserialized resources, disable CTO merge) and inline previously shared add-in code into the project. - Remove the obsolete
ILSpy.AddIn(VS2017/2019) project and related build/CI artifacts. - Replace
ILSpy.VSExtensions.slnwithILSpy.VSExtensions.slnxand update docs/CI accordingly.
Reviewed changes
Copilot reviewed 26 out of 50 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| README.md | Update references from ILSpy.VSExtensions.sln to .slnx. |
| publishlocaldev.ps1 | Adjust local publish flow to build solution first and support arm64 alongside x64. |
| ILSpy/Properties/Resources.resx | Add new localized string for About output (“started from”). |
| ILSpy/Properties/Resources.Designer.cs | Regenerate strongly-typed resource accessor for new string. |
| ILSpy/ILSpy.csproj | Remove legacy add-in .resx sort input reference. |
| ILSpy/Commands/AboutCommand.cs | Add startup path line to About output. |
| ILSpy.VSExtensions.slnx | New .slnx solution for VS extension build via dotnet build. |
| ILSpy.VSExtensions.sln | Remove legacy .sln solution. |
| ILSpy.AddIn/source.extension.vsixmanifest.template | Removed as part of retiring VS2017/2019 add-in. |
| ILSpy.AddIn/README.md | Removed as part of retiring VS2017/2019 add-in. |
| ILSpy.AddIn/Properties/launchSettings.json | Removed as part of retiring VS2017/2019 add-in. |
| ILSpy.AddIn/Properties/AssemblyInfo.cs | Removed as part of retiring VS2017/2019 add-in. |
| ILSpy.AddIn/packages.lock.json | Removed as part of retiring VS2017/2019 add-in. |
| ILSpy.AddIn/NuGet.config | Removed as part of retiring VS2017/2019 add-in. |
| ILSpy.AddIn/ILSpyAddIn.vsct | Removed as part of retiring VS2017/2019 add-in. |
| ILSpy.AddIn/ILSpyAddIn.en-US.vsct | Removed as part of retiring VS2017/2019 add-in. |
| ILSpy.AddIn/ILSpy.AddIn.csproj | Removed as part of retiring VS2017/2019 add-in. |
| ILSpy.AddIn/Decompiler/Dummy.cs | Removed as part of retiring VS2017/2019 add-in. |
| ILSpy.AddIn.VS2022/VSPackage.resx | Update package icon resource path to VS2022 project resources. |
| ILSpy.AddIn.VS2022/VSPackage.en-US.resx | Add localized package resource file. |
| ILSpy.AddIn.VS2022/Resources.resx | Add package-local resources for SDK-style build layout. |
| ILSpy.AddIn.VS2022/Resources.Designer.cs | Add generated strongly-typed Resources class for VS2022 add-in. |
| ILSpy.AddIn.VS2022/packages.lock.json | Update lockfile for new build tools/resources dependencies. |
| ILSpy.AddIn.VS2022/ILSpy.AddIn.VS2022.csproj | Convert to SDK-style VSIX build, update VSSDK settings and references, inline shared code. |
| ILSpy.AddIn.VS2022/Utils.cs | Add utility helpers for VS integration (selection/view/workspace/project output path). |
| ILSpy.AddIn.VS2022/SyntaxNodeExtensions.cs | Add Roslyn syntax helpers used by code-item navigation. |
| ILSpy.AddIn.VS2022/ILSpyInstance.cs | Add VSIX-side ILSpy launcher logic (x64/arm64). |
| ILSpy.AddIn.VS2022/ILSpyAddInPackage.cs | Add AsyncPackage implementation and command registration. |
| ILSpy.AddIn.VS2022/PkgCmdID.cs | Add command ID constants for VSCT integration. |
| ILSpy.AddIn.VS2022/Guids.cs | Add package/command set GUID declarations. |
| ILSpy.AddIn.VS2022/GlobalSuppressions.cs | Add project-level analyzer suppression file. |
| ILSpy.AddIn.VS2022/AssemblyFileFinder.cs | Add helper for resolving runtime vs reference assemblies and TFMs. |
| ILSpy.AddIn.VS2022/Commands/AssemblyReferenceForILSpy.cs | Add detection + parameter building for assembly references. |
| ILSpy.AddIn.VS2022/Commands/NuGetReferenceForILSpy.cs | Add detection + parameter building for NuGet references. |
| ILSpy.AddIn.VS2022/Commands/ProjectReferenceForILSpy.cs | Add detection + parameter building for project references. |
| ILSpy.AddIn.VS2022/Commands/ProjectItemForILSpy.cs | Add wrapper for determining project output assembly path. |
| ILSpy.AddIn.VS2022/Commands/OpenILSpyCommand.cs | Add base command wiring + reference discovery and “open ILSpy” command. |
| ILSpy.AddIn.VS2022/Commands/OpenReferenceCommand.cs | Add context-menu command to open selected references in ILSpy. |
| ILSpy.AddIn.VS2022/Commands/OpenProjectOutputCommand.cs | Add command to open current project output in ILSpy. |
| ILSpy.AddIn.VS2022/Commands/OpenCodeItemCommand.cs | Add command to open ILSpy at symbol under caret via Roslyn model. |
| ILSpy.AddIn.Shared/ILSpy.AddIn.Shared.shproj | Removed shared-items project (code is now inlined into VS2022 add-in). |
| ILSpy.AddIn.Shared/ILSpy.AddIn.Shared.projitems | Removed shared-items project items list (code now inlined). |
| CLAUDE.md | Update solution references to .slnx and clarify VS2022 extension build path. |
| BuildTools/update-assemblyinfo.ps1 | Remove legacy add-in manifest template generation step. |
| BuildTools/ILSpy.AddIn.vsix.filelist | Remove legacy VS2017/2019 VSIX filelist snapshot. |
| .github/workflows/build-ilspy.yml | Switch VS extension CI build step to dotnet build on .slnx and drop legacy artifact upload. |
Files not reviewed (1)
- ILSpy/Properties/Resources.Designer.cs: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
christophwille
force-pushed
the
christophwille/vsix
branch
from
June 23, 2026 10:12
173e554 to
f5082d0
Compare
The shared project had a single consumer after the VS2017/2019 add-in was retired, and its VSPackage.resx already referenced an icon in the sibling VS2022 project. Folding its sources and resources directly into VS2022 drops the shproj/projitems indirection and the extra slnx entry, leaving one self-contained extension project. The package-icon ResXFileRef is repointed to the now-local Resources\Package.ico. Assisted-by: Claude:claude-opus-4-8:Claude Code
christophwille
force-pushed
the
christophwille/vsix
branch
from
June 23, 2026 10:15
f5082d0 to
452843f
Compare
ProvideMenuResource("Menus.ctmenu", 1) makes Visual Studio load the command
table from the "Menus.ctmenu" entry of the package's VSPackage.resources
stream, so the compiled .vsct has to be merged into it (MergeWithCTO). The
SDK-style migration could not do that: VSPackage.resx carried the package icon
as a binary System.Drawing.Icon, which the dotnet CLI can only emit via
System.Resources.Extensions (preserialized), and the VSSDK CTO merger fails to
read that format (VSSDK1012). The migration worked around the build error by
setting MergeWithCTO=false, which made the build succeed but routed the command
table into the throwaway _EmptyResource the VSSDK injects when nothing opts in
to the merge -- a stream VS never consults. The result built cleanly but
shipped a package with no menus: no ILSpy entry under Tools, no context-menu
commands.
Drop the binary package icon (resource 400 and InstalledProductRegistration's
IconResourceID) so VSPackage.resx is string-only and emits in the classic
format, then turn MergeWithCTO back on. The command table is now merged into
the package resources where VS looks, exactly as the pre-migration full-msbuild
build produced. The icon was the legacy Help/About "Installed Products" logo,
which modern Visual Studio no longer surfaces; the extension's identity icon in
the Extensions manager comes from the .vsixmanifest (ILSpy-Large.ico) and is
unaffected. This also removes the System.Resources.Extensions dependency and
the preserialized-resources workaround.
Assisted-by: Claude:claude-opus-4-8:Claude Code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Migrates the Visual Studio extension to a true SDK-style VSIX so it builds with plain
dotnet buildinstead of fullmsbuild, retires the obsolete VS2017/2019 add-in, and moves the VS-extensions solution to.slnxwith CIbuilding it via
dotnet build.The end state: one SDK-style extension project (
ILSpy.AddIn.VS2022), a shared code project, and a singleILSpy.VSExtensions.slnxthat builds end-to-end withdotnet build— no Visual Studio / full-msbuilddependency in the build.Statistics for Retirement
2017-2019 extension
2022-2026 extension
Of interest are only the in-IDE downloads, and that translates to ~ 150/month for 2017-2019 with almost a 20 times higher number for 2022-206.
Changes and why
1.
ILSpy.AddIn.VS2022-> true SDK-style VSIX<Project Sdk="Microsoft.NET.Sdk">, dropping the hybrid explicitSdk.props/Sdk.targetsimports and the legacyMicrosoft.VsSDK.targetsimport. Added the VSIX propertiesVSSDKBuildToolsAutoSetup,VsixDeployOnDebug,GeneratePkgDefFileand theCreateVsixContainerproject capability.Why: the legacy
Microsoft.VsSDK.targetsimport is what forced fullmsbuild.VSSDKBuildToolsAutoSetup+CreateVsixContaineris the Microsoft-recommended SDK-style replacement and is what letsdotnet buildemit the
.vsix.Microsoft.VSSDK.BuildToolsbumped to18.5.40034and simplified toPrivateAssets=all;ExcludeAssets="runtime"added toMicrosoft.VisualStudio.SDK.Why: 18.5 is the floor for the auto-setup; the SDK metapackage's runtime assemblies are provided by VS, so they should not be copied locally.
GenerateResourceUsePreserializedResources=true+ aSystem.Resources.Extensionsreference.Why:
VSPackage.resxresource400is the Help/About package icon ([InstalledProductRegistration(..., IconResourceID = 400)]), stored as a binarySystem.Drawing.Icon. The dotnet CLIGenerateResourcetask cannotBinaryFormatter-serialize it the way fullmsbuilddoes (it fails with MSB3823/MSB3822), so the resource must be emitted viaSystem.Resources.Extensionsinstead.MergeWithCTOturned off for the package resources (per-project override, leaving the shared.resxuntouched).Why: the VSSDK CTO merger reads
VSPackage.resourceswith the classic reader and rejects the preserialized format. Modern SDK-style VSIX projects do not merge:VSCTCompilealready embedsMenus.ctmenuas its own resource,which is how
ProvideMenuResourcelocates the menus.System.Designreference.Why: the shared command classes use
MenuCommandService, which lives inSystem.Design. Fullmsbuildsupplied it implicitly; the SDK does not add it fornet472.2. Retire the VS2017/2019 add-in (
ILSpy.AddIn)ILSpy.AddInproject and everything that fed it: its solution entries, its VSIX-manifest template generation inBuildTools/update-assemblyinfo.ps1, the committedBuildTools/ILSpy.AddIn.vsix.filelistsnapshot, the now-dead..\ILSpy.AddIn\*.resxglob inILSpy/ILSpy.csproj, and the CI build-step rename plus the VS2017/2019 VSIX artifact-upload step.Why: it pinned
Microsoft.VisualStudio.SDK15.0.1 / Roslyn 2.4.0, was the last project that could only be built with fullmsbuild, and is obsolete now that the VS2022 add-in is the supported integration. Removing it is what makesthe whole solution
dotnet build-able.VSPackage.resxpackage-icon path from the deleted..\ILSpy.AddIn\Resources\Package.icoto the byte-identical copy under..\ILSpy.AddIn.VS2022\Resources\Package.ico(verified identical by git blob hash).3. Solution ->
.slnx, CI ->dotnet buildILSpy.VSExtensions.slnwithILSpy.VSExtensions.slnx(generated bydotnet sln migrate), carrying a<Deploy Solution="Debug|Any CPU" />entry on the VS2022 project for F5 deploy in VS 18.5+.build-ilspy.yml) now runsdotnet build ILSpy.VSExtensions.slnx -c Releaseinstead of twomsbuild ILSpy.VSExtensions.slninvocations..sln->.slnxreferences inREADME.mdandCLAUDE.md.Verification
dotnet build ILSpy.VSExtensions.slnx -c Releasesucceeds (0 warnings, 0 errors) and producesILSpy.AddIn.VS2022.vsix(~43 MB) containing the ILSpy distribution for bothx64andarm64(incl.ILSpy.exe), with the packagemanifest version intact.
packages.lock.jsonunchanged (no churn).dotnet buildonly; fullmsbuildis no longer required.References
CreateVsixContainercapability, and the<Deploy>slnx entry).CommandTableInfoconfirmed the "noMergeWithCTO,VSCTCompileemitsMenus.ctmenudirectly" pattern).GenerateResourceUsePreserializedResources+System.Resources.Extensionsremedy for the MSB3823/MSB3822 non-string resource error under the dotnet CLI.Downsides / things to watch
System.Resources.Extensions. That assembly is intentionally not in the VSIX (the VSSDK excludes assemblies VS itself ships), so the read relies on VS providing it — true for VS 2022, but a dependency on VS internals.Menus.ctmenuresource (after droppingMergeWithCTO).packages.lock.jsonchurn from the toolchain. Regenerating the lock for the BuildTools bump (on the net11-preview SDK) also droppedMicrosoft.NETFramework.ReferenceAssemblies(resolved from the installed targeting pack instead). The project is not in locked-restore mode, so this is tolerated; CI restores fresh.ILSpy.AddIn.Sharedis used only by VS2022, and itsVSPackage.resxreferences an icon in that sibling project. Inlining the shared project intoILSpy.AddIn.VS2022is a reasonable future cleanup, left out here to keep the change scoped.