2010-08-08 22 views
7

tôi có một dự án Silverlight 3 với một cái gì đó như thế này:MSBuild: Làm cách nào để tạo và sử dụng Tác vụ để chuyển đổi các mục Nội dung tại thời gian xây dựng?

<ItemGroup> 
    <Content Include="Content\image1.png"> 
    </Content> 
</ItemGroup> 

Về cơ bản tôi đã thêm một tập tin PNG để dự án của tôi và thiết lập xây dựng hành động của mình để "Nội dung". Điều này hoạt động độc đáo.

Bây giờ những gì tôi muốn làm là có thể thêm hình ảnh trong một định dạng khác nhau để dự án của tôi, và họ đã chuyển đổi sang PNG ở thời gian xây dựng - vì vậy mà kết quả cuối cùng là như thể tôi đã đã thêm hình ảnh PNG vào dự án (dưới dạng Nội dung) ngay từ đầu.

Nói cách khác - tôi muốn hình ảnh xuất hiện, ở định dạng PNG, trong gói XAP của tôi. Lý tưởng nhất là tôi muốn làm điều này theo cách nó sẽ làm việc với Visual Web Developer 2008 Express (vì vậy tôi có thể thêm tập tin hình ảnh vào dự án của tôi bằng cách kéo chúng vào IDE và có thể thay đổi hành động xây dựng), và mà không thực hiện bất kỳ thay đổi nào trên toàn hệ thống.

Định dạng cụ thể mà tôi muốn chuyển đổi là XCF - Tôi đã có mã .NET để thực hiện chuyển đổi sang PNG. Tôi giả định rằng tôi phải create a MSBuild Task.

Tôi không thực sự có nhiều kinh nghiệm về MSBuild và tôi muốn biết cách đặt một thứ như vậy với nhau.


Dựa trên sự hiểu biết thô của tôi như thế nào MSBuild làm việc, tôi nghĩ rằng tôi cần phải biết:

  • Làm thế nào để tạo ra một bộ sưu tập của các mục bằng cách (tái) di chuyển chúng từ @(Content) (hoặc một số khác) bộ sưu tập, dựa trên phần mở rộng tập tin của họ?
    • OR: Tạo một hành động tùy chỉnh xây dựng Tôi có thể sử dụng trong Visual Web Developer 2008 Express
  • Làm thế nào để nhận được đường đi của mặt hàng đầu vào trong một Task?
  • Ở đâu (.NET hoặc MSBuild?) Và Cách chỉ định vị trí của tệp đầu ra được tạo bởi một Task?
  • Làm thế nào để đảm bảo rằng một tệp được xây dựng lại nếu tệp đầu vào của nó thay đổi?
  • Trường hợp (có thể là BeforeBuild?) Và Cách để đưa lại các mục được chuyển đổi thành @(Content)? (Hoặc tôi có nên sử dụng một số bộ sưu tập khác không?)
    • HOẶC: Một số cách khác để đưa chúng vào XAP?

Và nếu điều này có vẻ như một cách hợp lý để làm những việc hoặc nếu tôi đã bỏ lỡ bất cứ điều gì?

+1

Tôi đã phát hiện ra rằng 'AvailableItemName' sẽ tạo một Action Build tùy chỉnh xuất hiện trong VWD. Tham khảo: http://msdn.microsoft.com/en-us/library/ms171468(VS.80).aspx –

Trả lời

13

Bạn đã yêu cầu cụ thể các câu hỏi phụ nhằm đạt được mục tiêu tổng thể của bạn, tôi đoán bạn muốn tìm hiểu về MSBuild, thay vì nhận được một câu trả lời cho nhiệm vụ tổng thể của bạn (đó là những gì bạn sẽ nhận được từ nhiều người khác do tiền thưởng của bạn), vì vậy tôi sẽ trả lời các câu hỏi cá nhân của bạn và sau đó cố gắng đưa chúng vào một giải pháp.

Vì vậy, giả sử bạn muốn chuyển đổi tất cả các tệp .jpg thành tệp .png.

Tạo một danh sách phụ từ mục danh sách nội dung dựa trên phần mở rộng:

<ItemGroup> 
    <Sublist Include="@(Content)" Condition=" '%(Extension)' == '.jpg' " /> 
</ItemGroup> 

Nhận con đường của mặt hàng đó trong một nhiệm vụ.

Hai cách - phụ thuộc vào đầu vào mà nhiệm vụ của bạn có thể chấp nhận. Bằng cách này giống như một "foreach" trên mỗi mục trong danh sách phụ chứa, và tôi sẽ có xu hướng sử dụng nó với một nhiệm vụ Exec:

<Exec Command="convert.exe /Input:%(Sublist.FullPath)" /> 

Xác định một đường dẫn đầu ra cũng phụ thuộc vào .exe hoặc các nhiệm vụ mà bạn và đường dẫn đầu ra có nghĩa là gì đối với một tác vụ cụ thể:

là thư mục hoặc chỉ một tên tệp có đuôi mở rộng khác. Nhưng tôi sẽ giả sử bạn muốn tập tin đầu ra có cùng tên, nhưng một phần mở rộng khác nhau:

<Exec Command="convert.exe &quot;%(Sublist.FullPath)&quot; &quot;%(Sublist.RootDir)%(Sublist.Directory)%(Sublist.Filename).png&quot;" />  

Làm thế nào để xây dựng lại các png nếu những thay đổi jpg (hoặc được làm sạch).

Vâng, điều này là sử dụng thuộc tính Đầu vào và Đầu ra của phần tử chứa mục tiêu nơi lệnh chuyển đổi của chúng tôi được thực thi. Các đầu vào chỉ định các tệp nguồn là gì và các đầu ra xác định mục tiêu sẽ tạo ra.MSBuild sau đó so sánh datetime của đầu vào với datetime của đầu ra và nếu họ hết hạn, sau đó các kết quả đầu ra được xây dựng lại

<Target Name="ConvertJpg" 
     Inputs="@(Content)" 
     Outputs="@(Content -> '%(RootDir)%(Directory)%(Filename).png')" 
     Condition=" '%(Extension)' == '.jpg' " 
  • Đầu vào nói rằng chúng ta muốn sử dụng "Nội dung" ItemGroup
  • Thuộc tính Điều kiện đảm bảo rằng chúng tôi chỉ làm việc với các mục Nội dung kết thúc bằng phần mở rộng .jpg
  • Thuộc tính Đầu ra cho biết rằng các đầu vào mà chúng tôi đang làm việc, chúng tôi sẽ tạo các tệp có đường dẫn và tên tệp tương tự, nhưng kết thúc bằng phần mở rộng .png

Cuối cùng, bạn đã phát hiện chính xác rằng bạn cần phải tiêm lại tệp .png đã tạo trở lại vào nhóm mục @Content - tốt, thật dễ dàng, bạn chỉ cần đưa chúng vào mục nội dung. Nhớ lại rằng Sublist chứa các tệp .jpg - chúng tôi muốn các tệp đó nhưng có đuôi .png. Chúng tôi cũng không muốn các tập tin .jpg trong nhóm mục Content một lần png đã được tạo

<Content Remove="@(Sublist)" /> 
<Content Include="@(Sublist -> '%(RootDir)%(Directory)%(Filename).png')" /> 

Vì vậy, tổng kết, mục tiêu của bạn sẽ trông giống như thế này tôi tin rằng:

<Target Name="ConvertJpg" 
     Inputs="@(Content)" 
     Outputs="@(Content -> '%(RootDir)%(Directory)%(Filename).png')" 
     Condition=" '%(Extension)' == '.jpg' " 
    <ItemGroup> 
     <Sublist Include="@(Content)" Condition=" '%(Extension)' == '.jpg' " /> 
    </ItemGroup> 

    <Exec Command="convert.exe /Input:%(Sublist.FullPath) Output=%(Sublist.RootDir)%(Sublist.Directory)%(Sublist.Filename).png" /> 

    <Content Remove="@(Sublist)" /> 
    <Content Include="@(Sublist -> '%(RootDir)%(Directory)%(Filename).png')" /> 
</Target> 

Vào cách, ImageMagik có một công cụ dòng lệnh sẽ chuyển đổi jpg thành png ...

+0

Câu trả lời hay. Tôi có một câu hỏi tiếp theo nhỏ: Nếu tôi muốn đầu ra đi đâu đó tạm thời (như thư mục obj), điều này có phù hợp không: '$ (IntermediateOutputPath)% (Identity) \% (Filename) .png'? –

+0

Một câu hỏi khác về câu trả lời của bạn: Các hình ảnh jpg có bị xóa khỏi '@ (Nội dung)' sau khi mục tiêu 'ConvertJpg' chạy không? Tôi sẽ không đoán được (sẽ đưa chúng vào đầu ra, điều đó là xấu) - mặc dù có vẻ như sử dụng Item Name/Build Action cụ thể sẽ giải quyết vấn đề này một cách dễ dàng, nếu đó là vấn đề. –

+0

Không sử dụng% (Identity) như thế - chứa các giá trị được nhập vào thuộc tính "Bao gồm". Tôi đoán bạn đang muốn tên thư mục như vậy: $ (IntermediateOutputPath) \% (Thư mục) \% (Tên tệp) .png Tôi đã chỉnh sửa câu trả lời của mình để giải quyết mối lo ngại khác của bạn (IE xóa jpg khỏi Nội dung) –

0

Thay vì tạo tác vụ MSBuild, bạn cũng có thể tạo công cụ Tùy chỉnh và chỉ định công cụ này trong Công cụ tùy chỉnh trong thuộc tính của tệp hình ảnh của bạn.

"công cụ tùy chỉnh sẽ chuyển đổi tệp tại thời điểm thiết kế và sẽ đặt đầu ra của biến đổi vào tệp khác"

ví dụ:Số liệu. nó có công cụ chuyển đổi riêng của nó thông qua đó chúng tôi có được một lớp để sử dụng trong ứng dụng của chúng tôi.

lợi thế của phương pháp này là bạn cũng có thể sử dụng tệp được tạo tại thời điểm thiết kế .

như thực hiện mẫu có thể được tìm thấy tại http://www.drewnoakes.com/snippets/WritingACustomCodeGeneratorToolForVisualStudio/

+0

Điều này dường như yêu cầu sửa đổi sổ đăng ký trên máy bằng công cụ này? –

+0

có để đăng ký công cụ của bạn với tư cách là Trình tạo mã. bạn có thể phân phối nó dưới dạng trình cài đặt hoặc tệp .reg để thực hiện các mục đăng ký. –

2

Tôi tin rằng bạn muốn một cái gì đó như thế này:

<ItemGroup> 
    <JPGContent Include="foo.jpg" /> 
</ItemGroup> 
<Target Name="BeforeBuild" 
     Inputs="@(JPGContent)" Outputs="%(JPGContent.Filename).png"> 
    <!-- replace this with call to jpg->png converter --> 
    <Exec Command="copy %22%(JPGContent.FullPath)%22 %(JPGContent.Filename).png" /> 
    <ItemGroup> 
    <Content Include="%(JPGContent.Filename).png" /> 
    </ItemGroup> 
</Target> 
<Target Name="AfterBuild"> 
    <!-- just demoing that 'Content' now has right value --> 
    <Warning Text ="[email protected](Content)" /> 
</Target> 

nơi bạn chỉ định một JPGContent BuildAction mới mà nó chuyển đổi.

(Có thể xem thêm http://msdn.microsoft.com/en-us/library/ms164313.aspx và lưu ý rằng %22 chỉ là một cách để nhúng một dấu ngoặc kép trong một thuộc tính.)

Các vấn đề liên quan