Skip to content

Commit

Permalink
Load NuGet assemblies (#115)
Browse files Browse the repository at this point in the history
Adds an overload to permit supplying additional paths in which to search for MSBuild assemblies beyond the default.

Uses this new overload to add the search path for NuGet assemblies for when in a VS install.

The latter fixes #86.
  • Loading branch information
Forgind authored Jan 6, 2021
1 parent 4e519a9 commit d007e5e
Showing 1 changed file with 48 additions and 9 deletions.
57 changes: 48 additions & 9 deletions src/MSBuildLocator/MSBuildLocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,50 @@ public static void RegisterInstance(VisualStudioInstance instance)
/// </param>
public static void RegisterMSBuildPath(string msbuildPath)
{
if (string.IsNullOrWhiteSpace(msbuildPath))
RegisterMSBuildPath(new string[] {
msbuildPath
#if NET46
// Finds and loads NuGet assemblies if msbuildPath is in a VS installation
, Path.GetFullPath(Path.Combine(msbuildPath, "..", "..", "..", "Common7", "IDE", "CommonExtensions", "Microsoft", "NuGet"))
#endif
});
}

/// <summary>
/// Add assembly resolution for Microsoft.Build core dlls in the current AppDomain from the specified
/// path.
/// </summary>
/// <param name="msbuildSearchPaths">
/// Paths to directories containing a deployment of MSBuild binaries.
/// A minimal MSBuild deployment would be the publish result of the Microsoft.Build.Runtime package.
///
/// In order to restore and build real projects, one needs a deployment that contains the rest of the toolchain (nuget, compilers, etc.).
/// Such deployments can be found in installations such as Visual Studio or dotnet CLI.
/// </param>
public static void RegisterMSBuildPath(string[] msbuildSearchPaths)
{
if (msbuildSearchPaths.Length < 1)
{
throw new ArgumentException("Value may not be null or whitespace", nameof(msbuildPath));
throw new ArgumentException("Must provide at least one search path to RegisterMSBuildPath.");
}

if (!Directory.Exists(msbuildPath))
List<ArgumentException> nullOrWhiteSpaceExceptions = new List<ArgumentException>();
for (int i = 0; i < msbuildSearchPaths.Length; i++)
{
throw new ArgumentException($"Directory \"{msbuildPath}\" does not exist", nameof(msbuildPath));
if (string.IsNullOrWhiteSpace(msbuildSearchPaths[i]))
{
nullOrWhiteSpaceExceptions.Add(new ArgumentException($"Value at position {i+1} may not be null or whitespace", nameof(msbuildSearchPaths)));
}
}
if (nullOrWhiteSpaceExceptions.Count > 0)
{
throw new AggregateException("Search paths for MSBuild assemblies cannot be null and must contain non-whitespace characters.", nullOrWhiteSpaceExceptions);
}

IEnumerable<string> paths = msbuildSearchPaths.Where(path => !Directory.Exists(path));
if (paths.FirstOrDefault() == null)
{
throw new AggregateException($"A directory or directories in \"{nameof(msbuildSearchPaths)}\" do not exist", paths.Select(path => new ArgumentException($"Directory \"{path}\" does not exist", nameof(msbuildSearchPaths))));
}

if (!CanRegister)
Expand Down Expand Up @@ -202,12 +238,15 @@ Assembly TryLoadAssembly(AssemblyName assemblyName)

// Look in the MSBuild folder for any unresolved reference. It may be a dependency
// of MSBuild or a task.
string targetAssembly = Path.Combine(msbuildPath, assemblyName.Name + ".dll");
if (File.Exists(targetAssembly))
foreach (string msbuildPath in msbuildSearchPaths)
{
assembly = Assembly.LoadFrom(targetAssembly);
loadedAssemblies.Add(assemblyName.FullName, assembly);
return assembly;
string targetAssembly = Path.Combine(msbuildPath, assemblyName.Name + ".dll");
if (File.Exists(targetAssembly))
{
assembly = Assembly.LoadFrom(targetAssembly);
loadedAssemblies.Add(assemblyName.FullName, assembly);
return assembly;
}
}

return null;
Expand Down

0 comments on commit d007e5e

Please sign in to comment.