Nei*_*eil 5 c# msbuild assembly-resolution
我正在编写一个验证工具,用于检查项目中引用的文件版本.我想使用MSBuild使用的相同解析过程.
例如,Assembly.Load(..)需要一个完全限定的程序集名称.但是,在项目文件中,我们可能只有"System.Xml"之类的东西.MSBuild可能使用项目的目标框架版本和其他一些启发式来决定加载哪个版本的System.Xml.
你将如何模仿(或直接使用)msbuild的装配解决过程?
换句话说,在运行时,我想获取字符串"System.Xml",以及.csproj文件中找到的其他信息,并找到msbuild将找到的相同文件.
我今天遇到了这个问题,我找到了这篇关于如何做到这一点的旧博客文章:
我尝试了一下,效果很好!我修改了代码以在可能的情况下查找 4.5.1 版本的程序集,这就是我现在所拥有的:
#if INTERACTIVE
#r "Microsoft.Build.Engine"
#r "Microsoft.Build.Framework"
#r "Microsoft.Build.Tasks.v4.0"
#r "Microsoft.Build.Utilities.v4.0"
#endif
open System
open System.Reflection
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 = {
referencePaths:string array
referenceDependencyPaths:string array
relatedPaths:string array
referenceSatellitePaths:string array
referenceScatterPaths:string array
referenceCopyLocalPaths:string array
suggestedBindingRedirects:string array
}
let resolve (references:string array, outputDirectory:string) =
let x = { new IBuildEngine with
member be.BuildProjectFile(projectFileName, targetNames, globalProperties, targetOutputs) = 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.IgnoreVersionForFrameworkReferences <- true
rar.TargetFrameworkVersion <- "v4.5.1"
rar.TargetedRuntimeVersion <- "v4.5.1"
rar.TargetFrameworkDirectories <- [||] //[|@"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\"|]
rar.Assemblies <- [|for r in references -> new Microsoft.Build.Utilities.TaskItem(r) :> ITaskItem|]
rar.AutoUnify <- true
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 |]
}
[<EntryPoint>]
let main argv =
try
let s = resolve([| "System"
"System.Data"
"System.Core, Version=4.0.0.0"
"Microsoft.SqlServer.Replication" |], "")
printfn "%A" s.referencePaths
finally
ignore (System.Console.ReadKey())
0
Run Code Online (Sandbox Code Playgroud)