線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:3345
推到 Plurk!
推到 Facebook!

Remote Data Module無法註冊到系統的問題

答題得分者是:jow
GrandRURU
站務副站長


發表:235
回覆:1655
積分:1753
註冊:2005-06-21

發送簡訊給我
#1 引用回覆 回覆 發表時間:2010-03-14 16:34:25 IP:115.43.xxx.xxx 訂閱
 我的系統是Win2003 + C++ Builder 2010 / BCB6
我開了一個Remote Data Module的專案之後,執行該專案
如果是winxp時,這個專案會自動在DCOM註冊,但是在Win2003卻無法註冊。

同樣的情況在Delphi 2010也是一樣無法註冊…
不過
網路上有這樣的一個解法
[code delphi]
TComponentFactory.Create(ComServer, TXOtecDbRemoteServer,
Class_XOtecDbRemoteServer, ciMultiInstance, tmApartment);

ComServer.UpdateRegistry(True); [/code]

使用之後的Delphi Remote Data Module就可以順利註冊上DCOM。

不過在C Builder的專案中找不到上述的宣告。
請問這個問題該怎麼解呢?

還是說CB只能用手動註冊的方式來註冊呢?
1.Select Start » Run.
2.Type the following in the dialog box that appears:
/RegServer
Where is the location of your EXE server
(e.g., C:\TestStand\Bin\REngine.exe /RegServer).
這個方法可以註冊上,但Clent端可以查到Server,卻無法連線到Server

還請各位大大幫忙~~~
編輯記錄
GrandRURU 重新編輯於 2010-03-14 16:37:56, 註解 無‧
GrandRURU 重新編輯於 2010-03-14 16:38:46, 註解 無‧
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#2 引用回覆 回覆 發表時間:2010-03-14 22:16:45 IP:123.193.xxx.xxx 未訂閱
改寫自 tregsvr.exe 的source code
提供你參考...^_^

[code delphi]
unit uTheRegisterServer;

interface

uses
SysUtils, Windows, Dialogs, ActiveX, ComObj;

function DoRegisterServer(FileName: string): Boolean;
function DoUnregisterServer(FileName: string): Boolean;

implementation

resourcestring
SNeedFileExt = 'You must specify a file extension for "%s"';
SRegStr = 'registered';
SUnregStr = 'unregistered';

type
TRegType = (rtAxLib, rtTypeLib, rtExeLib);
TRegAction = (raReg, raUnreg);
TRegProc = function : HResult; stdcall;

TUnRegTlbProc = function (
const libID: TGUID;
wVerMajor, wVerMinor: Word;
lcid: TLCID;
syskind: TSysKind): HResult; stdcall;

const
ProcName: array[TRegAction] of PChar = ('DllRegisterServer', 'DllUnregisterServer');
ExeFlags: array[TRegAction] of string = (' /regserver', ' /unregserver');

var
RegType: TRegType = rtAxLib;
RegAction: TRegAction = raReg;
QuietMode: Boolean = False;
FileName: string;
RegProc: TRegProc;
LibHandle: THandle;
OleAutLib: THandle;
UnRegTlbProc: TUnRegTlbProc;
TheParamStr: array[0..2] of string;
TheParamCount: Integer;

procedure OutputStr(S: string);
begin
if not QuietMode then
begin
CharToOEM(PChar(S), PChar(S));
ShowMessage(S);
end;
end;

function DecodeOptions: Boolean;
var
i: Integer;
FileStart: Boolean;
Param, FileExt: string;
begin
Result := False;
if TheParamCount = 0 then Exit;
FileName := '';
for i := 0 to TheParamCount-1 do
begin
Param := TheParamStr[i];
FileStart := not (Param[1] in ['-', '/']);
if FileStart then
begin
if FileName = '' then FileName := Param
else FileName := FileName ' ' Param;
// strip open and/or close quote if present
if (FileName[1] = '"') then
begin
if (FileName[Length(FileName)] = '"') then
FileName := Copy(FileName, 2, Length(FileName) - 2)
else if FileName[1] = '"' then Delete(FileName, 1, 1);
end;
end
else
begin
if Length(Param) < 2 then Exit;
case Param[2] of
'U', 'u': RegAction := raUnreg;
'Q', 'q': QuietMode := True;
'T', 't': RegType := rtTypeLib;
end;
end;
end;
FileExt := ExtractFileExt(FileName);
if FileExt = '' then raise Exception.CreateFmt(SNeedFileExt, [FileName]);
if RegType <> rtTypeLib then
begin
if CompareText(FileExt, '.TLB') = 0 then RegType := rtTypeLib
else if CompareText(FileExt, '.EXE') = 0 then RegType := rtExeLib
else RegType := rtAxLib;
end;
Result := True;
end;

function RegisterAxLib: Boolean;
begin
Result := False;
LibHandle := LoadLibrary(PChar(FileName));
if LibHandle <> 0 then
try
@RegProc := GetProcAddress(LibHandle,ProcName[RegAction]);
Result := (@RegProc <> nil) and (RegProc = 0);
finally
FreeLibrary(LibHandle);
end;
end;

function RegisterTLB: Boolean;
var
WFileName, DocName: WideString;
TypeLib: ITypeLib;
LibAttr: PTLibAttr;
DirBuffer: array[0..MAX_PATH] of char;
begin
Result := False;
if ExtractFilePath(FileName) = '' then
begin
GetCurrentDirectory(SizeOf(DirBuffer), DirBuffer);
FileName := '\' FileName;
FileName := DirBuffer FileName;
end;
if not FileExists(FileName) then EXIT;

WFileName := FileName;
OleCheck(LoadTypeLib(PWideChar(WFileName), TypeLib));
OleCheck(TypeLib.GetLibAttr(LibAttr));
try
case RegAction of
raReg:
begin
OleCheck(TypeLib.GetDocumentation(-1, nil, nil, nil, @DocName));
DocName := ExtractFilePath(DocName);
OleCheck(RegisterTypeLib(TypeLib, PWideChar(WFileName), PWideChar(DocName)));
Result := True;
end
else begin
OleAutLib := GetModuleHandle('OLEAUT32.DLL');
if OleAutLib <> 0 then
begin
@UnRegTlbProc := GetProcAddress(OleAutLib, 'UnRegisterTypeLib');
if @UnRegTlbProc <> nil then
with LibAttr^ do
begin
OleCheck(UnRegTlbProc(Guid, wMajorVerNum, wMinorVerNum, LCID, SysKind));
Result := True;
end;
end;
end;
end;
finally
TypeLib.ReleaseTLibAttr(LibAttr);
end;
end;

function RegisterEXE: Boolean;
var
SI: TStartupInfo;
PI: TProcessInformation;
begin
FillChar(SI, SizeOf(SI), 0);
SI.cb := SizeOf(SI);
Result := SysUtils.Win32Check(
CreateProcess(PChar(FileName),
PChar(FileName ExeFlags[RegAction]),
nil, nil, True, 0, nil, nil, SI, PI));
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
end;

function DoRegisterServer(FileName: string): Boolean;
begin
Result := False;
if FileExists(FileName) then
try
TheParamStr[0] := '-q';
TheParamStr[1] := FileName;
TheParamCount := 2;
if DecodeOptions then
begin
case RegType of
rtAxLib: Result := RegisterAxLib;
rtTypeLib: Result := RegisterTLB;
rtExeLib: Result := RegisterEXE;
end;
end;
except
on E:Exception do OutputStr(E.Message);
end;
end;

function DoUnregisterServer(FileName: string): Boolean;
begin
Result := False;
if FileExists(FileName) then
try
TheParamStr[0] := '-q';
TheParamStr[0] := '-u';
TheParamStr[1] := FileName;
TheParamCount := 2;
if DecodeOptions then
begin
case RegType of
rtAxLib: Result := RegisterAxLib;
rtTypeLib: Result := RegisterTLB;
rtExeLib: Result := RegisterEXE;
end;
end;
except
on E:Exception do OutputStr(E.Message);
end;
end;

end.

[/code]


GrandRURU
站務副站長


發表:235
回覆:1655
積分:1753
註冊:2005-06-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2010-03-15 08:42:48 IP:203.75.xxx.xxx 訂閱
謝謝jow大的回覆

請問這是要利用Source內registerEXE的內容導入到CB的專案中,讓自己註冊自己嗎?
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#4 引用回覆 回覆 發表時間:2010-03-15 09:12:13 IP:112.104.xxx.xxx 未訂閱
我個人的做法是在Client端程式中
use 這個改寫的 source unit (uTheRegisterServer)
再直接呼叫
function DoRegisterServer(FileName: string): Boolean;
function DoUnregisterServer(FileName: string): Boolean;

另外, 你也可以先在Client端程式中
直接執行外部程式tregsvr.exe 測試看看


個人做法,謹供參考
GrandRURU
站務副站長


發表:235
回覆:1655
積分:1753
註冊:2005-06-21

發送簡訊給我
#5 引用回覆 回覆 發表時間:2010-03-15 09:35:55 IP:203.75.xxx.xxx 訂閱
Client端程式註冊到server的方式不是只要利用DCOM/SOCKET/WEBCONNECTION,就可以找到server端裡所註冊好的Remote Data Module嗎?

但現在的情況是Server端裡的Remote Data Module無法註冊到Server內,不知道這個方法是否可以解決這個問題呢?

我剛剛在「TCRemoteDataModule」裡有看到下面的原式
__classmethod virtual void __fastcall UpdateRegistry(bool Register, const System::UnicodeString ClassID, const System::UnicodeString ProgID);

與DELPHI的有些許不同,不過函式裡的參數:ClassID, ProgID我就不知道要如何取得了……

===================引 用 jow 文 章===================
我個人的做法是在Client端程式中
use 這個改寫的 source unit (uTheRegisterServer)
再直接呼叫
functionDoRegisterServer(FileName:string):Boolean;
functionDoUnregisterServer(FileName:string):Boolean;

另外, 你也可以先在Client端程式中
直接執行外部程式tregsvr.exe 測試看看


個人做法,謹供參考
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#6 引用回覆 回覆 發表時間:2010-03-15 10:47:51 IP:112.104.xxx.xxx 未訂閱
關於 COM/DCOM based program
一般而言,在程式散發(distribute)時,必須在Client 端註冊
server 所宣告(declare)並定義/實作好的(define/implement)
的介面

以下是個人的一些經驗:
a. in-process server: 使用tregsvr.exe 或 regsvr32.exe來註冊,相關dll必須存在Client端
b. out-of-process server: 使用tregsvr.exe 或 將server程式執行一次(好像可以加上參數, 只做註冊動作)
c. out-of-process server 若為TAppServer, 並使用TSocketConnection連接,則Client端不需要註冊動作

另外,上述註冊的動作,應該也可以只使用*.TLB 來登錄相關的介面資訊(這方面個人尚未測試過)

最後,關於Server程式無法註冊的狀況
個人在Win7中使用時,必須以管理員身分執行
請確認是否由此原因所致


個人一些經驗, 謹供參考


===================引 用 GrandRURU 文 章===================
Client端程式註冊到server的方式不是只要利用DCOM/SOCKET/WEBCONNECTION,就可以找到server端裡所註冊好的Remote Data Module嗎?

但現在的情況是Server端裡的Remote Data Module無法註冊到Server內,不知道這個方法是否可以解決這個問題呢?

我剛剛在「TCRemoteDataModule」裡有看到下面的原式
__classmethod virtual void __fastcall UpdateRegistry(bool Register, const System::UnicodeString ClassID, const System::UnicodeString ProgID);

與DELPHI的有些許不同,不過函式裡的參數:ClassID, ProgID我就不知道要如何取得了……

GrandRURU
站務副站長


發表:235
回覆:1655
積分:1753
註冊:2005-06-21

發送簡訊給我
#7 引用回覆 回覆 發表時間:2010-03-15 11:45:41 IP:203.75.xxx.xxx 訂閱
//------Win2000 Pro + BCB6
我在Win2000 pro時有先用BCB6來try過。
DB, AP在同一台

AP在REMOTE DATA MODULE設定好時有先執行過一次(註冊在DCOM中)

Client則有測過:
DCOM: 自機編/連線 區網連線
Scoket: 自機編/連線 區網連線 外網連線
WebConnection: 自機編/連線

Client端撰寫時有先把DCOM/SocketConnection連上AP端,會得到ServerName,然後也會得到ServerGUID。

//------Win2003 RAD 2010
Win2003則是以Administrator身份登入(剛安裝好也只有Admin身份)
Remote Data Module設定好之後也執行過一次(註冊,但實際上卻沒註冊到server的dcom中)

client同樣使用上述三者連線元件,皆找不到ServerName, ServerGUID

JOW大的處理方式好像都是針對client做處理

但如果Remote Data Module一直無法順利註冊到DCOM中……

不知JOW大的方法是否這樣就可以無視這個問題而正常使用呢?

同樣的情況,在delphi中只要以開頭的解法就可以順利解決了唷!
想不透平平是姐妹品,為何會差這麼多……

===================引 用 jow 文 章===================
關於 COM/DCOM based program
一般而言,在程式散發(distribute)時,必須在Client 端註冊
server 所宣告(declare)並定義/實作好的(define/implement)
的介面

以下是個人的一些經驗:
a. in-process server: 使用tregsvr.exe 或 regsvr32.exe來註冊,相關dll必須存在Client端
b.out-of-process server: 使用tregsvr.exe 或 將server程式執行一次(好像可以加上參數, 只做註冊動作)
c. out-of-process server 若為TAppServer, 並使用TSocketConnection連接,則Client端不需要註冊動作

另外,上述註冊的動作,應該也可以只使用*.TLB 來登錄相關的介面資訊(這方面個人尚未測試過)

最後,關於Server程式無法註冊的狀況
個人在Win7中使用時,必須以管理員身分執行
請確認是否由此原因所致


個人一些經驗, 謹供參考
GrandRURU
站務副站長


發表:235
回覆:1655
積分:1753
註冊:2005-06-21

發送簡訊給我
#8 引用回覆 回覆 發表時間:2010-03-15 13:25:12 IP:203.75.xxx.xxx 訂閱
剛剛我試了在WIN2000下用bcb6建立的ap.exe搬到win2003下執行,結果可以順利註冊,而且2010的client也可以正常連結ap

難道說這是2010的bug嗎……?
shchen
一般會員


發表:12
回覆:26
積分:7
註冊:2003-08-13

發送簡訊給我
#9 引用回覆 回覆 發表時間:2010-07-26 21:27:38 IP:202.173.xxx.xxx 訂閱
我也是剛開始改用RAD 2010內的C++ Builder 2010,我也遇到Remote Data Module不會像C++Builder 6 編出的DCOM Server 端程式,執行EXE就會自動注冊,在李維 老師所著的Delphi 4.X 實戰扁1內也是說會自動注冊DCOM Interface.
真奇怪,BCB 6可自動注冊,而BCB 2010卻無法自動注冊,翻遍資料,查到對於進程外的COM 伺服器(EXE or DLL),要使用命令列下的 xxx.EXE /regserver,來注冊,但很像也不是很完整,注冊後在注冊表內的GUID是有了,而DCOMConnection1 的ServerName屬性也出現了注冊的DCOM Server,但我將ClientDataSet1->Activer設為true是就不斷的給我報錯 " ClientDataSet1: Missing data provider or data packet " 氣死我了,卡了4天,還沒解決,還是該維持用BCB6嗎??

最後發現是自己搞烏龍,Remote Data module 上的TQuity 沒有設SQL String,沒有命令導致的啦.
編輯記錄
shchen 重新編輯於 2010-11-03 05:16:17, 註解 無‧
shchen 重新編輯於 2010-11-03 05:17:18, 註解 無‧
GrandRURU
站務副站長


發表:235
回覆:1655
積分:1753
註冊:2005-06-21

發送簡訊給我
#10 引用回覆 回覆 發表時間:2010-08-03 12:52:01 IP:203.75.xxx.xxx 訂閱
你有下DataSetProvider物件嗎?

===================引 用 shchen 文 章===================
我也是剛開始改用RAD 2010內的C Builder 2010,我也遇到Remote Data Module不會像C Builder 6 編出的DCOM Server 端程式,執行EXE就會自動注冊,在李維 老師所著的Delphi 4.X 實戰扁1內也是說會自動注冊DCOM Interface.
真奇怪,BCB 6可自動注冊,而BCB 2010卻無法自動注冊,翻遍資料,查到對於進程外的COM 伺服器(EXE or DLL),要使用命令列下的 xxx.EXE /regserver,來注冊,但很像也不是很完整,注冊後在注冊表內的GUID是有了,而DCOMConnection1 的ServerName屬性也出現了注冊的DCOM Server,但我將ClientDataSet1->Activer設為true是就不斷的給我報錯 " ClientDataSet1: Missing data provider or data packet " 氣死我了,卡了4天,還沒解決,還是該維持用BCB6嗎??

系統時間:2017-12-14 23:10:55
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!