概念:
(一)dotnet中的版本組成
dotnet中的版本由4個物理號碼組成,如圖(一)
圖(一)
在程式集裡面,我們可以通過加上assemblyversion特性來設定它,
如[assembly: assemblyversion("2.0.2.11")]
(二) gac:
計算機範圍內的**快取,它儲存專門安裝的程式集,這些程式集由計算機上的許多應用程式共享。在全域性程式集快取中部署的應用程式必須具有強名稱,乙個程式集如果註冊到了gac裡,被其他程式集合引用的時候,將不會拷貝副本到引用的程式目錄中。 (本文只討論註冊到gac中的程式集)
正文:(1) 我們現在開始寫第乙個元件
它的版本號為 1.0.0.0 有乙個類,包含乙個簡單的方法,該方法返回乙個字串
**如下,我都做了註解
//首先生成強名稱到檔案中
sn –k c:/version.snk
//寫類檔案
v1.cs
using
system;
using
system.reflection;
[assembly: assemblykeyfile(
@"c:version.snk
")]
//因為註冊到gac,所以使用強名稱簽名
[assembly: assemblyversion(
"1.0.0.0
")]
//設定版本號
namespace
v1public
string
getversion()}}
編譯成元件 v1.dll
拷貝這個v1.dll到 資料夾c:/v1
把v1.dll註冊到gac
gacutil –i c:/v1/v1.dll
系統顯示註冊成功
(2) 然後我們編寫乙個控制台程式測試這個元件
testversion.cs
//////
請新增對v1.dll(c:v1v1.dll)的引用,因為是在gac裡面,所以v1.dll不會在本地目錄存在
///using
system;
namespace
testversion}}
編譯後執行(testversion.exe)
螢幕輸出的結果是 :
"你好,我是版本1"
(3) 好了,一切很美好,過了幾年了,我們得公升級程式了
現在來編寫v1.dll公升級版本,版本號為2.0.0.0
v1.cs
using
system;
using
system.reflection;
[assembly: assemblykeyfile(
@"c:version.snk
")]
///使用上面的強名稱
[assembly: assemblyversion(
"2.0.0.0
")]
///注意,這裡已經改了主版本號
namespace
v1public
string
getversion()}}
編譯 成元件 v1.dll
拷貝這個v1.dll到 資料夾c:/v2
把v1.dll註冊到gac
gacutil –i c:/v2/v1.dll
(4) .現在來看看再次執行testversion.exe輸出了什麼東西
是的,和原來的沒有變化還是
"你好,我是版本1"
為什麼不是"你好,我是版本2"?
我們用ilda**.exe開啟程式集testversion.exe 看看
是的,它目前就是使用了版本1.0.0.0
(5) 我們開始進行版本公升級
把testversion.exe使用的版本由1.0.0.0替換成版本2.0.0.0
其實很簡單的,給我們的 testversion.exe
加個配置檔案 testversion.exe.config裡面打入
<?
xml version="
1.0"
?>
<
configuration
>
<
runtime
>
<
assemblybinding xmlns="
urn:schemas-microsoft-com:a**.v1
">
<
dependentassembly
>
<
assemblyidentity name="
v1"publickeytoken="
758fe4e9db9d8251
"/>
<
bindingredirect oldversion="
1.0.0.0
"newversion="
2.0.0.0
"/>
dependentassembly
>
assemblybinding
>
runtime
>
configuration
>
簡單說明:
assemblyidentity 主要進行程式集合的標識
其中 name是程式集的名稱 publickeytoken是公匙的標記;如何獲得這些資訊呢?很簡單,開啟%systemdir%/assembly (我的是c:/winnt/assembly)
可以看到這些資訊(如下圖,你的機器上可能和我不一樣)
可以看到有兩個v1(正確,我們確實註冊了兩個進去,版本也對) 我們開始用的是1.0.0.0的,記下公匙token 寫到publickeytoken
bindingredirect 節點主要配置版本如何跳轉
oldversion="1.0.0.0" newversion="2.0.0.0" 很清楚的,就是如果testversion.exe使用的v1.dll是舊版本的,程式集版本號為1.0.0.0,那麼就使用新的,版本號為2.0.0.0的程式集
需要注意的是,oldversion 可以使用範圍來界定,如 oldversion="1.0-1.9" 但是如果沒有使用範圍表示法的話,一定要寫全版本號
newversion 不可以使用範圍表示法,請寫全版本號
好了,現在再次執行testversion.exe
輸出的是: "你好,我是版本2",掌聲!!!
就是怎麼簡單!
(6) 如果現在我們用ilda**.exe開啟程式集testversion.exe,看到的內容將沒有變化
確實,是配置檔案起了作用,整個過程沒有對呼叫程式testversion.exe的**做半點改動!
(7) 配置錯了會怎麼樣?:
有可能的錯誤,比如newversion寫錯了,根本沒這個公升級版本,將會丟擲異常system.io.filenotfoundexception,請注意處理
強名稱保護
用 籤強名稱我會 中 sn k key.snk csc keyfile key.snk cs 強名稱的去除 頭中的flag項,去除comimage flags strongnamesigned標誌 頭中的strongnamesignature,與 為 表中的 項,送去0 0001 標識 通常變後為0...
強名稱(3)強名稱的脆弱性
通過前文共同體驗了強名稱對程式集的保護方式和原理,但是這種保護的強度到底有多大呢?能有效地防禦惡意篡改者嗎?先看下面的例子。回到上篇文章的 清單 9 7,重新對 strongnamereferencelib 專案進行強名稱簽名,然後編譯 strongname 專案。在 strongname 專案的b...
強名稱程式集不能引用非強名稱程式集
想生成乙個強名稱程式集,引用了乙個非強名稱程式集裡的型別,結果在編譯時出錯 error cs1577 程式集生成失敗 引用的程式集 mytypes 沒有強名稱 檢視msdn中編號為cs1577的編譯器錯誤,顯示如下資訊 程式集生成失敗 原因 編譯的程式集生成部分失敗。有關更多資訊,請參見 alink...