Skip to content

Commit 7fb5f08

Browse files
committed
Add COM workaround
1 parent 6adf982 commit 7fb5f08

File tree

1 file changed

+34
-26
lines changed

1 file changed

+34
-26
lines changed

src/Cli/dotnet/commands/dotnet-workload/list/VisualStudioWorkloads.cs

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ namespace Microsoft.DotNet.Workloads.Workload
2020
#endif
2121
internal static class VisualStudioWorkloads
2222
{
23+
private static readonly object s_guard = new();
24+
2325
private const int REGDB_E_CLASSNOTREG = unchecked((int)0x80040154);
2426

2527
/// <summary>
@@ -158,44 +160,50 @@ internal static void WriteSDKInstallRecordsForVSWorkloads(IInstaller workloadIns
158160
/// <returns>A list of Visual Studio instances.</returns>
159161
private static List<ISetupInstance> GetVisualStudioInstances()
160162
{
161-
List<ISetupInstance> vsInstances = new();
162-
163-
try
163+
// The underlying COM API has a bug where-by it's not safe for concurrent calls. Until their
164+
// bug fix is rolled out use a lock to ensure we don't concurrently access this API.
165+
// https://dev.azure.com/devdiv/DevDiv/_workitems/edit/2241752/
166+
lock (s_guard)
164167
{
165-
SetupConfiguration setupConfiguration = new();
166-
ISetupConfiguration2 setupConfiguration2 = setupConfiguration;
167-
IEnumSetupInstances setupInstances = setupConfiguration2.EnumInstances();
168-
ISetupInstance[] instances = new ISetupInstance[1];
169-
int fetched = 0;
168+
List<ISetupInstance> vsInstances = new();
170169

171-
do
170+
try
172171
{
173-
setupInstances.Next(1, instances, out fetched);
172+
SetupConfiguration setupConfiguration = new();
173+
ISetupConfiguration2 setupConfiguration2 = setupConfiguration;
174+
IEnumSetupInstances setupInstances = setupConfiguration2.EnumInstances();
175+
ISetupInstance[] instances = new ISetupInstance[1];
176+
int fetched = 0;
174177

175-
if (fetched > 0)
178+
do
176179
{
177-
ISetupInstance2 instance = (ISetupInstance2)instances[0];
180+
setupInstances.Next(1, instances, out fetched);
178181

179-
// .NET Workloads only shipped in 17.0 and later and we should only look at IDE based SKUs
180-
// such as community, professional, and enterprise.
181-
if (Version.TryParse(instance.GetInstallationVersion(), out Version version) &&
182-
version.Major >= 17 &&
183-
s_visualStudioProducts.Contains(instance.GetProduct().GetId()))
182+
if (fetched > 0)
184183
{
185-
vsInstances.Add(instances[0]);
184+
ISetupInstance2 instance = (ISetupInstance2)instances[0];
185+
186+
// .NET Workloads only shipped in 17.0 and later and we should only look at IDE based SKUs
187+
// such as community, professional, and enterprise.
188+
if (Version.TryParse(instance.GetInstallationVersion(), out Version version) &&
189+
version.Major >= 17 &&
190+
s_visualStudioProducts.Contains(instance.GetProduct().GetId()))
191+
{
192+
vsInstances.Add(instances[0]);
193+
}
186194
}
187195
}
196+
while (fetched > 0);
197+
198+
}
199+
catch (COMException e) when (e.ErrorCode == REGDB_E_CLASSNOTREG)
200+
{
201+
// Query API not registered, good indication there are no VS installations of 15.0 or later.
202+
// Other exceptions are passed through since that likely points to a real error.
188203
}
189-
while (fetched > 0);
190204

205+
return vsInstances;
191206
}
192-
catch (COMException e) when (e.ErrorCode == REGDB_E_CLASSNOTREG)
193-
{
194-
// Query API not registered, good indication there are no VS installations of 15.0 or later.
195-
// Other exceptions are passed through since that likely points to a real error.
196-
}
197-
198-
return vsInstances;
199207
}
200208
}
201209
}

0 commit comments

Comments
 (0)