我想我会更新我以前的答案,因为我已经花了很多时间和精力创造我自己的解决此问题的。解决问题的方法比简单地解决问题要全面一些,但我试图消除这个问题,并且避免像这样的未来冲击。
MSBuild已从解决方案,配置或其他方面降级。只要求MSBuild独立编译项目。这种情况发生的顺序是通过Powershell脚本来计算的,该脚本解析我们的解决方案和项目以制定出最佳的即时生成执行计划。
关键就在这(我想你可能会发现有用)如下片段:
识别我的解决方案
我在我的平台上的所有解决方案的列表,我基本上是重复在每个这些。
$buildPlan = (
@{
solutions = (
@{
name = "DataStorage"
namespace = "Platform.Databases"
},
@{
name = "CoreFramework"
},
@{
namespace = "Platform.Server"
name = "Application1"
},
@{
namespace = "Platform.Server"
name = "Application2"
},
@{
namespace = "Platform.Client"
name = "Application1"
}
)
})
我有一些逻辑,帮助转化为实际的物理路径,这一点,但它很定制我们的需求,所以我不会在这里列出来。足以说,从这个列表中,我可以找到需要解析的.sln文件。
解析为项目
随着每个解决方案解决方案文件,我看了.sln文件,并尝试提取我以后需要建立包含内的所有项目。
所以,首先,找出所有的项目在我
$solutionContent = Get-Content $solutionFile
$buildConfigurations += Get-Content $solutionFile | Select-String "{([a-fA-F0-9]{8}-([a-fA-F0-9]{4}-){3}[a-fA-F0-9]{12})}\.(Release.*)\|Any CPU\.Build" | % {
New-Object PSObject -Property @{
Name = $_.matches[0].groups[3].value.replace("Release ","");
Guid = $_.matches[0].groups[1].value
}
} | Sort-Object Name,Guid -unique
然后翻译成的,我以后可以遍历项目一个不错的榜单。
$projectDefinitions = $solutionContent |
Select-String 'Project\(' |
ForEach-Object {
$projectParts = $_ -Split '[,=]' | ForEach-Object { $_.Trim('[ "{}]') };
$configs = ($buildConfigurations | where {$_.Guid -eq $projectParts[3]} | Select-Object Name)
foreach ($config in $configs)
{
$santisiedConfig = if ([string]::IsNullOrEmpty($config.Name)){"Release"}else{$config.Name}
if ($projectParts[1] -match "OurCompanyPrefix.")
{
New-Object PSObject -Property @{
Name = $projectParts[1];
File = $projectParts[2];
Guid = $projectParts[3];
Config = $santisiedConfig
}
}
}
}
加载Visual Studio项目
从我的解决方案文件的解析,我现在的每解决方案项目,其中关键的是含有从解决方案根的相对文件路径,找到名单项目。
$projectDefinition = [xml](Get-Content $csProjectFileName)
$ns = @{ e = "http://schemas.microsoft.com/developer/msbuild/2003" }
$references = @();
1)确定外部项目引用
$references += Select-Xml -Xml $projectDefinition -XPath "//e:Project/e:ItemGroup/e:Reference" -Namespace $ns | % {$_.Node} | where {$_.Include -match "OurCompanyPrefix" -and $_.HintPath -notmatch "packages"} | % {$_.Include}
2)确定内部项目引用
$references += Select-Xml -Xml $projectDefinition -XPath "//e:Project/e:ItemGroup/e:ProjectReference" -Namespace $ns | % { $_.Node.Name }
3)继 “生成后” 事件作为外部引用
$references += Select-Xml -Xml $projectDefinition -XPath "//e:Project/e:PropertyGroup/e:PostBuildEvent" -Namespace $ns | where {(!([String]::IsNullOrEmpty($_.Node.InnerText)))} | % {
$postBuildEvents = $_.Node.InnerText.Split("`n")
$projectsReferencedInPostBuildEvents = $postBuildEvents | Select-String "\(SolutionDir\)((\w|\.)*)" | % {$_.Matches[0].Groups[1].Value}
if ($projectsReferencedInPostBuildEvents -ne $null)
{
Write-Output $projectsReferencedInPostBuildEvents | % { $matchedProject = $_; ($releaseConfiguation | ? {$_.File -match $matchedProject}).Name }
}
}
而且,由于我们是在它,了解一些基本的输出信息太
这是非常方便,当涉及到迭代我的项目,以建立清单,知道在哪里推输出,或在哪里查找依赖项的输出。
$assemblyName = (Select-Xml -Xml $projectDefinition -XPath "//e:Project/e:PropertyGroup/e:AssemblyName" -Namespace $ns).Node.InnerText
$outputPath = (Select-Xml -Xml $projectDefinition -XPath "//e:Project/e:PropertyGroup[contains(@Condition,'Release|')]/e:OutputPath" -Namespace $ns).Node.InnerText
而在这一切
我们只需要确保我们没有任何重复,所以我只记录这个特殊的代码项目的不同依赖结束:
$dependendents = @();
if ($references -ne $null)
{
$buildAction.project.dependencies += $references | where {(!([string]::IsNullOrEmpty($_))) -and ($_ -match "OurCompanyPrefix\.(.*)")} | % { $_.ToLower()} | Select -unique
}
我希望这可以为您提供足够的信息来解析您的SLN和PROJ文件。如何选择捕获和存储这些信息我认为完全取决于您。
我正在编写一篇相当深入的博客文章,其中将包含我上面未提及的所有修剪和框架。这篇文章还没有准备好,但我会从早期的文章链接到它:http://automagik.piximo.me/2013/02/just-in-time-compilation.html - 由于微软的这一改变几乎使这项工作脱轨!
干杯。
+1。 –
当你说MSBuild有确认的错误时,你是什么意思?有没有在MSDN中的这个问题的链接,所以我可以跟踪它,看看微软是否有任何指导? –
正是在这里 http://connect.microsoft.com/VisualStudio/feedback/details/586875/msbuild-4-0-incorrectly-processes-project-dependencies-specified-in-solution-file 固定为4.5 –