升級到sp2後,基於充分利用Windows xp sp2安全功能方面的考慮,本人近期開始將原有的DCOM應用向Com+環境轉移。現將本人轉移過程中出現的問題及解決辦法,介紹如下,請方家指正:
一、原DCOM應用的結構:
我用DELPHI IDE的向導正常生成一個遠程數據模塊(RdbDBSvr),並在其中放入AdoDataset,Adoquery等數據集控件,建立接口方法,對外Export方法接口,為客戶端提供數據查詢功能,該服務器采用獨立運行的進程外服務模式。客戶端則利用Dcomconnection來連接此遠程數據模塊。總之是一個在Delphi中創建的標准的C/S應用程序。
需要說明的是在設計RdbDBSvr時,為保持未來的代碼重用,其中沒有加入直接引用主窗體變量的引用,一些為了同步線程設置的變量,我均將其放入了一個公用變量單元中。同時,同時我還盡量使用方法而不是直接使用Provider控件來為客戶提供數據。事實證明,這種設計減輕了DCOM向COM+對象轉換的復雜程度,而且應該說是相當方便的。
在客戶端,我則通過公用變量引入遠程數據模塊的IAPPServer接口,並在大部分的代碼中引用這一公用變量並調用方法。也就是說,代碼中沒有加入對特定遠程數據提供者的直接引用。
二、現在我們對服務器進行轉換。
DCOM對象向COM+對象轉換前,我事實上運用了一個事實:就是Delphi中無論是RemoteDataMoudel還是MTSDataMoudle,都實現了IAPPServer接口,並歸入Borland DataSnap Applacation server Catlog中。因此無論是MTS對象,不是DCOM對象,在使用DcomConnection控制找遠程數據提供者(Remote data provider)時,都會在列表中出現。
(一) 方法一
1、用Delphi IDE創建一個新的Transactional data moudle,並將其放入一個單獨的ActiveX DLL中。
2、打開原DCOM服務器中的遠程數據模塊,選擇其中的全部控件,並將其拷貝到你新創建的MTS數據模塊中,這樣你原遠程數據模塊中所有控件的屬性都被原樣復制過來了。這一步是為下一步得用DCOM遠程數據模塊代碼做了必要准備。
3、打開Type library編輯器,將原DCOM服務器的類型庫加入到引用列表中,並將新的MTS數據模塊的Parent interface改成DCOM服務器中遠程數據模塊實現的接口。然後刷新類型庫。
4、此時你的MTS接口實現單元中,將會自動加入原DCOM遠程數據模塊的接口聲明,並加入實現代碼的框架。
TDemo = class(TMtsDataModule, IDemo)
private
{ Private declarations }
protected
class procedure UpdateRegistry(Register: Boolean; const ClassID, ProgID: string); override;
//以下是我的原遠程數據模塊的接口表,Delphi自動將其復制到此單元中,並且生成了代碼框架
procedure FindPersons(const Name, UnitNo: WideString;
out RDataset: OleVariant); safecall;
procedure GetFIEldsName(const TBName: WideString; out FDNames: OleVariant);
safecall;
procedure GetLaborage(const PersonNo: WideString; out Records: OleVariant);
safecall;
procedure GetOtherInfo(const TableName, PersonNo: WideString;
……
public
{ Public declarations }
end;
……
procedure TDemo.FindPersons(const Name, UnitNo: WideString;
out RDataset: OleVariant);
begin
end;
……
5、現在,返回到原DCOM遠程數據模塊的實現單元,將其方法的具體實現代碼復制到此單元。並將復制代碼中的原DCOM對象的類名替換成MTS對象的類名。同時注意:如果原DOCM遠程數據模塊引用了公用單元(如我自己引用的公用變量單元),將你還需將引用的公用單元加入到USER列表中。
6、至此,你的與DCOM數據模塊相同功能的MTS數據模塊完全實現,請編譯並注冊該MTS對象。
三、客戶端:
打開你的客戶端應用程序源代碼,並打開客戶端數據模塊中的DCOMConnection對象的ServerName屬性列表,此時,你將可以看到MTS對象出現在了列表中,選擇它,並重新編譯你的客戶應用程序。如果你在客戶端代碼中沒有加入對ServerName的引用硬編碼,則你將看到客戶端不需任何改變就能夠正常運行,而此時它引用的已不是DCOM對象而是運行在COM+環境中的MTS對象。為證實這一點,你可以運行DCOMCNFG。在本地計算機中“正在運行的進程”列表中,你將看到MTS正在歡快的旋轉。
四、注意的問題:
1、上述方法是將原DCOM 應用服務器的類型庫導入到MTS服務器中,再實現類型庫中的方法。因此,如果你將新生成的MTS服務器組件發布到其他計算機上,並且沒有將原DCOM應用服務器拷貝並注冊到該計算機上,將你的客戶端將會收到“找不到類型庫”的錯誤提示。解決這一問題的辦法是將原DCOM應用服務器的*.tlb文件復制到該計算機上,並用tregsvr.exe –t (server).tlb 來在該計算機上注冊類型庫(server用你原服務器名代替)。另一種方法是,在編輯MTS對象類型庫時,直接引用原服務器的TLB文件,而在分民MTS對象將該TLB文件與MTS包隨同分發。
2、以上轉換事實上只能對比較簡單的DCOM對象進行。如果你的DCOM代碼中加入了與後端數據庫相關的事務支持代碼,則你必須修改其代碼,使之使用MTS提供的事務管理功能,這樣才能充分發揮MTS資源管理、事務協調的強大功能,當然,如果你的DCOM對象沒有使用與MTS相容的線程模型,則你的修改工作量將會更大。
3、在轉換成MTS對象後,你就能直接運用MTS基於角色的安全功能,對你的MTS的安全屬性實施細微的控制,並且不用增加任何代碼,當然如果你的代碼中加入了原基於DCOM的特殊安全設定,你可能還要進行微調。但是,COM+會兼容這些安全代碼。
4、轉換成MTS對象後,建議你重新確定你的COM默認發生的“最低安全限制”屬性和你計算機的防火牆設置,以免它停止工作或“拒絕訪問”。