Skip to content

Commit e12d66f

Browse files
lukkaloop8ack
authored andcommitted
Prevent StackOverflow exceptions in Visual Studio 2026 for users who have ExtensionManager installed: fixed the assembly resolver to prevent recursion and version mismatches.
1 parent edaa5cb commit e12d66f

2 files changed

Lines changed: 36 additions & 7 deletions

File tree

src/ExtensionManager.Manifest/ExtensionManager.Manifest.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<PackageReference Include="Nullable" Version="1.3.1" PrivateAssets="all" />
55
<PackageReference Include="IsExternalInit" Version="1.0.3" PrivateAssets="all" />
66
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
7-
<PackageReference Include="System.Text.Json" Version="8.0.4" />
7+
<PackageReference Include="System.Text.Json" Version="8.0.5" />
88
</ItemGroup>
99

1010
<ItemGroup>

src/ExtensionManager.Vsix.Shared/ExtensionManagerPackage.cs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,18 +127,47 @@ async void OnHandleCommand(object sender, EventArgs e)
127127

128128
file static class AssemblyResolver
129129
{
130+
[ThreadStatic]
131+
private static int _nestingCount;
132+
130133
public static void Initialize()
131134
=> AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
132135

133136
private static Assembly? OnAssemblyResolve(object sender, ResolveEventArgs e)
134137
{
135-
var assemblyName = new AssemblyName(e.Name).Name;
136-
var currentFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
137-
var assemblyPath = Path.Combine(currentFolder, assemblyName + ".dll");
138+
// Prevent infinite recursion by checking if we're already inside this resolver
139+
if (_nestingCount > 0)
140+
return null;
138141

139-
if (File.Exists(assemblyPath))
140-
return Assembly.LoadFile(assemblyPath);
142+
_nestingCount++;
143+
try
144+
{
145+
var requestedAssembly = new AssemblyName(e.Name);
146+
var assemblyName = requestedAssembly.Name;
147+
var currentFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
148+
var assemblyPath = Path.Combine(currentFolder, assemblyName + ".dll");
141149

142-
return null;
150+
if (!File.Exists(assemblyPath))
151+
return null;
152+
153+
var onDiskAssembly = AssemblyName.GetAssemblyName(assemblyPath);
154+
155+
// Only load if versions match - return null if they don't to allow other resolvers to try
156+
if (requestedAssembly.Version != null &&
157+
onDiskAssembly.Version != requestedAssembly.Version)
158+
return null;
159+
160+
return Assembly.LoadFile(assemblyPath);
161+
}
162+
catch
163+
{
164+
// Swallow all exceptions and return null to allow other resolvers to try
165+
// or to let the CLR handle the failure in the standard way
166+
return null;
167+
}
168+
finally
169+
{
170+
_nestingCount--;
171+
}
143172
}
144173
}

0 commit comments

Comments
 (0)