@@ -19,6 +19,8 @@ namespace Microsoft.DotNet.Workloads.Workload
19
19
#endif
20
20
internal static class VisualStudioWorkloads
21
21
{
22
+ private static readonly object s_guard = new ( ) ;
23
+
22
24
private const int REGDB_E_CLASSNOTREG = unchecked ( ( int ) 0x80040154 ) ;
23
25
24
26
/// <summary>
@@ -204,44 +206,50 @@ internal static IEnumerable<WorkloadId> WriteSDKInstallRecordsForVSWorkloads(IIn
204
206
/// <returns>A list of Visual Studio instances.</returns>
205
207
private static List < ISetupInstance > GetVisualStudioInstances ( )
206
208
{
207
- List < ISetupInstance > vsInstances = new ( ) ;
208
-
209
- try
209
+ // The underlying COM API has a bug where-by it's not safe for concurrent calls. Until their
210
+ // bug fix is rolled out use a lock to ensure we don't concurrently access this API.
211
+ // https://dev.azure.com/devdiv/DevDiv/_workitems/edit/2241752/
212
+ lock ( s_guard )
210
213
{
211
- SetupConfiguration setupConfiguration = new ( ) ;
212
- ISetupConfiguration2 setupConfiguration2 = setupConfiguration ;
213
- IEnumSetupInstances setupInstances = setupConfiguration2 . EnumInstances ( ) ;
214
- ISetupInstance [ ] instances = new ISetupInstance [ 1 ] ;
215
- int fetched = 0 ;
214
+ List < ISetupInstance > vsInstances = new ( ) ;
216
215
217
- do
216
+ try
218
217
{
219
- setupInstances . Next ( 1 , instances , out fetched ) ;
218
+ SetupConfiguration setupConfiguration = new ( ) ;
219
+ ISetupConfiguration2 setupConfiguration2 = setupConfiguration ;
220
+ IEnumSetupInstances setupInstances = setupConfiguration2 . EnumInstances ( ) ;
221
+ ISetupInstance [ ] instances = new ISetupInstance [ 1 ] ;
222
+ int fetched = 0 ;
220
223
221
- if ( fetched > 0 )
224
+ do
222
225
{
223
- ISetupInstance2 instance = ( ISetupInstance2 ) instances [ 0 ] ;
226
+ setupInstances . Next ( 1 , instances , out fetched ) ;
224
227
225
- // .NET Workloads only shipped in 17.0 and later and we should only look at IDE based SKUs
226
- // such as community, professional, and enterprise.
227
- if ( Version . TryParse ( instance . GetInstallationVersion ( ) , out Version version ) &&
228
- version . Major >= 17 &&
229
- s_visualStudioProducts . Contains ( instance . GetProduct ( ) . GetId ( ) ) )
228
+ if ( fetched > 0 )
230
229
{
231
- vsInstances . Add ( instances [ 0 ] ) ;
230
+ ISetupInstance2 instance = ( ISetupInstance2 ) instances [ 0 ] ;
231
+
232
+ // .NET Workloads only shipped in 17.0 and later and we should only look at IDE based SKUs
233
+ // such as community, professional, and enterprise.
234
+ if ( Version . TryParse ( instance . GetInstallationVersion ( ) , out Version version ) &&
235
+ version . Major >= 17 &&
236
+ s_visualStudioProducts . Contains ( instance . GetProduct ( ) . GetId ( ) ) )
237
+ {
238
+ vsInstances . Add ( instances [ 0 ] ) ;
239
+ }
232
240
}
233
241
}
242
+ while ( fetched > 0 ) ;
243
+
244
+ }
245
+ catch ( COMException e ) when ( e . ErrorCode == REGDB_E_CLASSNOTREG )
246
+ {
247
+ // Query API not registered, good indication there are no VS installations of 15.0 or later.
248
+ // Other exceptions are passed through since that likely points to a real error.
234
249
}
235
- while ( fetched > 0 ) ;
236
250
251
+ return vsInstances ;
237
252
}
238
- catch ( COMException e ) when ( e . ErrorCode == REGDB_E_CLASSNOTREG )
239
- {
240
- // Query API not registered, good indication there are no VS installations of 15.0 or later.
241
- // Other exceptions are passed through since that likely points to a real error.
242
- }
243
-
244
- return vsInstances ;
245
253
}
246
254
}
247
255
}
0 commit comments