共用方式為


執行階段如何定位元件

備註

本文專屬於 .NET Framework。 它不適用於較新的 .NET 實作,包括 .NET 6 和更新版本。

若要成功部署 .NET Framework 應用程式,您必須瞭解 Common Language Runtime 如何找出並系結至構成應用程式的元件。 根據預設,執行階段會嘗試與應用程式所建置的組件的確切版本進行綁定。 此預設行為可由組態檔設定覆寫。

當 Common Language Runtime 嘗試定位並解析組件參考時,會執行多個步驟。 下列各節將說明每個步驟。 描述執行階段如何定位元件時,通常會使用探測一詞;它是指一組啟發式方法,用來根據元件的名稱和文化來尋找元件。

備註

您可以使用包含在 Windows SDK 中的元件系結 記錄查看器(Fuslogvw.exe)來檢視記錄檔中的系結資訊。

啟動綁定

當執行階段嘗試解析另一個組件的參考時,定位和綁定至組件的過程便開始。 此參考可以是靜態或動態。 編譯程式會在建置時記錄元件指令清單元數據中的靜態參考。 動態參考是在即時運行時,透過呼叫各種方法而生成,例如 Assembly.Load

參考元件的慣用方式是使用完整參考,包括元件名稱、版本、文化特性和公鑰令牌(如果有的話)。 運行時間會使用這項資訊來尋找元件,並遵循本節稍後所述的步驟。 不論參考是靜態或動態元件,執行階段都會使用相同的解析過程。

您也可以提供呼叫方法,只提供元件的部分資訊,例如只指定元件名稱,來對元件進行動態參考。 在此情況下,只會搜尋應用程式目錄來尋找元件,而且不會進行其他檢查。 您可以使用任何各種方法來載入元件,例如 Assembly.LoadAppDomain.Load,作為部分參考。

最後,您可以使用 之類的Assembly.Load方法建立動態參考,並只提供部分資訊;然後使用應用程式組態檔中的qualifyAssembly<元素來限定參考>。 此元素可讓您在應用程式組態檔中提供完整的參考資訊(名稱、版本、文化特性,以及如果適用的話,公鑰令牌),而不是在您的程式代碼中。 如果您想要完整限定應用程式目錄外部元件的參考,或想要在全域程式集緩存中參考元件,但想要在組態檔中指定完整參考,而不是在程式碼中指定完整參考,則可以使用這項技術。

備註

這種類型的部分參考不應該與在數個應用程式之間共用的元件搭配使用。 因為組態設定會套用於每個應用程式,而不是每個組件,因此使用此部分參考類型的共用組件會要求,每個使用共用組件的應用程式在其組態檔中具有限定資訊。

運行時會使用下列步驟來解析元件參考:

  1. 透過檢查適用的組態檔,包括應用程式組態檔、發行者原則檔和系統組態檔,以判斷正確的元件版本。 如果組態檔位於遠端電腦上,則運行時間必須先找出並下載應用程式組態檔。

  2. 檢查元件名稱之前是否已系結至 ,如果是,則使用先前載入的元件。 如果先前載入元件的要求失敗,要求會立即失敗,而不會嘗試載入元件。

    備註

    .NET Framework 2.0 中引入了元件系結失敗的快取功能。

  3. 檢查全域程式集緩存。 如果找到該元件,運行時間會使用此元件。

  4. 使用下列步驟檢測組件

    1. 如果組態和發行者原則不會影響原始參考,且系結要求使用 Assembly.LoadFrom 方法建立,執行階段會檢查位置提示訊息。

    2. 如果在組態檔中找到程式代碼基底,運行時間只會檢查這個位置。 如果此探查失敗,運行時間會判斷系結要求失敗,而且不會發生其他探查。

    3. 使用探查一節中所述的啟發式方法來探查配件組裝。 如果在探查之後找不到元件,運行時間會要求 Windows Installer 提供元件。 這可作為隨選安裝功能。

      備註

      沒有強名稱的元件不會進行版本檢查,執行階段也不會檢查全域元件快取中的強名稱元件。

步驟 1:檢查組態檔

元件系結行為可以根據三個 XML 檔案,在不同的層級設定:

  • 應用程式組態檔。

  • 發行者原則檔案。

  • 計算機組態檔。

這些檔案遵循相同的語法,並提供資訊,例如系結重新導向、程序代碼的位置,以及特定元件的系結模式。 每個組態檔都可以包含 <重新導向系結過程的 assemblyBinding 元素>assemblyBinding< 專案的子專案>包含 <dependentAssembly> 元素dependentAssembly< 元素的>子系包括 <assemblyIdentity> 元素<bindingRedirect> 元素<codeBase> 元素

備註

您可以在三個組態檔中找到組態資訊;並非所有元素在所有組態檔中都有效。 例如,系結模式和私人路徑資訊只能位於應用程式組態檔中。 如需每個檔案中包含的資訊完整清單,請參閱 使用組態檔設定應用程式

應用程式組態檔

首先,公用語言執行平台會檢查應用程式組態檔,以取得覆寫儲存在呼叫封裝清單中版本資訊的相關信息。 應用程式組態檔可以使用應用程式來部署,但不需要應用程式執行。 通常,擷取此檔案幾乎是瞬間的,但在應用程式基底位於遠端電腦上的情況,例如在 Web 型案例中,必須下載組態檔。

針對客戶端可執行檔,應用程式組態檔位於與應用程式可執行檔相同的目錄中,且其基底名稱與具有 .config 擴展名的可執行檔相同。 例如,C:\Program Files\Myapp\Myapp.exe 的組態檔是 C:\Program Files\Myapp\Myapp.exe.config。在瀏覽器型案例中,HTML 檔案必須使用 <連結> 項目來明確指向組態檔。

下列程式代碼提供應用程式組態檔的簡單範例。 這個範例將TextWriterTraceListener新增至Listeners集合,以啟用將偵錯資訊記錄在檔案中。

<configuration>
   <system.diagnostics>
      <trace useGlobalLock="false" autoflush="true" indentsize="0">
         <listeners>
            <add name="myListener" type="System.Diagnostics.TextWriterTraceListener, system version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" initializeData="c:\myListener.log" />
         </listeners>
      </trace>
   </system.diagnostics>
</configuration>

發行者原則檔案

其次,運行時期會檢查發行者原則檔案(如果存在)。 發佈者政策檔案由元件發佈者散發,作為共用元件的修正或更新。 這些檔案包含由共用元件發行者所發出的相容性資訊,該共用元件會將元件參考導向至新版本。 不同於應用程式和計算機組態檔,發行者原則檔案會包含在其本身的元件中,必須安裝在全域程式集緩存中。

以下是發行者原則配置檔的範例:

<configuration>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">

            <dependentAssembly>
                <assemblyIdentity name="asm6" publicKeyToken="c0305c36380ba429" />
                <bindingRedirect oldVersion="3.0.0.0" newVersion="2.0.0.0"/>
            </dependentAssembly>

        </assemblyBinding>
    </runtime>
</configuration>

若要建立組件,您可以使用 Al.exe (Assembly Linker) 工具,並執行以下命令:

Al.exe /link:asm6.exe.config /out:policy.3.0.asm6.dll /keyfile: compatkey.dat /v:3.0.0.0

compatkey.dat 是強名稱金鑰檔案。 此命令會建立一個強名稱組件,您可以放在全域組件快取中。

備註

發行者原則會影響使用共用元件的所有應用程式。

發行者政策配置檔會覆寫來自應用程式的版本資訊(也就是來自組件清單或應用程式組態檔的資訊)。 如果應用程式組態檔中沒有語句可重新導向元件指令清單中指定的版本,發行者原則檔會覆寫元件指令清單中指定的版本。 不過,如果應用程式組態檔中有重新導向語句,發行者原則會覆寫該版本,而不是指令清單中指定的版本。

當共用元件更新時,會使用發行者原則檔案,所有使用該元件的應用程式都應採用該元件的新版。 除非應用程式組態檔強制執行安全模式,否則發行者原則檔中的設定會覆蓋應用程式組態檔中的設定。

安全模式

發行者原則檔案通常會明確安裝為 Service Pack 或程式更新的一部分。 如果升級的共用元件發生任何問題,您可以使用安全模式忽略發行者原則檔案中的覆寫。 安全模式是由 <publisherPolicy apply=“yes|no”/> 元素所決定,該元素只位於應用程式組態檔中。 它會指定是否應該從系結程式中移除發行者原則設定資訊。

您可以針對整個應用程式或選取的元件設定安全模式。 也就是說,您可以關閉組成應用程式的所有元件的原則,或針對某些元件開啟它,但不能開啟其他元件。 若要選擇性地將發行者原則套用至組成應用程式的元件,請設定 <publisherPolicy apply=no/> 並指定要使用 < 元素影響哪些>元件。 若要將發行者原則套用至組成應用程式的所有元件,請設定 <publisherPolicy apply=no/> 且沒有相依元件元素。 如需設定的詳細資訊,請參閱 使用組態檔設定應用程式

計算機組態檔

第三,運行時間會檢查機器組態檔。 這個稱為 Machine.config的檔案位於安裝運行時間之根目錄的 Config 子目錄中的本機電腦上。 系統管理員可以使用此檔案來指定該計算機本機的元件系結限制。 計算機組態檔中的設定優先於所有其他組態設定;不過,這並不表示所有組態設定都應該放在這個檔案中。 系統管理員原則檔案所決定的版本是最終版本,而且無法覆寫。 在 Machine.config 檔案中指定的覆寫會影響所有應用程式。 如需組態檔的詳細資訊,請參閱 使用組態檔設定應用程式

步驟 2:檢查先前參考的元件

如果在先前的呼叫中已經要求過相同的組件,Common Language Runtime 會使用已載入的組件。 在命名組成應用程式的元件時,這可能會產生影響。 如需命名元件的詳細資訊,請參閱 元件名稱

如果先前對元件的要求失敗,則元件的後續要求會立即失敗,而不會嘗試載入元件。 從 .NET Framework 2.0 版開始,會快取元件系結失敗,並使用快取的信息來判斷是否嘗試載入元件。

備註

若要還原為 .NET Framework 1.0 和 1.1 版的行為(該版本不會快取系結失敗),請在組態檔中包含 <disableCachingBindingFailures> 元素

步驟 3:檢查全域程式集緩存

針對強名稱元件,系結程式會繼續查看全域程式集緩存。 全域程式集緩存會儲存電腦上數個應用程式可以使用的元件。 全域程式集緩存中的所有元件都必須具有強名稱。

步驟 4:透過程式碼庫或探查來定位程序集

使用呼叫組件的參考和組態檔中的資訊來判斷正確的組件版本之後,以及在檢查全域組件快取之後(僅適用於強名稱組件),Common Language Runtime 會嘗試尋找該組件。 尋找元件的程式牽涉到下列步驟:

  1. 如果在應用程式組態檔中找到codeBase<元素,運行時間會檢查指定的位置。> 如果找到相符的組件,則會使用該組件,而且不會進行探查。 如果找不到元件,系結要求就會失敗。

  2. 執行階段接著會使用本節隨後規範的規則來探查參考的元件。

備註

如果您在目錄中有多個版本的元件,而您想要參考該元件的特定版本時,則必須使用<codeBase>元素,而不是probingprivatePath元素的<屬性>。 如果您使用 <探查> 元素,執行時會在第一次找到符合簡單元件名稱的元件時停止探查,不論它是否正確符合。 如果是正確的匹配,則使用該元件。 如果不是正確匹配,探測會停止並綁定失敗。

透過程式碼庫尋找組件

您可以使用組態檔中的codeBase元素來提供 <程式代碼基底> 資訊。 執行階段嘗試探查參考元件之前,一律會檢查此程式碼庫。 如果包含最終版本重新導向的發行者原則檔案也包含 <codeBase> 元素,則使用該 <codeBase> 元素。 例如,如果您的應用程式組態檔指定<codeBase>元素,而覆寫應用程式資訊的發行者原則檔案也會指定<codeBase元素,則會使用發行者原則檔中的codeBase><元素。>

如果在<codeBase>元素所指定的位置找不到相符專案,系結要求會失敗,而且不會採取任何進一步的步驟。 如果運行時間判斷元件符合呼叫元件的準則,則會使用該元件。 當載入由<codeBase>元素指定的檔案時,執行執行階段會檢查確認名稱、版本、文化特性和公鑰是否符合呼叫組件的參考。

備註

應用程式根目錄外的參考元件必須具有強名稱,而且必須安裝在全域程式集緩存中,或使用 codeBase< 元素指定>

透過探查定位組件

如果應用程式組態檔中沒有 <codeBase> 元素,運行時間會使用四個準則來探查元件:

  • 應用程式基底,這是執行應用程式的根位置。

  • Culture,這是所參考元件的文化特性屬性。

  • 名稱,指參考的元件的名稱。

  • privatePath < 探查>元素的屬性,是根目錄位置下子目錄的使用者定義列表。 您可以在應用程式組態檔案和受管理的程式碼中使用應用程式域的AppDomainSetup.PrivateBinPath屬性來指定這個位置。 在受控程式碼中指定時,首先探測受控程式碼privatePath,然後探測應用程式組態檔中指定的路徑。

探查應用程式主目錄和文化設定目錄

執行階段一律會在應用程式的基底中開始探測,它可以是 URL 或電腦上的應用程式根目錄。 如果在應用程式基底中找不到參考的元件,而且未提供任何文化特性資訊,運行時間會搜尋任何具有元件名稱的子目錄。 探查的目錄包括:

  • [應用程式基底] / [元件名稱].dll

  • [應用程式基底] / [元件名稱] / [元件名稱].dll

如果針對參考的元件指定文化特性資訊,則只會探查下列目錄:

  • [應用程式基底] / [culture] / [元件名稱].dll

  • [application base] / [culture] / [元件名稱] / [元件名稱].dll

使用 privatePath 屬性探查

除了針對參考元件所命名的文化特性子目錄和子目錄之外,運行時間也會探查使用privatePath探查<項目屬性>所指定的目錄。 使用 privatePath 屬性指定的目錄必須是應用程式根目錄的子目錄。 探查的目錄會根據參考的組件請求中是否包含文化資訊而有所不同。

運行時第一次找到符合參考之簡單組件名稱的組件時,就會停止搜尋,無論它是否正確匹配。 如果是正確的匹配,則使用該元件。 如果不是正確匹配,探測會停止並綁定失敗。

如果包含文化特性,則會探查下列目錄:

  • [application base] / [binpath] / [culture] / [元件名稱].dll

  • [application base] / [binpath] / [culture] / [元件名稱] / [元件名稱].dll

如果未包含文化資訊,則會搜尋下列目錄:

  • [application base] / [binpath] / [元件名稱].dll

  • [application base] / [binpath] / [assembly name] / [assembly name].dll

探測範例

提供下列資訊:

  • 參考的元件名稱:myAssembly

  • 應用程式根目錄: http://www.code.microsoft.com

  • 組態檔中的探測<元素指定: bin>

  • 文化:德國

運行時會探查下列 URL:

  • http://www.code.microsoft.com/de/myAssembly.dll

  • http://www.code.microsoft.com/de/myAssembly/myAssembly.dll

  • http://www.code.microsoft.com/bin/de/myAssembly.dll

  • http://www.code.microsoft.com/bin/de/myAssembly/myAssembly.dll

具有相同名稱的多個元件

下列範例示範如何設定多個具有相同名稱的元件。

<dependentAssembly>
   <assemblyIdentity name="Server" publicKeyToken="c0305c36380ba429" />
   <codeBase version="1.0.0.0" href="v1/Server.dll" />
   <codeBase version="2.0.0.0" href="v2/Server.dll" />
</dependentAssembly>

探查的其他位置

元件位置也可以使用目前的系結內容來判斷。 在使用 Assembly.LoadFrom 方法或在 COM interop 情境中,通常會發生這種情況。 如果元件使用 LoadFrom 方法來參考另一個元件,則呼叫元件的位置會被視為尋找參考元件的提示。 如果找到相符的組件,則會載入該組件。 如果找不到相符項目,執行階段會繼續其搜尋語義,然後查詢 Windows Installer 以提供元件。 如果未提供符合系結要求的元件,則會拋出例外狀況。 如果參考了型別,此例外狀況是在受控代碼中的 TypeLoadException;如果找不到載入的組件,則為 FileNotFoundException

例如,如果 Assembly1 參考 Assembly2,並且 Assembly1 是從 http://www.code.microsoft.com/utils 下載的,那麼該位置會被視為關於如何找到 Assembly2.dll的提示。 然後,在http://www.code.microsoft.com/utils/Assembly2.dllhttp://www.code.microsoft.com/utils/Assembly2/Assembly2.dll中,運行時間會探查元件。 如果在其中一個位置找不到 Assembly2,運行時間會查詢 Windows Installer。

另請參閱