2012-12-10 15 views
6

Visual Studio Modeling SDKに依存関係を追加せずに、ビルド時にT4テンプレートを実行しようとしています。私は首尾よくhereと表示されたバッチファイルの変種を使用しましたが、私の.ttファイルが$(SolutionDir)変数を使用して他のプロジェクトを参照する(したがって現在コンパイルされていない)という問題があります。

これを処理する最善の方法は何ですか?他の人は何をしましたか? (絶対パスをハードコーディングすることはオプションではありません)

EDIT: 私はTextTransform.exeに渡すことができ-a引数があります参照、$(SolutionDir)を定義するためにこれを使用することが可能ですか?

+1

を使用すると、現在のディレクトリに変数を設定するには、 '設定SolutionDirは=%でcd%'を試したことがありますか? – Pawel

+1

それは動作しません、どちらも-a !! $(SolutionDir)!C:\ dev \ mysolutionroot – piers7

+0

T4のMonoポートがあります。私は答えがどこかのコードベースにあるのだろうかと思います。 http://stackoverflow.com/a/1395377/26167を参照してください。 – piers7

答えて

2

TextTransformation.exe(ILSpy)のソースコードを見ると、これはテンプレートを変更しなければ可能ではないと思いますが(解決方法はあります)

は最終的に私たちがここで気に何Microsoft.VisualStudio.TextTemplating.Engine.ResolveAssemblyReferencesは()が呼び出されたテンプレートの解析時の段階です。 ITextTemplatingEngineHost.ResolveAssemblyReference()(それが最初の環境変数を展開するんが)

テンプレートは、コマンドラインから実行された場合、使用中の実装は単にCommandLineHost、およびその実装が提供することにあるこの代表団参照パスとGACで提供されているファイルを探します。ファイル名にはまだこの時点で$(SolutionPath)ビットが入っていますので、決して成功することはありません。

CommandLineHostが内部:-(であるか、あなたが潜在的にモノポートhttps://stackoverflow.com/a/1395377/26167

を活用する可能性があるので、あなたがTextTransform.exeのご 自身バージョンを実装することができますが、あなたはスクラッチ(または使用リフレクション)から大きく起動する必要があるだろう

私は同じ船に乗って自分自身を見つけるので、私は、このことについて満足していると言うことはできません...

編集:しかし...最終的にあなたがする必要があるすべては、テンプレートを変更であることから、 PowerShellスクリプトを使ってテンプレートをtempディレクトリにコピーし、手動で$(SolutionDir)maを展開してプロセスの中でcroを実行し、そこから実行します。それはちょうど良いを動作するようです。

問題のあるプロジェクトにドロップこれを(あなたは、ファイルの拡張子を変更したい場合があります)、あなたが行くように良いことがあります:

<# 
.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; 
} 
+0

これについて少し詳しく説明できますか?これをプロジェクトのどこに「落とす」でしょうか?ビルド前またはビルド後の操作から呼び出すだけですか? –

+0

書かれたコードは、解決策dirが1つのフォルダであると仮定し、それ自体に関連するTTファイルを見つけます。そのため、ルートにあるプロジェクトに追加するだけです。コマンドラインから(PowerShellで)これを実行します。必要であれば、事前ビルドのステップでこれを呼び出すことができます(私は手動で行います)。 – piers7

+0

@ piers7共有いただきありがとうございます。私はあなたの固定ファイル拡張子をregexを使ってttファイルから抽出した拡張子に置き換えました... '$ extension = Select-String -Path $ template.FullName -Pattern '<#@ \ s * output \ s + extension = "(。*)" \ s *#> '| ForEach-Object {$ _。Matches.Groups [1] .Value} ' – Hosein

0

私はpiers7に非常によく似たアプローチを使用 - 私の場合を除き、私は実際に* .ttファイルを同じディレクトリに保存する必要がありました(相対パスに基づくファイルの実行時ルックアップのため)。しかし、ファイル自体の名前が異なるかどうかは気にしませんでした。そのため、$ templateTempにtempディレクトリに一時ファイルを作成させる代わりに、同じフォルダに保存しました。

ソリューションディレクトリ内のどこでも* .ttファイルを再帰的に検索する必要がありました。ここで

はpiers7年代を取って、それを修正し、結果のスクリプトです:

<# 
.Synopsis 
Executes all the T4 templates within designated areas of the containing project 
#> 
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\12.0\texttransform.exe"; 
$solutionDir = Resolve-Path "$scriptDir\" 
$templates = Get-ChildItem -Path $scriptDir -Filter *.tt -Recurse 
$extension = '.ts'; 

pushd $scriptDir; 
try{ 
    foreach($template in $templates){ 
     # keeping the same path (because my template references relative paths), 
     # but copying under different name: 
     $templateTemp = $template.FullName + "____temporary" 
     $targetfile = [IO.Path]::ChangeExtension($template.FullName, $extension); 
     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; 
} 
関連する問題