Programmatically Resolve Assembly Name to Full Path the Same Way MSBuild Does

Jomo Fisher—Every once in a while I find I need to turn and assembly name like “System” or “System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL” into a path to the actual file for that assembly. This is a tricky problem considering the assembly name might be for a product install in Program Files or elsewhere. MSBuild already has rules for doing this resolution. Here’s how to call that code directly (written in F#):

#light

#r "c:\Windows\Microsoft.NET\Framework\v2.0.50727\Microsoft.Build.Tasks.dll"

#r "c:\Windows\Microsoft.NET\Framework\v2.0.50727\Microsoft.Build.Utilities.dll"

#r "c:\Windows\Microsoft.NET\Framework\v2.0.50727\Microsoft.Build.Framework.dll"

#r "c:\Windows\Microsoft.NET\Framework\v2.0.50727\Microsoft.Build.Engine.dll"

open Microsoft.Build.Tasks

open Microsoft.Build.Utilities

open Microsoft.Build.Framework

open Microsoft.Build.BuildEngine

/// Reference resolution results. All paths are fully qualified.

type ResolutionResults = {

    /// Paths to primary references

    referencePaths:string array

    /// Paths to dependencies

    referenceDependencyPaths:string array

    /// Paths to related files (like .xml and .pdb)

    relatedPaths:string array

    /// Paths to satellite assemblies used for localization.

    referenceSatellitePaths:string array

    /// Additional files required to support multi-file assemblies.

    referenceScatterPaths:string array

    /// Paths to files that reference resolution recommend be copied to the local directory

    referenceCopyLocalPaths:string array

    /// Binding redirects that reference resolution recommends for the app.config file.

    suggestedBindingRedirects:string array

    }

let Resolve(references:string array, outputDirectory:string) =

    let x = { new IBuildEngine with

                member be.BuildProjectFile(projectFileName, targetNames, globalProperties, argetOutputs) = true

                member be.LogCustomEvent(e) = ()

                member be.LogErrorEvent(e) = ()

                member be.LogMessageEvent(e) = ()

                member be.LogWarningEvent(e) = ()

                member be.ColumnNumberOfTaskNode with get() = 1

                member be.ContinueOnError with get() = true

                member be.LineNumberOfTaskNode with get() = 1

                member be.ProjectFileOfTaskNode with get() = "" }

    let rar = new ResolveAssemblyReference()

    rar.BuildEngine <- x

    rar.TargetFrameworkDirectories <- [|@"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\"|]

    rar.AllowedRelatedFileExtensions <- [| ".pdb"; ".xml"; ".optdata" |]

    rar.FindRelatedFiles <- true

    rar.Assemblies <- [|for r in references -> new Microsoft.Build.Utilities.TaskItem(r):>ITaskItem|]

    rar.SearchPaths <- [| "{CandidateAssemblyFiles}"

                          "{HintPathFromItem}"

                          "{TargetFrameworkDirectory}"

                          "{Registry:Software\Microsoft\.NetFramework,v3.5,AssemblyFoldersEx}"

                          "{AssemblyFolders}"

   "{GAC}"

                          "{RawFileName}"

                          outputDirectory |]

                             

    rar.AllowedAssemblyExtensions <- [| ".exe"; ".dll" |]

    rar.TargetProcessorArchitecture <- "x86"

    if not (rar.Execute()) then

        failwith "Could not resolve"

    {

        referencePaths = [| for p in rar.ResolvedFiles -> p.ItemSpec |]

        referenceDependencyPaths = [| for p in rar.ResolvedDependencyFiles -> p.ItemSpec |]

        relatedPaths = [| for p in rar.RelatedFiles -> p.ItemSpec |]

        referenceSatellitePaths = [| for p in rar.SatelliteFiles -> p.ItemSpec |]

        referenceScatterPaths = [| for p in rar.ScatterFiles -> p.ItemSpec |]

        referenceCopyLocalPaths = [| for p in rar.CopyLocalFiles -> p.ItemSpec |]

        suggestedBindingRedirects = [| for p in rar.SuggestedRedirects -> p.ItemSpec |]

    }

   

try

    let s = Resolve([| "System"

                       "System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"

                       "Microsoft.SqlServer.Replication"

                    |], "")

    printfn "%A" s

finally

    ignore (System.Console.ReadKey())

The result of running the code looks like this:

{referencePaths =

  [|"C:\\Program Files\\Microsoft SQL Server\\90\\SDK\\Assemblies\\Microsoft.SqlServer.Replication.dll";

    "C:\\Program Files\\Reference Assemblies\\Microsoft\\Framework\\v3.5\\System.Core.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System\\2.0.0.0__b77a5c561934e089\\System.dll"|];

 referenceDependencyPaths =

  [|"C:\\Windows\\assembly\\GAC_MSIL\\System.DirectoryServices\\2.0.0.0__b03f5f7f11d50a3a\\System.DirectoryServices.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.Xml\\2.0.0.0__b77a5c561934e089\\System.Xml.dll";

    "C:\\Windows\\assembly\\GAC_32\\Microsoft.SqlServer.BatchParser\\9.0.242.0__89845dcd8080cc91\\Microsoft.SqlServer.BatchParser.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.Runtime.Remoting\\2.0.0.0__b77a5c561934e089\\System.Runtime.Remoting.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\Microsoft.Vsa\\8.0.0.0__b03f5f7f11d50a3a\\Microsoft.Vsa.dll";

    "C:\\Windows\\assembly\\GAC_32\\System.Data.OracleClient\\2.0.0.0__b77a5c561934e089\\System.Data.OracleClient.dll";

    "C:\\Program Files\\Microsoft SQL Server\\90\\SDK\\Assemblies\\Microsoft.SqlServer.ConnectionInfo.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\Accessibility\\2.0.0.0__b03f5f7f11d50a3a\\Accessibility.dll";

    "C:\\Windows\\assembly\\GAC_32\\System.Transactions\\2.0.0.0__b77a5c561934e089\\System.Transactions.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.DirectoryServices.Protocols\\2.0.0.0__b03f5f7f11d50a3a\\System.DirectoryServices.Protocols.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.Drawing\\2.0.0.0__b03f5f7f11d50a3a\\System.Drawing.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.Deployment\\2.0.0.0__b03f5f7f11d50a3a\\System.Deployment.dll";

    "C:\\Program Files\\Microsoft SQL Server\\90\\SDK\\Assemblies\\Microsoft.SqlServer.Smo.dll";

    "C:\\Windows\\assembly\\GAC_32\\System.EnterpriseServices\\2.0.0.0__b03f5f7f11d50a3a\\System.EnterpriseServices.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.Web.RegularExpressions\\2.0.0.0__b03f5f7f11d50a3a\\System.Web.RegularExpressions.dll";

    "C:\\Program Files\\Microsoft SQL Server\\90\\SDK\\Assemblies\\Microsoft.SqlServer.WmiEnum.dll";

    "C:\\Program Files\\Microsoft SQL Server\\90\\SDK\\Assemblies\\Microsoft.SqlServer.ServiceBrokerEnum.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.Configuration\\2.0.0.0__b03f5f7f11d50a3a\\System.Configuration.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.Web.Services\\2.0.0.0__b03f5f7f11d50a3a\\System.Web.Services.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.Management\\2.0.0.0__b03f5f7f11d50a3a\\System.Management.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.Design\\2.0.0.0__b03f5f7f11d50a3a\\System.Design.dll";

    "C:\\Windows\\assembly\\GAC_32\\System.Web\\2.0.0.0__b03f5f7f11d50a3a\\System.Web.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.Windows.Forms\\2.0.0.0__b77a5c561934e089\\System.Windows.Forms.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.Security\\2.0.0.0__b03f5f7f11d50a3a\\System.Security.dll";

    "C:\\Program Files\\Microsoft SQL Server\\90\\SDK\\Assemblies\\Microsoft.SqlServer.SmoEnum.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.Runtime.Serialization.Formatters.Soap\\2.0.0.0__b03f5f7f11d50a3a\\System.Runtime.Serialization.Formatters.Soap.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\Microsoft.JScript\\8.0.0.0__b03f5f7f11d50a3a\\Microsoft.JScript.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.Configuration.Install\\2.0.0.0__b03f5f7f11d50a3a\\System.Configuration.Install.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\Microsoft.VisualC\\8.0.0.0__b03f5f7f11d50a3a\\Microsoft.VisualC.dll";

    "C:\\Program Files\\Microsoft SQL Server\\90\\SDK\\Assemblies\\Microsoft.SqlServer.SqlEnum.dll";

    "C:\\Windows\\assembly\\GAC_32\\System.Data\\2.0.0.0__b77a5c561934e089\\System.Data.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.Drawing.Design\\2.0.0.0__b03f5f7f11d50a3a\\System.Drawing.Design.dll";

    "C:\\Program Files\\Microsoft SQL Server\\90\\SDK\\Assemblies\\Microsoft.SqlServer.Rmo.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.Data.SqlXml\\2.0.0.0__b77a5c561934e089\\System.Data.SqlXml.dll";

    "C:\\Windows\\assembly\\GAC_MSIL\\System.ServiceProcess\\2.0.0.0__b03f5f7f11d50a3a\\System.ServiceProcess.dll";

    "C:\\Program Files\\Microsoft SQL Server\\90\\SDK\\Assemblies\\Microsoft.SqlServer.RegSvrEnum.dll"|];

 relatedPaths = [||];

 referenceSatellitePaths = [||];

 referenceScatterPaths =

  [|"C:\\Windows\\assembly\\GAC_32\\System.EnterpriseServices\\2.0.0.0__b03f5f7f11d50a3a\\System.EnterpriseServices.Wrapper.dll"|];

 referenceCopyLocalPaths = [||];

 suggestedBindingRedirects = [||];}

This posting is provided "AS IS" with no warranties, and confers no rights.