查看来自 TextTransformation.exe(使用 ILSpy)的源代码,我认为不修改模板是不可能的(但我确实有解决方案)。
最终我们在这里关心的是模板解析过程中调用 Microsoft.VisualStudio.TextTemplating.Engine.ResolveAssemblyReferences() 的步骤。这代表 ITextTemplatingEngineHost.ResolveAssemblyReference()(尽管它确实首先扩展了环境变量)
当模板从命令行运行时,所使用的实现是由 CommandLineHost 提供的,它的实现只是查找引用路径和 GAC 中提供的文件。鉴于此时文件名仍然包含 $(SolutionPath) 位,它永远不会成功。
您可以实现 自己的 版本的 TextTransform.exe,但您必须从头开始(或使用反射),因为 CommandLineHost 是内部的 :-( 或者您可能会利用单声道端口https://stackoverflow.com/a/1395377/26167
我不能说我对此感到高兴,因为我发现自己在同一条船上......
编辑: 但是...由于最终您需要做的就是更改模板,因此我编写了一个 PowerShell 脚本将模板复制到临时目录,手动扩展 $(SolutionDir)过程中的宏,并从那里执行它们。这似乎工作很好。
把它放到有问题的项目中(你可能想更改文件扩展名),你应该很高兴:
<#
.Synopsis
Executes all the T4 templates within designated areas of the containing project
.Description
Unfortunately the Visual Studio 2010 'Transform All Templates' function doesn't appear
to work in SSDT projects, so have to resort to hackery like this to bulk-execute templates
#>
param(
)
$ErrorActionPreference = 'stop';
$scriptDir = Split-Path $MyInvocation.MyCommand.Path
$commonProgramFiles32 = $env:CommmonProgramFiles
if (Test-Path environment::"CommonProgramFiles(x86)") { $commonProgramFiles32 = (gi "Env:CommonProgramFiles(x86)").Value };
$t4 = Resolve-Path "$commonProgramFiles32\Microsoft Shared\TextTemplating\10.0\texttransform.exe";
$solutionDir = Resolve-Path "$scriptDir\..\"
$templates = @(dir "$scriptDir\Database Objects\load\*.tt")
# Cloning to temp dir originally caused issues, because I use the file name in the template (doh!)
# Now I copy to temp dir under the same name
pushd $scriptDir;
try{
foreach($template in $templates){
$templateTemp = Join-Path ([IO.Path]::GetTempPath()) $template.Name;
$targetfile = [IO.Path]::ChangeExtension($template.FullName, '.sql');
Write-Host "Running $($template.Name)"
Write-Host "...output to $targetFile";
# When run from outside VisualStudio you can't use $(SolutionDir)
# ...so have to modify the template to get this to work...
# ...do this by cloning to a temp file, and running this instead
Get-Content $template.FullName | % {
$_.Replace('$(SolutionDir)',"$solutionDir")
} | Out-File -FilePath:$templateTemp
try{
& $t4 $templateTemp -out $targetfile -I $template.DirectoryName;
}finally{
if(Test-Path $templateTemp){ Remove-Item $templateTemp; }
}
}
}finally{
popd;
}