@@ -62,7 +62,7 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
6262 try
6363 {
6464 this . dotnet = DotNet . Make ( options , logger , tempWorkingDirectory ) ;
65- runtimeLazy = new Lazy < Runtime > ( ( ) => new Runtime ( dotnet ) ) ;
65+ runtimeLazy = new Lazy < Runtime > ( ( ) => new Runtime ( dotnet , logger ) ) ;
6666 }
6767 catch
6868 {
@@ -112,7 +112,7 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
112112 logger . LogInfo ( $ "Unresolved reference { r . Key } in project { r . Value } ") ;
113113 }
114114
115- var webViewExtractionOption = Environment . GetEnvironmentVariable ( "CODEQL_EXTRACTOR_CSHARP_STANDALONE_EXTRACT_WEB_VIEWS" ) ;
115+ var webViewExtractionOption = Environment . GetEnvironmentVariable ( EnvironmentVariableNames . WebViewGeneration ) ;
116116 if ( webViewExtractionOption == null ||
117117 bool . TryParse ( webViewExtractionOption , out var shouldExtractWebViews ) &&
118118 shouldExtractWebViews )
@@ -159,6 +159,53 @@ private HashSet<string> AddFrameworkDlls(HashSet<string> dllPaths)
159159 {
160160 var frameworkLocations = new HashSet < string > ( ) ;
161161
162+ var frameworkReferences = Environment . GetEnvironmentVariable ( EnvironmentVariableNames . DotnetFrameworkReferences ) ;
163+ var frameworkReferencesUseSubfolders = Environment . GetEnvironmentVariable ( EnvironmentVariableNames . DotnetFrameworkReferencesUseSubfolders ) ;
164+ _ = bool . TryParse ( frameworkReferencesUseSubfolders , out var useSubfolders ) ;
165+ if ( ! string . IsNullOrWhiteSpace ( frameworkReferences ) )
166+ {
167+ RemoveFrameworkNugetPackages ( dllPaths ) ;
168+ RemoveNugetPackageReference ( FrameworkPackageNames . AspNetCoreFramework , dllPaths ) ;
169+ RemoveNugetPackageReference ( FrameworkPackageNames . WindowsDesktopFramework , dllPaths ) ;
170+
171+ var frameworkPaths = frameworkReferences . Split ( Path . PathSeparator , StringSplitOptions . RemoveEmptyEntries ) ;
172+
173+ foreach ( var path in frameworkPaths )
174+ {
175+ if ( ! Directory . Exists ( path ) )
176+ {
177+ logger . LogError ( $ "Specified framework reference path '{ path } ' does not exist.") ;
178+ continue ;
179+ }
180+
181+ if ( useSubfolders )
182+ {
183+ dllPaths . Add ( path ) ;
184+ frameworkLocations . Add ( path ) ;
185+ continue ;
186+ }
187+
188+ try
189+ {
190+ var dlls = Directory . GetFiles ( path , "*.dll" , new EnumerationOptions { RecurseSubdirectories = false , MatchCasing = MatchCasing . CaseInsensitive } ) ;
191+ if ( dlls . Length == 0 )
192+ {
193+ logger . LogError ( $ "No DLLs found in specified framework reference path '{ path } '.") ;
194+ continue ;
195+ }
196+
197+ dllPaths . UnionWith ( dlls ) ;
198+ frameworkLocations . UnionWith ( dlls ) ;
199+ }
200+ catch ( Exception e )
201+ {
202+ logger . LogError ( $ "Error while searching for DLLs in '{ path } ': { e . Message } ") ;
203+ }
204+ }
205+
206+ return frameworkLocations ;
207+ }
208+
162209 AddNetFrameworkDlls ( dllPaths , frameworkLocations ) ;
163210 AddAspNetCoreFrameworkDlls ( dllPaths , frameworkLocations ) ;
164211 AddMicrosoftWindowsDesktopDlls ( dllPaths , frameworkLocations ) ;
@@ -204,9 +251,9 @@ private void RestoreNugetPackages(List<FileInfo> allNonBinaryFiles, IEnumerable<
204251 nugetPackageDllPaths . ExceptWith ( excludedPaths ) ;
205252 dllPaths . UnionWith ( nugetPackageDllPaths ) ;
206253 }
207- catch ( Exception )
254+ catch ( Exception exc )
208255 {
209- logger . LogError ( "Failed to restore Nuget packages with nuget.exe" ) ;
256+ logger . LogError ( $ "Failed to restore Nuget packages with nuget.exe: { exc . Message } ") ;
210257 }
211258
212259 var restoredProjects = RestoreSolutions ( allSolutions , out var assets1 ) ;
@@ -297,14 +344,23 @@ private static DirectoryInfo[] GetPackageVersionSubDirectories(string packagePat
297344 . ToArray ( ) ;
298345 }
299346
347+ private void RemoveFrameworkNugetPackages ( ISet < string > dllPaths , int fromIndex = 0 )
348+ {
349+ var packagesInPrioOrder = FrameworkPackageNames . NetFrameworks ;
350+ for ( var i = fromIndex ; i < packagesInPrioOrder . Length ; i ++ )
351+ {
352+ RemoveNugetPackageReference ( packagesInPrioOrder [ i ] , dllPaths ) ;
353+ }
354+ }
355+
300356 private void AddNetFrameworkDlls ( ISet < string > dllPaths , ISet < string > frameworkLocations )
301357 {
302358 // Multiple dotnet framework packages could be present.
303359 // The order of the packages is important, we're adding the first one that is present in the nuget cache.
304360 var packagesInPrioOrder = FrameworkPackageNames . NetFrameworks ;
305361
306362 var frameworkPaths = packagesInPrioOrder
307- . Select ( ( s , index ) => ( Index : index , Path : GetPackageDirectory ( s ) ) )
363+ . Select ( ( s , index ) => ( Index : index , Path : GetPackageDirectory ( s , packageDirectory ) ) )
308364 . Where ( pair => pair . Path is not null )
309365 . ToArray ( ) ;
310366
@@ -318,12 +374,7 @@ private void AddNetFrameworkDlls(ISet<string> dllPaths, ISet<string> frameworkLo
318374 }
319375
320376 SelectNewestFrameworkPath ( frameworkPath . Path , ".NET Framework" , dllPaths , frameworkLocations ) ;
321-
322- for ( var i = frameworkPath . Index + 1 ; i < packagesInPrioOrder . Length ; i ++ )
323- {
324- RemoveNugetPackageReference ( packagesInPrioOrder [ i ] , dllPaths ) ;
325- }
326-
377+ RemoveFrameworkNugetPackages ( dllPaths , frameworkPath . Index + 1 ) ;
327378 return ;
328379 }
329380
@@ -336,6 +387,16 @@ private void AddNetFrameworkDlls(ISet<string> dllPaths, ISet<string> frameworkLo
336387 else if ( fileContent . IsLegacyProjectStructureUsed )
337388 {
338389 runtimeLocation = Runtime . DesktopRuntime ;
390+
391+ if ( runtimeLocation is null )
392+ {
393+ logger . LogInfo ( "No .NET Desktop Runtime location found. Attempting to restore the .NET Framework reference assemblies manually." ) ;
394+
395+ if ( TryRestorePackageManually ( FrameworkPackageNames . LatestNetFrameworkReferenceAssemblies , null ) )
396+ {
397+ runtimeLocation = GetPackageDirectory ( FrameworkPackageNames . LatestNetFrameworkReferenceAssemblies , missingPackageDirectory ) ;
398+ }
399+ }
339400 }
340401
341402 runtimeLocation ??= Runtime . ExecutingRuntime ;
@@ -375,7 +436,7 @@ private void AddAspNetCoreFrameworkDlls(ISet<string> dllPaths, ISet<string> fram
375436 }
376437
377438 // First try to find ASP.NET Core assemblies in the NuGet packages
378- if ( GetPackageDirectory ( FrameworkPackageNames . AspNetCoreFramework ) is string aspNetCorePackage )
439+ if ( GetPackageDirectory ( FrameworkPackageNames . AspNetCoreFramework , packageDirectory ) is string aspNetCorePackage )
379440 {
380441 SelectNewestFrameworkPath ( aspNetCorePackage , "ASP.NET Core" , dllPaths , frameworkLocations ) ;
381442 return ;
@@ -391,15 +452,15 @@ private void AddAspNetCoreFrameworkDlls(ISet<string> dllPaths, ISet<string> fram
391452
392453 private void AddMicrosoftWindowsDesktopDlls ( ISet < string > dllPaths , ISet < string > frameworkLocations )
393454 {
394- if ( GetPackageDirectory ( FrameworkPackageNames . WindowsDesktopFramework ) is string windowsDesktopApp )
455+ if ( GetPackageDirectory ( FrameworkPackageNames . WindowsDesktopFramework , packageDirectory ) is string windowsDesktopApp )
395456 {
396457 SelectNewestFrameworkPath ( windowsDesktopApp , "Windows Desktop App" , dllPaths , frameworkLocations ) ;
397458 }
398459 }
399460
400- private string ? GetPackageDirectory ( string packagePrefix )
461+ private string ? GetPackageDirectory ( string packagePrefix , TemporaryDirectory root )
401462 {
402- return new DirectoryInfo ( packageDirectory . DirInfo . FullName )
463+ return new DirectoryInfo ( root . DirInfo . FullName )
403464 . EnumerateDirectories ( packagePrefix + "*" , new EnumerationOptions { MatchCasing = MatchCasing . CaseInsensitive , RecurseSubdirectories = false } )
404465 . FirstOrDefault ( ) ?
405466 . FullName ;
@@ -435,19 +496,19 @@ private void GenerateSourceFileFromImplicitUsings()
435496 }
436497
437498 // Hardcoded values from https://learn.microsoft.com/en-us/dotnet/core/project-sdk/overview#implicit-using-directives
438- usings . UnionWith ( new [ ] { "System" , "System.Collections.Generic" , "System.IO" , "System.Linq" , "System.Net.Http" , "System.Threading" ,
439- "System.Threading.Tasks" } ) ;
499+ usings . UnionWith ( [ "System" , "System.Collections.Generic" , "System.IO" , "System.Linq" , "System.Net.Http" , "System.Threading" ,
500+ "System.Threading.Tasks" ] ) ;
440501
441502 if ( fileContent . UseAspNetCoreDlls )
442503 {
443- usings . UnionWith ( new [ ] { "System.Net.Http.Json" , "Microsoft.AspNetCore.Builder" , "Microsoft.AspNetCore.Hosting" ,
504+ usings . UnionWith ( [ "System.Net.Http.Json" , "Microsoft.AspNetCore.Builder" , "Microsoft.AspNetCore.Hosting" ,
444505 "Microsoft.AspNetCore.Http" , "Microsoft.AspNetCore.Routing" , "Microsoft.Extensions.Configuration" ,
445- "Microsoft.Extensions.DependencyInjection" , "Microsoft.Extensions.Hosting" , "Microsoft.Extensions.Logging" } ) ;
506+ "Microsoft.Extensions.DependencyInjection" , "Microsoft.Extensions.Hosting" , "Microsoft.Extensions.Logging" ] ) ;
446507 }
447508
448509 if ( fileContent . UseWindowsForms )
449510 {
450- usings . UnionWith ( new [ ] { "System.Drawing" , "System.Windows.Forms" } ) ;
511+ usings . UnionWith ( [ "System.Drawing" , "System.Windows.Forms" ] ) ;
451512 }
452513
453514 usings . UnionWith ( fileContent . CustomImplicitUsings ) ;
@@ -869,47 +930,58 @@ private void DownloadMissingPackages(List<FileInfo> allFiles, ISet<string> dllPa
869930
870931 Parallel . ForEach ( notYetDownloadedPackages , new ParallelOptions { MaxDegreeOfParallelism = options . Threads } , package =>
871932 {
872- logger . LogInfo ( $ "Restoring package { package } ...") ;
873- using var tempDir = new TemporaryDirectory ( ComputeTempDirectory ( package , "missingpackages_workingdir" ) ) ;
874- var success = dotnet . New ( tempDir . DirInfo . FullName ) ;
933+ var success = TryRestorePackageManually ( package , nugetConfig ) ;
875934 if ( ! success )
876935 {
877936 return ;
878937 }
879938
880- success = dotnet . AddPackage ( tempDir . DirInfo . FullName , package ) ;
881- if ( ! success )
939+ lock ( sync )
882940 {
883- return ;
941+ successCount ++ ;
884942 }
943+ } ) ;
885944
886- var res = dotnet . Restore ( new ( tempDir . DirInfo . FullName , missingPackageDirectory . DirInfo . FullName , ForceDotnetRefAssemblyFetching : false , PathToNugetConfig : nugetConfig ) ) ;
887- if ( ! res . Success )
888- {
889- if ( res . HasNugetPackageSourceError )
890- {
891- // Restore could not be completed because the listed source is unavailable. Try without the nuget.config:
892- res = dotnet . Restore ( new ( tempDir . DirInfo . FullName , missingPackageDirectory . DirInfo . FullName , ForceDotnetRefAssemblyFetching : false , PathToNugetConfig : null , ForceReevaluation : true ) ) ;
893- }
945+ CompilationInfos . Add ( ( "Successfully ran fallback nuget restore" , successCount . ToString ( ) ) ) ;
894946
895- // TODO: the restore might fail, we could retry with a prerelease (*-* instead of *) version of the package.
947+ dllPaths . Add ( missingPackageDirectory . DirInfo . FullName ) ;
948+ }
896949
897- if ( ! res . Success )
898- {
899- logger . LogInfo ( $ "Failed to restore nuget package { package } ") ;
900- return ;
901- }
902- }
950+ private bool TryRestorePackageManually ( string package , string ? nugetConfig )
951+ {
952+ logger . LogInfo ( $ "Restoring package { package } ...") ;
953+ using var tempDir = new TemporaryDirectory ( ComputeTempDirectory ( package , "missingpackages_workingdir" ) ) ;
954+ var success = dotnet . New ( tempDir . DirInfo . FullName ) ;
955+ if ( ! success )
956+ {
957+ return false ;
958+ }
903959
904- lock ( sync )
960+ success = dotnet . AddPackage ( tempDir . DirInfo . FullName , package ) ;
961+ if ( ! success )
962+ {
963+ return false ;
964+ }
965+
966+ var res = dotnet . Restore ( new ( tempDir . DirInfo . FullName , missingPackageDirectory . DirInfo . FullName , ForceDotnetRefAssemblyFetching : false , PathToNugetConfig : nugetConfig ) ) ;
967+ if ( ! res . Success )
968+ {
969+ if ( res . HasNugetPackageSourceError && nugetConfig is not null )
905970 {
906- successCount ++ ;
971+ // Restore could not be completed because the listed source is unavailable. Try without the nuget.config:
972+ res = dotnet . Restore ( new ( tempDir . DirInfo . FullName , missingPackageDirectory . DirInfo . FullName , ForceDotnetRefAssemblyFetching : false , PathToNugetConfig : null , ForceReevaluation : true ) ) ;
907973 }
908- } ) ;
909974
910- CompilationInfos . Add ( ( "Successfully ran fallback nuget restore" , successCount . ToString ( ) ) ) ;
975+ // TODO: the restore might fail, we could retry with a prerelease (*-* instead of *) version of the package.
911976
912- dllPaths . Add ( missingPackageDirectory . DirInfo . FullName ) ;
977+ if ( ! res . Success )
978+ {
979+ logger . LogInfo ( $ "Failed to restore nuget package { package } ") ;
980+ return false ;
981+ }
982+ }
983+
984+ return true ;
913985 }
914986
915987 public void Dispose ( TemporaryDirectory ? dir , string name )
0 commit comments