2010-03-20 60 views
15

我們對Win Forms項目有一個非常有趣的問題。它已經解決了。我們知道發生了什麼,但我們想知道它爲什麼發生。這可能有助於未來出現類似問題的其他人。.NET參考「複製本地」基於GAC的內容設置真/假

WinForms項目在我們的客戶端PC上失敗。該錯誤是一個模糊的kernel.dll錯誤。該項目在其他3臺PC上運行良好。

我們發現我們的發佈文件夾中缺少.DLL(log4net.dll - 一個非常流行的開源日誌記錄庫)。它以前在我們的發佈文件夾中。爲什麼在這個最新版本中缺少它?

它丟失了,因爲我必須在使用log4net.dll的Dev框上安裝了一個程序,並將它添加到全局程序集緩存中。

當我檢查解決方案的log4net.dll引用時,它們被更改爲「copy local = FALSE」。他們必須自動更改,因爲log4net.dll出現在我的GAC中。

這裏就是我的問題開始:

爲什麼我的log4net.dll參考獲得來自COPY LOCAL = TRUE改爲複製本地= FALSE?我懷疑這是因爲它被另一個程序添加到我的GAC中。

我們該如何防止這種情況再次發生?現在,如果我安裝了一個使用公用庫的軟件,並將其添加到我的GAC,那麼引用該DLL的SLN將從Copy Local TRUE更改爲FALSE。

+0

什麼大會? http://en.wikipedia.org/wiki/Global_Assembly_Cache? – 2010-03-20 01:18:07

回答

6

發生這種情況的原因是,如果在GAC中安裝了程序集,則「複製本地」= True時沒有任何意義。由於該本地副本永遠不會被使用,所以GAC總是首先被搜索。如果將它保持不變會導致嚴重的混淆,你會認爲你使用的是本地副本,但是取而代之。如果您沒有注意到,更改它也會導致混淆,這可能是在解決方案加載時用消息框解決的。

Log4net是一個麻煩製造者,在沒有任何部署過程的情況下,有太多的版本可以確保這些版本互不相容。 Apache顯然不想解決這個問題,而是把它留給程序員。擁有依賴於Log4net的產品以及對感知的DLL地獄風險做些事情在某種程度上是不可避免的。作爲回報給你一個DLL地獄問題。

乾淨簡單的答案,除了意識到你的機器上安裝了什麼。考慮發佈到connect.microsoft.com以在Visual Studio自動更新複製本地屬性時要求警告。這是一個合理的問題。

+0

From nobugz:「考慮發佈到connect.microsoft.com以在Visual Studio自動更新」複製本地「屬性時要求警告。」 謝謝,bugz。這是一個好主意。 「複製本地」更改時的通知會很好。這是VS2K5,順便說一句。它讓我想起了VS2K3的神奇標記。謝謝你的洞察力。 – 2010-03-20 02:04:43

+0

誠然,還有+1,儘管我不會完全將責任歸咎於Apache(或原作者Neoworks) - 我懷疑他們是否預料到特別部署會變得多麼廣泛。 *大多數*開源產品並不像試圖讓自己進入GAC的方式那麼傲慢,而且如果Apache現在改變了模型,它會破壞現有的代碼(如此處所示)。 – Aaronaught 2010-03-20 02:07:15

+0

有什麼辦法來防止它改變?我懷疑,「這是設計。」如果這是真的,那麼我需要定期檢查ref,如果我的開發/構建箱是我的主要PC,並且我經常添加/刪除東西? – 2010-03-20 02:11:28

0

你可以通過在msbuild/proj文件中添加一個hintpath來確保使用了你的嗎?

從上面的鏈接:

HintPath:相對或絕對路徑組件

2

在運行時,程序集必須位於以下兩個位置之一:項目的輸出路徑或全局程序集緩存(請參閱使用程序集和全局程序集緩存)。如果項目包含對不在這些位置之一中的對象的引用,則在構建項目時,必須將引用複製到項目的輸出路徑。 CopyLocal屬性指示是否需要創建此副本。如果該值爲真,則複製參考。如果爲false,則不會複製該參考。

CopyLocal的項目分配的值是按照下面的順序來確定:

  1. 如果引用另一個項目中,被稱爲項目到項目引用,則該值是真實的。
  2. 如果在全局程序集緩存中找到該程序集,則該值爲false。
  3. 作爲一種特殊情況,mscorlib.dll引用的值爲false。
  4. 如果在Framework SDK文件夾中找到該程序集,則該值爲false。 否則,該值爲true。

問候...... 繆斯VSExtensions

1

我正好遇到我們構建服務器上這個問題了。這是Visual Studio非常令人討厭(和意外)的行爲。兩種解決方法:

  1. 從GAC中刪除程序集。
  2. 添加一個PostBuild事件以手動將程序集複製到輸出目錄中。
1

我在我們的構建服務器上找到了我們的解決方案。

問題: 在沒有理由的特定日期(我現在假設該文件已添加到GAC中)程序集System.Web.MVC.dll從我們的許多項目中消失。我相信這適用於有問題的任何DLL。

解決方案: 在Visual Studio中更改引用(假設複製本地已經爲True)。

  1. 更改複製本地=真複製本地=假
  2. 更改複製本地回真
  3. 公告中的.csproj提交<Private>True</Private>加入。
  4. 立即編譯,即使消息保持不變,您也會看到dll確實包含在內。

解決方案2: 手動添加<private>True</private>屬性。

結論: 我對<Private>的理解是複製本地,所以如果複製本地= True私人屬性應該被添加,但在我們的情況下,至少它不是。

附加註意事項:

  1. 使用Visual Studio 2013和2015
  2. 使用的msbuild 12和14
  3. 使用TFS生成模板測試測試進行測試。
  4. 我們的代碼已經從2008年升級到2015年的visual studio,該標誌在那段時間可能已經變得混亂了,但是直到程序集以某種方式添加到GAC之後,問題纔開始。

最終結果是:

<Reference Include="System.Web.Mvc, Version=4.0.0.1, Culture=neutral,PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> 
<SpecificVersion>False</SpecificVersion> 
<HintPath>packages\Microsoft.AspNet.Mvc.4.0.40804.0\lib\net40\System.Web.Mvc.dll  </HintPath> 
     <Private>True</Private> 
    </Reference>