2012-12-10 15 views
6

Tôi đang cố gắng tải mẫu T4 của mình để chạy lúc xây dựng, mà không thêm phụ thuộc vào SDK mô hình hóa Visual Studio. Tôi đã sử dụng thành công một biến thể của tệp lô được hiển thị here, nhưng bây giờ tôi gặp sự cố trong đó tệp .tt của tôi sử dụng biến số $(SolutionDir) để tham chiếu các dự án khác (và do đó hiện không biên dịch).

Cách tốt nhất để xử lý việc này là gì? Những người khác đã làm gì? (Hard-mã hóa đường dẫn tuyệt đối không phải là một lựa chọn)

EDIT: tôi thấy có những -a lập luận cho rằng có thể được truyền cho TextTransform.exe, là nó có thể sử dụng để xác định $(SolutionDir)?

+1

bạn đã cố gắng 'thiết SolutionDir =% cd% 'để đặt biến vào thư mục hiện? – Pawel

+1

Điều đó không có tác dụng, không -a !! $ (SolutionDir)! C: \ dev \ mysolutionroot – piers7

+0

Có một cổng Mono của T4. Tôi tự hỏi nếu câu trả lời là trong codebase một nơi nào đó. Xem http://stackoverflow.com/a/1395377/26167 – piers7

Trả lời

2

Nhìn qua mã nguồn từ TextTransformation.exe (với ILSpy) Tôi không nghĩ rằng điều này là có thể mà không sửa đổi mẫu (nhưng tôi có một giải pháp).

Cuối cùng, những gì chúng tôi quan tâm ở đây là bước trong khi phân tích cú pháp mẫu trong đó Microsoft.VisualStudio.TextTemplating.Engine.ResolveAssemblyReferences() được gọi. Đây đại biểu ITextTemplatingEngineHost.ResolveAssemblyReference() (mặc dù nó không mở rộng các biến môi trường đầu tiên)

Khi mẫu được chạy từ dòng lệnh, việc thực hiện đang được sử dụng được cung cấp bởi các CommandLineHost, và việc thực hiện đơn giản tìm kiếm tệp như được cung cấp trong đường dẫn tham chiếu và GAC. Với tên tập tin vào thời điểm này vẫn còn có bit $ (SolutionPath), nó sẽ không bao giờ thành công.

Bạn có thể thực hiện phiên bản riêng lại TextTransform.exe, nhưng bạn sẽ phải bắt đầu chủ yếu từ đầu (hoặc sử dụng phản ánh), vì CommandLineHost là :-(nội Hoặc bạn có khả năng có thể tận dụng các cổng Mono https://stackoverflow.com/a/1395377/26167

tôi không thể nói rằng tôi đang hạnh phúc về điều này, bởi vì tôi thấy mình trong cùng một thuyền ...

Edit: Tuy nhiên ... kể từ cuối cùng tất cả các bạn cần làm là thay đổi mẫu, Tôi đặt cùng một kịch bản PowerShell để sao chép các mẫu vào thư mục tạm thời, mở rộng thủ công $ (SolutionDir) ma cro trong quá trình, và thực hiện chúng từ đó. Điều đó dường như hoạt động chỉ tốt.

Drop này vào dự án vi phạm (bạn có thể muốn thay đổi phần mở rộng tập tin) và bạn sẽ được tốt để đi:

<# 
.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

Bạn có thể giải thích về điều này một chút - nơi mà một trong những 'thả' này vào dự án? Bạn chỉ cần gọi điều này từ các hoạt động trước hoặc sau xây dựng? –

+0

Mã được viết bằng giả định thư mục giải pháp là một thư mục và tìm các tệp TT liên quan đến chính nó. Vì vậy, chỉ cần thêm nó vào dự án ở gốc. Bạn sẽ thực hiện điều này từ dòng lệnh (trong PowerShell), và có - bạn có thể có thể gọi điều này trong một bước dựng sẵn nếu cần (tôi làm theo cách thủ công). – piers7

+0

@ piers7 Cảm ơn bạn đã chia sẻ. Tôi đã thay thế phần mở rộng tập tin cố định của bạn với một phần mở rộng được trích xuất từ ​​tập tin tt chính nó bằng cách sử dụng regex ... '$ extension = Select-String -Path $ template.FullName -Pattern '<# @ \ s * output \ s + extension = "(. *)" \ s * #> '| ForEach-Object {$ _. Matches.Groups [1] .Value} ' – Hosein

0

tôi đã sử dụng một cách tiếp cận rất giống với piers7 - ngoại trừ trong trường hợp của tôi, Tôi thực sự cần phải giữ tập tin * .tt trong cùng một thư mục (vì tra cứu thời gian chạy các tập tin dựa trên các đường dẫn tương đối), nhưng không quan tâm nếu tập tin đó được đặt tên khác nhau. Như vậy, thay vì có $ templateTemp tạo một tệp tạm thời trong thư mục tạm thời, tôi giữ nó trong cùng một thư mục.

Tôi cũng cần tìm kiếm đệ quy các tệp * .tt ở bất kỳ đâu trong thư mục giải pháp.

Đây là kịch bản kết quả, tham gia của piers7 và sửa đổi nó:

<# 
.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; 
} 
Các vấn đề liên quan