Tìm thấy câu trả lời ở đây:
http://www.digitallycished.net/Blog/59/locally-publishing-a-vs2010-asp.net-web-application-using-msbuild
Visual Studio 2010 có các tính năng xuất bản Dự án ứng dụng web mới tuyệt vời cho phép bạn dễ dàng xuất bản dự án ứng dụng web của mình chỉ bằng một cú nhấp chuột. Phía sau hậu trường, quá trình chuyển đổi và xây dựng gói Web.config được thực hiện bởi một tập lệnh MSBuild lớn được nhập vào tệp dự án của bạn (tìm thấy tại: C: \ Program Files (x86) \ MSBuild \ Microsoft \ VisualStudio \ v10.0 \ Web \ Microsoft .Web.Publishing.targets). Thật không may, tập lệnh cực kỳ phức tạp, lộn xộn và không có tài liệu (sau đó một số nhận xét sai chính tả và chủ yếu là vô ích trong tệp). Một sơ đồ lớn của tệp đó và một số tài liệu về cách kết nối vào nó sẽ rất hay, nhưng có vẻ như vẫn còn thiếu (hoặc ít nhất là tôi không thể tìm thấy nó).
Thật không may, điều này có nghĩa là thực hiện xuất bản thông qua dòng lệnh mờ hơn nhiều so với mức cần thiết. Tôi rất ngạc nhiên về việc thiếu tài liệu trong lĩnh vực này, vì ngày nay nhiều cửa hàng sử dụng máy chủ tích hợp liên tục và một số thậm chí còn triển khai tự động (mà các tính năng xuất bản của VS2010 có thể giúp ích rất nhiều), vì vậy tôi đã nghĩ rằng việc bật điều này ( dễ dàng!) sẽ là một yêu cầu khá chính cho tính năng này.
Dù sao đi nữa, sau khi đào qua tệp Microsoft.Web.Publishing.targets hàng giờ và đập đầu vào tường thử nghiệm và lỗi, tôi đã tìm ra cách Visual Studio thực hiện phép thuật của nó chỉ bằng một cú nhấp chuột “Xuất bản lên Hệ thống tệp” và các tính năng “Gói triển khai xây dựng”. Tôi sẽ tìm hiểu một chút về kịch bản MSBuild, vì vậy nếu bạn chưa quen với MSBuild, tôi khuyên bạn nên xem trang MSDN của khóa học về lỗi này.
Xuất bản lên hệ thống tệp
Hộp thoại Xuất bản lên Hệ thống Tệp VS2010 Xuất bản lên Hệ thống Tệp khiến tôi mất một lúc để giải thích vì tôi mong đợi một số hoạt động sử dụng hợp lý của MSBuild sẽ xảy ra. Thay vào đó, VS2010 làm một điều gì đó khá kỳ lạ: nó kêu gọi MSBuild thực hiện kiểu triển khai một nửa để chuẩn bị các tệp của ứng dụng web trong thư mục obj của dự án của bạn, sau đó nó dường như thực hiện một bản sao thủ công của các tệp đó (tức là bên ngoài MSBuild) vào thư mục xuất bản mục tiêu của bạn. Đây thực sự là một hành vi kỳ lạ vì MSBuild được thiết kế để sao chép các tệp xung quanh (và những thứ liên quan đến xây dựng khác), vì vậy sẽ có ý nghĩa nếu toàn bộ quá trình chỉ là một mục tiêu MSBuild mà VS2010 đã gọi, không phải là mục tiêu sau đó là bản sao thủ công.
Điều này có nghĩa là thực hiện điều này thông qua MSBuild trên dòng lệnh không đơn giản như việc gọi tệp dự án của bạn với một mục tiêu cụ thể và thiết lập một số thuộc tính. Bạn sẽ cần phải làm những gì VS2010 phải làm: tự tạo một mục tiêu để thực hiện nửa triển khai sau đó sao chép kết quả vào thư mục đích. Để chỉnh sửa tệp dự án của bạn, nhấp chuột phải vào dự án trong VS2010 và nhấp vào Dỡ dự án, sau đó nhấp chuột phải một lần nữa và nhấp vào Chỉnh sửa. Cuộn xuống cho đến khi bạn tìm thấy phần tử Nhập nhập mục tiêu ứng dụng web (Microsoft.WebApplication.targets; chính tệp này nhập tệp Microsoft.Web.Publishing.targets được đề cập trước đó). Bên dưới dòng này, chúng tôi sẽ thêm mục tiêu mới, được gọi là PublishToFileSystem:
<Target Name="PublishToFileSystem"
DependsOnTargets="PipelinePreDeployCopyAllFilesToOneFolder">
<Error Condition="'$(PublishDestination)'==''"
Text="The PublishDestination property must be set to the intended publishing destination." />
<MakeDir Condition="!Exists($(PublishDestination))"
Directories="$(PublishDestination)" />
<ItemGroup>
<PublishFiles Include="$(_PackageTempDir)\**\*.*" />
</ItemGroup>
<Copy SourceFiles="@(PublishFiles)"
DestinationFiles="@(PublishFiles->'$(PublishDestination)\%(RecursiveDir)%(Filename)%(Extension)')"
SkipUnchangedFiles="True" />
</Target>
Mục tiêu này phụ thuộc vào mục tiêu PipelinePreDeployCopyAllFilesToOneFolder, là mục tiêu mà VS2010 gọi trước khi thực hiện sao chép thủ công. Một số tìm hiểu trong Microsoft.Web.Publishing.targets cho thấy rằng việc gọi đích này khiến các tệp dự án được đặt vào thư mục được chỉ định bởi thuộc tính _PackageTempDir.
Tác vụ đầu tiên chúng tôi gọi trong mục tiêu của mình là tác vụ Lỗi, trên đó chúng tôi đã đặt một điều kiện đảm bảo rằng tác vụ chỉ xảy ra nếu thuộc tính PublishDestination chưa được đặt. Điều này sẽ bắt bạn và lỗi bản dựng trong trường hợp bạn quên chỉ định thuộc tính PublishDestination. Sau đó, chúng tôi gọi tác vụ MakeDir để tạo thư mục PublishDestination đó nếu nó chưa tồn tại.
Sau đó, chúng tôi xác định một Mục được gọi là PublishFiles đại diện cho tất cả các tệp được tìm thấy trong thư mục _PackageTempDir. Sau đó, tác vụ Sao chép được gọi là tác vụ sao chép tất cả các tệp đó vào thư mục Đích xuất bản. Thuộc tính DestinationFiles trên phần tử Copy hơi phức tạp; nó thực hiện chuyển đổi các mục và chuyển đổi các đường dẫn của chúng thành các đường dẫn mới bắt nguồn từ thư mục PublishDestination (kiểm tra Siêu dữ liệu Mục Nổi tiếng để xem ý nghĩa của% () s).
Để gọi mục tiêu này từ dòng lệnh, bây giờ chúng ta có thể chỉ cần thực hiện lệnh này (rõ ràng là thay đổi tên tệp dự án và thuộc tính cho phù hợp với bạn):
msbuild Website.csproj "/p:Platform=AnyCPU;Configuration=Release;PublishDestination=F:\Temp\Publish" /t:PublishToFileSystem
Condition="false"
tồn tại để tương thích ngược. VS2010 yêu cầu nhập này tồn tại, ngay cả khi nó bị bỏ qua vì điều kiện sai. Nếu bạn nhìn lại thì bạn sẽ thấy rằng csproj chứa một bản nhập khác để phân$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets
giải thành tệp đích cho phiên bản Visual Studio hiện tại.