簡體   English   中英

msbuild和Visual Studio項目配置問題

[英]msbuild and visual studio project configuration problem

我有一個包含很多項目和安裝程序項目的解決方案。 一個項目使用第三方程序包。 該軟件包帶有一個本機DLL和.net包裝器DLL。 為了使代碼正常工作,.net包裝器DLL需要在運行時查找本機DLL。 但是代碼在編譯時從不直接引用本機DLL(代碼在編譯時與.net包裝器DLL通信)。

現在,我必須在程序員的計算機上的編譯期間以及在用戶計算機上的安裝期間選擇適當的方法來部署本機DLL。

基本上,我有兩個選擇,要么將本機DLL放入Windows System文件夾,要么將本機DLL放入包含exe文件的本地文件夾。

要將本機DLL放入系統文件夾,在構建解決方案后,我需要一個后構建腳本來將該文件xcopy到目錄中。 我還需要在安裝程序項目中創建系統文件夾輸出,以便安裝程序在客戶端計算機上工作。 我不知道將文件復制到系統文件夾是否是個好主意。 對於此解決方案,每次(大團隊中的其他人)創建新的安裝程序時,他或她都必須記住創建系統文件夾輸出並在配置下添加本機DLL,否則他或她的安裝程序將無法安裝用戶計算機上的軟件。

要將本機DLL放入本地文件夾,我有以下兩種方式:1.使用后期生成腳本。 此解決方案必須在我的大型解決方案中找出每個使用本機DLL對該項目進行引用的可執行項目,並將構建后腳本鏈接到每個此類可執行項目。 將來,當某人(其他人在大團隊中)創建相同類型的新可執行項目時,他(或她)必須記住鏈接相同的構建后腳本,否則可執行文件將無法找到本機DLL。 。 這是我真正不喜歡的,人們往往會忘記。

  1. 我可以將本機DLL添加到使用它的項目中,並在DLL的屬性配置中將其設置為“ Copy If Newer”。 這樣,本機DLL將被復制到項目的輸出文件夾以及引用該項目的每個項目中。 這樣,我不必記住任何東西。 本機DLL將被復制到每個相關項目的本地文件夾中。

這似乎是一個很好的解決方案。 但是msbuild命令似乎不能巧妙地處理這種情況。 例如,假設項目A直接使用本機DLL,並且我將本機DLL添加到項目A。項目B指代項目A,項目C指代項目B和項目A。如果使用msbuild生成解決方案,則本機DLL將是重復復制3次到項目C的輸出文件夾,一次復制到項目A,一次復制到項目B,一次復制到項目B,復制到項目A。在我的大型解決方案中,依賴項鏈接的末尾無論“復制較新”設置如何,本機DLL都會以指數方式多次復制到同一輸出文件夾。 這將花費大量時間來構建整個解決方案。

現在我完全不知道什么是最適合我的情況的解決方案。 對於使用本機DLL的任何人,您如何部署DLL,因此1.既方便在開發人員機器(編譯並運行)和用戶計算機(安裝並運行)上進行部署,2.大型團隊中的開發人員沒有在他或她向解決方案添加新項目/安裝程序時記住任何東西,3.足夠聰明的構建方式,避免了不必要的重復操作。 謝謝您的任何提示,網上教程,建議或提前的聰明教導。

通常,我們要做的是使所有\\ bin目錄都成為指向公共目錄的符號鏈接。 這樣可以避免VS對所有引用所做的所有傳遞副本,並且可以將大型解決方案的全新構建速度提高到10-20倍。

我們使用以下powershell腳本來設置符號鏈接:

param($linkTarget={throw "Link target must be specified"}, $rootDir=".")

ls $rootDir -Recurse -Include *.csproj | % { $_.DirectoryName } | % { Join-Path $_ -ChildPath "bin" } | % {

  Write-Host "Creating link from $_ to $linkTarget"
  if (Test-Path $_)
  {
    Remove-Item -Force -Recurse $_
    cmd /c rd $_
  }

  cmd /c mklink /D $_ $linkTarget
}

符號鏈接需要Vista或Win7。 如果在XP上,可以通過將對mklink的調用替換為對junction.exe的調用來代替使用結點。

默認情況下,它必須以管理員身份運行。

對於初學者,除非沒有其他選擇,否則避免使用構建后事件。 生成后事件不受管理的性質往往會使生成失敗並且可維護性較低。

“如果較新則復制”標志可能有些la腳,但可以向您保證:1)所需的依賴項將被復制到輸出2)它不會使構建失敗3)實際上沒有可維護性。

其次,可以通過僅使用“ Copy If Newer”標志設置構建鏈中的最后一個項目來減少冗余復制,例如:項目A直接引用DLL但將其復制到輸出,項目C通過以下方式間接指向項目A項目B,並且具有對DLL的虛擬引用,並啟用了“如果更新則復制”。

史蒂夫,

我一直都將本機dll添加到我的項目中,而將dll作為內容添加到項目中並沒有問題。 您實際上可以將必要的dll添加為項目鏈接,而不是實際內容。 這樣,dll將不會被復制到項目文件夾以及目標文件夾中。

這是devx的解釋:

要添加共享文件,請打開對話框以使用“項目” |“選擇”來選擇現有文件。 添加現有項菜單項,然后選擇要包括的文件。 然后,不要單擊“打開”按鈕,而是單擊該按鈕左側的箭頭,然后從下拉列表中單擊“鏈接文件”。 這樣,您可以鏈接到原始文件,而不是其本地副本。

您是否將所有項目都構建到公共解決方案目標目錄中,即.. \\ bin \\ debug? 這可能會減少不必要的副本。

將項目鏈接添加到dll絕對比在構建事件中復制要容易維護。

在項目設置中必須有一些“狡猾”的東西(例如循環引用)來引起無限的復制循環-但是找到它可能很棘手和/或很耗時。

我會嘗試兩件事:

  • 關閉“較新”標志,看看它是否對您的問題有影響。 復制單個dll不太可能極大地影響構建時間,並且當文件的日期戳不清時,使用此選項可能會出現問題。 (我不希望這會導致重復的復制嘗試)

  • 嘗試對xcopy使用構建后事件來復制文件,而不要依賴自動系統。 然后,您將完全控制一個簡單的系統,而不用擔心為什么一個聰明的系統不起作用。

我個人將本機DLL和程序集DLL視為一個實體。 將鏈接添加到文件是一種方法。 或者,您可以有一個單獨的主構建腳本,以完善您的項目和安裝程序。

例如,我有一個Library.msbuild文件,該文件運行源.csproj的MsBuild任務作為構建目標。 我的部署目標使用復制任務將dll從source \\ library \\ LibraryName \\ bin \\ Configuration * .dll復制到library \\ LibraryName。 對於我需要構建的所有源文件,我都有一個庫位置,另一個是主項目引用的所有bin。

這是整個Library.msbuild腳本:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
        <ProjectDirectory>library\AspNetMvc\DataAnnotationsModelBinder\src</ProjectDirectory>
        <LibraryDirectory>..\library\AspNetMvc</LibraryDirectory>
    </PropertyGroup>
    <ItemGroup>
       <CompiledBinaries Include="$(ProjectDirectory)\bin\$(Configuration)\*.dll" />
    </ItemGroup>

    <Target Name="Clean">
        <MSBuild Projects="$(ProjectDirectory)\Microsoft.Web.Mvc.DataAnnotations.csproj"
        Targets="Clean" Properties="Configuration=$(Configuration)" />
    </Target>

    <Target Name="PreBuild" DependsOnTargets="Clean">
    </Target>

    <Target Name="Build" DependsOnTargets="PreBuild">
        <MSBuild Projects="$(ProjectDirectory)\Microsoft.Web.Mvc.DataAnnotations.csproj"
        Targets="Build" Properties="Configuration=$(Configuration)" />
    </Target>

    <Target Name="Deploy" DependsOnTargets="Build">
        <Copy SourceFiles="@(CompiledBinaries)" DestinationFolder="$(LibraryDirectory)"/>
    </Target>
</Project>  

在您的實例中,我將Deploy復制任務移至PreBuild或完全刪除它,以依賴於復制dll的Add Existing方法。 目的是當您運行\\調試項目時,所有內容都是相對於bin的。 如果要從.NET DLL中分離本機,甚至可以使用bin \\ win32。

現在,每個構建都是通過.build.cmd批處理文件(一鍵生成)完成的,該文件就是這樣: C:\\Windows\\Microsoft.NET\\Framework\\v3.5\\MSBuild Library.msbuild /t:Deploy 您可以自由地在構建后但部署之前在測試中添加更多目標,例如測試。

如果您使用的是WiX或任何其他類型的安裝程序,則應該能夠為文件本身使用相對路徑。 我有一個頂級的staging \\目錄,從source \\ install \\(.. \\ .. \\ staging \\ icky,是的,沒問題,但是可以使用)進入。 最壞的情況是,您可以將登台目錄放置在安裝路徑內的某個位置。

在大多數情況下,您不必擺脫.csproj或.wixproj文件的抽象MsBuild所困擾。 之前/之后構建遇到一個非常低的上限,但是我發現自己現在幾乎在每種情況下都選擇這種方法。

看到這個職位: http : //blog.alexyakunin.com/2009/09/making-msbuild-visual-studio-to.html

它說明了如何自動將第N級依賴項復制到Bin文件夾中。

如果您有一些甚至沒有間接引用的程序集,則可以創建另一個程序集(例如MyProject.ThirdPartyMagnet ),從該項目中引用該程序集,並從需要將所有程序集復制到其中的項目中引用MyProject.ThirdPartyMagnet

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM