Pages

2009-09-30

Microsoft Web Platform Installer 2.0

為了便利ASP.NET的Hosting環境,微軟推出一個簡易型的Web Platform
透過一個線上安裝檔(官方沒有離線版),就可以把IIS, MVC, PHP等整合建構。

一直以來,嵌入式的ASP.NET Web Server應用,
我一直使用Cassini Web Server,既然微軟有新的玩意,或許管理介面上會更強也說不定。

安裝Web Platform 2.0 RTW時,發現Core Web Server竟只有IIS 5.1(還以為是IIS 7),
不知是否是因為OS是XP才導致只能裝IIS 5.1?
想說舊歸舊能跑就好,又看到以下連線限制就放棄了:
SNAGHTMLcb36569

其實XP或Vista的光碟都有內含IIS Server,原以為新的Web Platform能提供更簡精好用的平台
倘若限制一大堆,倒不如就裝Cassini Web Server。

2009-09-29

網路授權啟用機制 - License管理平台

資料庫設計可以規劃為代理商(Agent)架構機制,因為有些軟體授權機制是先跟代理商談好合作條件
讓代理商自行向客戶發行軟件並啟用License,開發商再跟代理商用月結方式依啟用數量取款。

基於此需求,開發商要提供代理商一個可管理License檔的Web平台,
依顧客所購買的軟體版本或功能,創造出不同的License檔案。
SNAGHTML7a7a847
其中啟用Quota並不侷限1套,讓一個License可以支援多數量的啟用。

代理商能查看購買顧客的啟用狀況,對於異常使用可隨時中止(Cancel)或刪除未啟用的LicenseKey:
SNAGHTML7a6d6e5

顧客歷史啟用記錄內容,可以記錄Client平台的相關資訊、版本及IP Address,避免統計結帳時的糾紛。
在此架構中,代理商可以依合約規定自由發行License,為了防止該代理商帳號被非法使用,
代理商帳號也有一個Credit限制設計,其所發行的任何License之啟動總數量,不能超過此值。

此系列文章,主要在闡述軟件網路授權啟用的機制設計,
身為軟件開發商的你,不要再花時間建立序號或郵寄USB硬體鎖了(除非單價高)。

專案源碼交付的程度範圍

很多公司會購買專案原始碼(Source Code),對於專案上所使用的一些DLL也要求一併交付源碼
這點常常令開發公司對於源碼交付程度的定義產生困擾,
其實交付源碼為非無上綱地交付,正確的定義應該是指牽扯到專案邏輯部分的源碼範圍。

買源碼就是為了日後要修改或增加新功能,因此只要跟專案邏輯有關的源碼,
開發公司都該交付,但若開發公司使用3-Party元件(涉及授權)或WinAPI, OpenSource元件,
因為這些Component本身並不牽扯到專案邏輯部分,就可以不用交付。
在專案簽約時雙方最好能對源碼交付的範圍有共識,即可避免無謂的困擾。

倘若覺得這些*.dll存在是很礙眼的,可以在編譯完成後使用ILMerge.exe程式,
把*.exe, *.dll全部打包成單一執行檔就行了。

2009-09-28

Windows Server 2003 R2安裝升級步驟

Windows Server 2003 R2 是 Windows Server 2003 作業系統的更新發行
相關的更新說明,請詳見官方中文版FAQ:
http://www.microsoft.com/taiwan/windowsserver2003/R2/R2FAQ.mspx

從MSDN下載會有兩個CD ISO檔,安裝步驟為:
1. 安裝CD1的Windows 2003 with SP2版本,查看「我的電腦」右鍵「屬性」。
SNAGHTMLfc99667
2. 執行Win2003 Service Pack2安裝檔(WindowsServer2003-KB914961-SP2-x86-CHT.exe, 內建的版號不一致),再執行CD2的Upgrade R2 (127MB),否則會出現以下問題:
SNAGHTMLfca8c1b
3. 放入R2光碟選擇「升級」,它只會裝更新部分,一下子就好了。
SNAGHTMLfcd426f
4. 進行Windows Update更新,約有68個更新。

2009-09-26

網路授權啟用機制 - 驗證啟用服務

當Client端軟件進行License啟用時,它會負責先檢驗其License檔格式正確與否,
並讀取到一個License Key,再進行與遠方主機的TCP/IP訪問,
因此官方主機必須實作一個驗證啟用服務,它是一個TcpListener機制。

TCP訪問流程(所有Socket資訊都經過對稱式加密):
1. 當Client連線時,先進行AUTH密碼確認。
2. Client傳來硬體平台資訊(XML格式)及安裝版本資訊、IP Address。
2. 讀取License Key,比對資料庫是否已存在,並調出客戶資訊 (如購買套數/版本/啟動次數限制)。
3. 比對啟用Quota是否超過限制,相同硬體上的重複啟用不計次。
4. 回應Client端是否啟用驗證通過,並寄發Email通知管理員。

SNAGHTML83f4ad0

假如通過驗證,Client端軟件就會把安裝平台硬體資訊及擷自伺服主機的資訊,
產生一個License.lic檔(經過加密Binary檔),放置在軟體安裝目錄內,軟件主程式執行時會讀取該檔。

官方資料庫會記錄每次Client的連線啟用資訊,包含時間, IP, 安裝軟件版本、安裝目錄、硬體/OS版本資訊,
幾乎什麼Client系統內的資訊都可以收集,用來當作日後的違規使用證明。

2009-09-25

網路授權啟用機制 - License檔案

為了有效保護商業軟件,使用序號方式已無法有效防制盜版擴散,
現在普通的軟體保護機制就是使用網路啟動,當用戶購買軟件時,先發予一個加密的License檔案,
軟體啟用時指定該檔,即可連線至官方啟用主機進行驗證,官方能控制啟用次數及資訊。
SNAGHTML81ebf72

官方所給予用戶的License檔,除了記錄user資訊及所購買的版本限制外
主要是其內含有一個Unique License Key,它也會先登記在官方伺服資料庫內,
待上傳時進行資料存在比對。

實作該License檔的方式,.NET實作方式可以將物件序列化成二進位檔
再將檔案予以加密(使用XOR Array或對稱式加密),
然而.NET的序列化在解開時必須符合Assembly Namespace完整名稱,
一些知名的Assembly加殻混淆保護工具常會破壞此Namespace的資訊,造成還原上的問題。
更況何非.NET的程式語言,亦無法有效支援此License的讀取,故不推薦此方式。

針對License檔實作方式,筆者使用一個固定Size的Byte[]陣列,再使用Struct Mapping對應方式
讓Byte[]與結構變數(Struct)能互相轉換,並方便寫入檔案。
檔案會做XOR Checksum機制,再予以不等長對稱加密方式保護。
SNAGHTML81fe6cf

當軟件進行網路啟用成功時,會產生出一個License.lic檔案,其實它的結構跟原來的License檔一樣
只差別在內容上的差異,寫入了安裝平台的硬體資訊及限制資訊(如版本控制、使用期限)

每當軟件程式啟動時,就先判斷該驗證過的*.lic檔是否存在,
再進行合法格式讀取(比對解密還原後的size及checksum),假如成功就轉成Struct變數
再針對內容資訊作邏輯流程控制。

這個讀取License的程序通常寫在一個method,為了避免.NET Assmebly被反組譯註解內容(雖然會混淆)
最好在method裏把讀取到的License Struct變數指定為global變數,於重要的功能使用前再比對該global變數值,
類似網站的login畫面雖被駭客繞過去,但後面的操作是需要其登入程序裏獲取的Session值。

2009-09-18

Vista空資料夾無法刪除

在Vista下有時候發現某些空資料夾無法刪除
使用了Process Explorer去查看系統佔住的handle也無所獲
進安全模式或找一些強制刪檔的軟件,都仍會出現:「找不到此項目」

今天終於找到解決之道:
1. 進入命令提示模式 cmd
2. RD “D:\abc /”  (重點在最後引號加上斜線)

就這樣,該死的空資料夾就消失了。
解決來源: http://support.microsoft.com/default.aspx/kb/811176/zh-tw

2009-09-17

封包資料驗證

無論是網路UDP封包或RS232的串列資料,它們的傳輸不保證內容順序及資料是正確的,
因此若要實作資料驗證機制的話,最基本的封包(Package或Frame)結構定義如下表:

起始字

資料長度

資料

檢查碼

1 byte

2 bytes

N bytes

1 bytes

1. 起始字: 如固定以0xAB開頭
2. 資料長度: 代表後面資料的陣列長度,通常low byte在前,high byte在後地組成2個bytes。
3. 資料: 一個符合前面長度的byte[]陣列,有可能是0長度。
4. 檢查碼: 通常是從資料長度byte至資料陣列的最後一個byte作xor sum。

由於接收資料的socket或rs232 reader,每次事件觸發可能只收到破碎的片段資料
因此必須準備一個自訂Queue來累績存放讀取buffer進來的raw data,
當Queue的長度大於一個封包定義的最小長度時,即進行Queue的Parsing工作。

從Queue映射出一個Shadow Array(固定長度),然後使用一個loop來比對起始字
接著取得其資料長度(Data Length)。這兩個代表資料長度的bytes可能是錯誤的值,
因此要檢查其宣稱的長度值,是否在封包定義最小長度與整個映射array長度之間。

若是,則依Data Length值跳至該封包最後一個byte作checksum驗證,若正確則是有效封包區段,
直接作長度跳躍去驗證下一個封包片段起始字。
反之,若Data Length及checksum檢查失敗,則array position加1繼續比對起始字。

當中值得注意的是,當checksum失敗的話代表其區域內的bytes值都不可靠,
因此即使Data Length所宣稱值符合在Array範圍內,亦不可直接作整個長度的跳躍
只能postition + 1,繼續比對下一個起始字byte。

另外,需要設定一個queue已讀取位置的read position變數,記錄checksum失敗時的讀取位置,
避免重複再對這些不可靠的區段作parsing。等到遇到一個有效封包結構進來時,
再一次回收這些空間,該read position變數再設為0。

SNAGHTMLb1a0d4

以上是業界作資料驗證的邏輯原則,筆者經過千錘百鍊的資料傳輸驗證及效能除錯
基於智慧財產保障,僅提供流程邏輯,並不提供源碼分享,尚請見諒。

2009-09-11

轉Hex字串成為byte[]陣列

若您從事低層程序設計,估計常常會需要讀取Hex字串,轉成byte陣列。
例如「5A 02 03 EF…」,以下的函式提供一種通用且靈活的實作方式。
SNAGHTML16f9e39

設計時我有考慮到效能及靈活性,函式呼叫方式為:
string hexList = “5A 02 03 EF”;
byte[] bb = ToArray(hexList, “ “, “,”);

2009-09-09

WinCE SerialPort測試程式

SerialPort (RS232)的收發測試免費程式很多,但若平台是WinCE或PDA上,
這類的資料收發測試就不多。

一般人以為RS232收發很容易,只要元件拉一拉配合硬體狀況就能跑,
然而其中遇到的細節(例如HandShake, RTS, Recv資料驗證、多執行緒、Send Overrun Ack),
絕非只用Time Delay這種治標的方式來遷就硬體。

為了寫好這隻通用的程式,我把RS232的規格/名詞挖出看了一遍
寫出下面通用的RS232測試程式,支援NetCF 2.0,XP上也能跑。
畫面小小的,是為了兼容Mobile Device的畫面,連CF版本不升3.5,都是為了方便。

接收資料畫面: (儲存檔案可用於佈署傳檔)
SNAGHTML5bcfe68

傳送資料畫面: (可送檔)
SNAGHTML5c6245f

由於它只是測試程式用途,因此並沒有實作封包檢驗及傳送Ack等細部地方
但意思到就好。

下載: CeSerialPort.exe (18KB)

破壞If規則的例子

程式目的是接收RS232傳來的資料寫入一個檔案,
因此畫面上就是按Listen時開檔,按Stop時關檔,並設為null。
SNAGHTML3ce3fb2
當我關檔成功時,其FileStream也確定是null,5秒後,再RS232又有資料來
理論上應該會被下圖的if {}給略過,但卻仍發生錯誤。
SNAGHTML3c7fd55
VS2008畫面說fileStream.Write()因為是null,不能執行,檢查了fileStream值的確是null值
但它卻闖入了!!

雖然這整個method是非同步執行的,但我的確等了足足5秒後再傳資料來
就算是不同的thread,也足夠時間同步這global變數fileStream的狀態吧?!

這真的是很奇怪的現象… 有人能解釋嗎?