2010-07-30 33 views
25

Tôi đang phát triển một tác vụ MSBuild tùy chỉnh xây dựng một ORM layer và sử dụng nó trong một dự án. Tôi đang bị cản trở bởi hành vi của Visual Studio giữ MSBuild nhiệm vụ DLL và không cho phép đi.Visual Studio 2008 khóa các cụm MSBuild Task tùy chỉnh

Tôi muốn tổ chức giải pháp của mình như thế này;

My Solution 
| 
+- (1) ORM Layer Custom Task Project 
| | 
| +- BuildOrmLayerTask.cs  // here's my task 
| 
+- (2) Business Logic Project // and here's the project that uses it. 
    | 
    +- <UsingTask TaskName="BuildOrmLayerTask" AssemblyFile="$(TaskAssembly)" /> 

Tuy nhiên, khi dự án (2) xây dựng, nó sẽ khóa vào lắp ráp từ dự án (1). Vì vậy, bây giờ tôi không thể xây dựng dự án (1) một lần nữa mà không đóng giải pháp và mở lại nó.

Có cách nào để tôi có thể sắp xếp mọi thứ để tác vụ tùy chỉnh tạo không bị khóa bởi Visual Studio không?

Trả lời

21

(Edit:Sayed Ibrahim Hashimi, người theo nghĩa đen wrote the book trên msbuild, cho thấy lớp AppDomainIsolatedTask cho một cách tiếp cận tốt hơn)

tôi đã quản lý để giải quyết cái này bản thân mình ...

Tìm thấy forum post from Dan Moseley này, một trong những nhà phát triển MSBuild từ Microsoft:

Chào bạn,

Thật không may điều này là do MSBuild tải các assembly nhiệm vụ trong appdomain chính. CLR không cho phép các hội đồng tải xuống từ một miền ứng dụng vì điều này cho phép tối ưu hóa quan trọng trên phần của chúng.

Cách giải quyết duy nhất tôi đề nghị là gọi tomsbuild.exe để tạo dự án sử dụng tác vụ. Để thực hiện việc này, hãy tạo MSBuild.exe <> dưới dạng công cụ bên ngoài trong VS.

Dan
nhà phát triển trên msbuild
DanMoseley - MSFT

Vì vậy, có vẻ như để ngăn chặn ổ khóa, bạn phải đẻ trứng ra một quá trình msbuild.exe mới. Nó không thể là một trong đó chạy bên trong Visual Studio, bởi vì khi MSBuild chạy, nó tải các nhiệm vụ vào miền ứng dụng chính của Visual Studio, và điều đó không bao giờ có thể được dỡ bỏ.

  • tạo một dự án mới MSBuild (một csproj hoặc tương tự) mà đè 'xây dựng' Mục tiêu và thực hiện hành động tùy chỉnh của bạn, ví dụ;

    <!-- fragment of Prebuild.csproj --> 
    <Target Name="Build"> 
        <BuildOrmLayerTask Repository="$(Repository)" /> 
    </Target> 
    
  • Thêm nó vào visual studio nếu bạn muốn, nhưng sử dụng Virtual Machine Manager để chắc chắn rằng nó là không xây dựng trong bất kỳ cấu hình. Chỉ cần để VS chăm sóc kiểm soát nguồn và tương tự, không xây dựng.

  • Chỉnh sửa.tệp csproj của dự án phụ thuộc vào Prebuild.csproj. Thêm mục tiêu BeforeBuild gọi MSBuild bằng cách sử dụng tác vụ Exec. Điều này sẽ bắt đầu một quy trình mới và khi quá trình đó kết thúc, các khóa tệp được giải phóng. Thí dụ;

    <PropertyGroup> 
        <PrebuildProject>$(SolutionDir)Prebuild\Prebuild.csproj</PrebuildProject> 
    </PropertyGroup> 
    <Target Name="BeforeBuild"> 
        <Exec Command="msbuild.exe &quot;$(PrebuildProject)&quot;" /> 
    </Target> 
    

Bây giờ, khi bạn xây dựng các dự án phụ thuộc, nó thực thi MSBuild trong một quá trình mới trước khi chạy biên dịch.

+2

Khởi chạy một tiến trình msbuild.exe khác có vẻ là giải pháp duy nhất hoạt động. Tôi không thấy cách mở rộng AppDomainIsolatedTask được cho là hoạt động trong tình huống này, vì MSBuild đã tải assembly trong AppDomain chính vào thời điểm nó cố đọc các kiểu. Có cần phải có một cách trong tập tin dự án chính nó để cho MSBuild tải nhiệm vụ trong một AppDomain khác. Microsoft từ chối khắc phục vấn đề lớn này vì các lần truy cập hiệu suất bằng cách sử dụng các AppDomain mới - cũng cho phép chúng tôi ghi đè tùy chọn và quyết định cho chính mình? Tại sao đây là một vấn đề khó khăn đối với MS "kỹ sư" để sửa chữa? – makhdumi

+1

Mở rộng AppDomainIsolatedTask không hoạt động đối với tôi. – Fosna

+1

Bạn không phải tạo một dự án MSBuild riêng biệt. Bạn có thể chỉ cần đặt một điều kiện vào mục tiêu của bạn và làm cho mục tiêu 'BeforeBuild' thực hiện dự án hiện tại với một số tham số, ví dụ: '' và ''. – Stijn

4

Bạn có thể chỉnh sửa các tập tin dự án và bao gồm việc kê khai tài sản sau

<PropertyGroup> 
    <GenerateResourceNeverLockTypeAssemblies>true</GenerateResourceNeverLockTypeAssemblies> 
</PropertyGroup> 

Hãy cho tôi biết nếu mà làm việc cho bạn.

+0

Tôi đã thêm điều này vào tất cả các dự án của mình và giờ đây nó hoạt động hoàn hảo. Cảm ơn! –

+0

Thực ra, khi tôi bắt đầu làm việc với nó, nó lại bị khóa lại. Tôi đã tìm ra giải pháp, mặc dù; xem câu trả lời của tôi Có vẻ như VS tải các nhiệm vụ tùy chỉnh vào miền ứng dụng chính và không bao giờ có thể được tải xuống, vì vậy tất cả những gì bạn có thể làm là bắt đầu một quy trình MSBuild.exe mới bằng cách sử dụng Exec. –

+8

Nếu nhiệm vụ tùy chỉnh của nó, bạn có thể mở rộng Microsoft.Build.Utilities.AppDomainIsolatedTask để giúp bạn. –

3

Như tôi đã đề cập trong nhận xét được hướng dẫn tại @ Al-Muhandis, có vẻ như có thể tạo trình bao quanh tác vụ tùy chỉnh sao cho trình bao bọc bị khóa nhưng không phải là tác vụ tùy chỉnh DLL. Tôi đã thực hiện một shot ban đầu khi làm như vậy với dự án isolated-task. Nó có thể là lỗi, và nó chỉ hoạt động với VS2008 bây giờ. Kéo yêu cầu chào mừng.

Ý tưởng cho dự án dựa trên quan sát rằng nhiệm vụ xuất phát từ MarshalByRefObject (sử dụng, có lẽ, AppDomainIsolatedTask) dường như được tải vào miền ứng dụng chính cho mục đích phản chiếu, nhưng miền ứng dụng mới được tạo để thực thi tác vụ . Kể từ khi tải vào miền ứng dụng chính vẫn có vẻ như khóa các DLL, nó đã được hữu ích để tạo ra một DLL với một nhiệm vụ bắt nguồn từ AppDomainIsolatedTask tải các nhiệm vụ tùy chỉnh DLL. Bằng cách đó, các wrapper DLL bị khóa, nhưng bởi vì nó thực hiện trong miền ứng dụng riêng của mình, các DLL nhiệm vụ tùy chỉnh được dỡ bỏ khi miền thực hiện nhiệm vụ của trình bao bọc được dỡ xuống. Thủ tục này tránh giữ một khóa trên các nhiệm vụ tùy chỉnh DLL sau khi xây dựng hoàn tất.

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