我的win98客户端 也要设置权限?!
解决方案 »
- 两张图片的对比,我在网上找的代码,不知道错哪里了,坐等牛人,谢谢
- 用Delphi设计图书管理系统 错误不知道怎么改~望高手能教我下
- 请教获取网络数据包,用什么控件比较容易实现?
- Delphi的常用函数有哪些啊??
- 请各位兄弟帮我看年吧.我不知错在那里了.
- 关于赋值
- 求助!!请大家帮我看一下好吗?
- 小弟的一个小作品:剪贴版加强工具。要源代码mail me:[email protected]
- 关于API Hook的问题 请教高手!
- 大家讨论一下,用delphi开发网络数据库应用时,有什么好的办法实现不同的用户只能用不同的功能,即权限管理。
- 有没有这样的控件?
- 关于TDBEdit控件的问题,怎么输入是超过4位就输不进去了呢?
可以互访共享目录或文件
1、应用服务器的启动用户使用默认配置,即“交互式用户”,然后你用user用户登录Win2000。
2、在dcomcnfg中,选择你的应用服务,打开它的“属性”,在“标识”页中选择“指定用户”,然后选择user用户及输入用户密码(建议使用这种方式)。
参数太多,有的参数不知干什么用的
然后在[应用程序]页选择你的程序模块,显示[属性],所有[安全性]设为默认;位置“在这台计算机启动”;身份标识“交互式用户”
我的WINDOWS2000的确不是域方式,我再改TsocketConnection试试
to maozefa:
你的指点我做了,前进了一步,出现 RPC服务器无法使用,我还在试!
我才知道 我的应用程序名在DCOMcnfg.exe中却是My Object,
没有了BDE的错误,现在的错误是"RPC服务器无法使用";
用SocketConnection成功了,这种连接方式,是经过中介scktsrvr.exe
才成功,而中介程序跟DCOM服务器在同一台机上,所以权限要求低;
TDOMConnection一定要在域中运行的?这个问题要弄明白
那个TDCOMConnection,我以前玩的时候,也只是在本机的连才行。我已经放弃它了,不知道delphi6.0会怎么样。
用DCOMConnection,在本机上,实现三层库是没有意义的,
在多机上,关键是权限问题,难道就这样没戏了?!
而TDCOMConnection的权限, 一般是说通过dcomcnfg.exe来分配的,我看了以前的问题好像是说要一个一个用户的配置,不是everyone, or domain user...
还有李维的书上说remote module有一个什么什么方法(忘了),可以进行权限的控制,不过我从来没有试过。水平有限。
关注......
还有一种方法,不过这只是访问remote module里面interface 的属性,不能用DataProvider
只是可以通过interface 的方法,函数和属性,你看能不能封装一个。type
IMyInterface = interface
'[GUID]'
procedure methode1(param: ParamType);
procedure methode2(out param: ParamType);
end;
..
//直接用这来创建远程对象接口,用对象方法和来实现你的功能 。
//var Obj: IMyInterface;
// Obj := CoMyInterface.CreateRemote('MahineName');
// Obj.Method1 Obj.Property Obj.Function
CoMyInterface = class
class function Create: IMyInterface;
class function CreateRemote(const MachineName: string): IMyInterface;
end;
//DCOMConnection连接不了的。我也没办法。:(
“RPC服务器无法使用”错误主要还是服务器DCOM设置问题,检查你的应用程序模块的"身份标志"是否为交互式,配置完以后重新启动计算机看看。如果你的其它方面没问题,应该可以运行。与Win98的网络用户访问方式无关。我做过很多这种程序,都很正常。
使用TSocketConnection连接也可以,不过有两个问题要注意,一是安全性不强,而是当传输数据包裹较大,特别是某一字段如Blob字段的值较大时,中途容易超时中断。
mail:[email protected]
win2000上应用程序模块的"身份标志"已设为'交互式';就是会出现: “RPC服务器无法使用”,但在win2000上,'数据库应用服务器程序'能被自动启
动起来,且可以有多个实例,客户端无法见到数据库数据'客户/服务'在同一台机运行,win98与win2000都没有任何问题;
分开来就不行,唉
很有可能是问题1.因为如果客户机正常登录服务器后,在服务器上只应该启动一个实例,而不管有多少客户。如果你的服务器不是域服务器,请改为域服务器试试。
至于有朋友要例子程序,我做的几个程序都较复杂,且涉及注册表问题和SQL 7.0,目前不好回复,如果实在要,请联系我的E_Mail:[email protected],我抽时间编一个简单一点的例子,包裹后发给你。
只要你不怕泄密,呵呵,我要了,数据库就不用了,我想见识一下其它的写作风格,还有一些技术习惯,哈哈。
客户机如果没有midas.dll是不能够启动的,会raise midas error,不会是第三个原因。
中间层的连接,如果本机可行的话,一般是没有问题的。
至于权限,BCB说的是对等网之间的连接,我想DCOMConnection是不能在不是NT域中进行的吧。
RPC服务不能启动,可能是由于NT服务器多了一些服务的程序,如果是对等网的2000可能是无法调用它的服务程序,以致于出错。
unit ServerMain;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ImgList, Db, DBTables, ComCtrls, StdCtrls, ExtCtrls, ADODB, Menus;const
// 服务器在注册表的登记项路径,程序安装时自动登记
RegPath = '\SoftWare\Zfinfo\ZfServer';
UpdatePath = '\Software\UpdateData';
ConnectionStr = 'Provider=SQLOLEDB.1;Password=195316;Persist Security Info=True;User ID=sa;Initial Catalog=Zfinfo';
// ConnectionStr = 'Provider=MSDASQL.1;Password=195316;Persist Security Info=True;User ID=sa;Data Source=ZfInfoDB;Initial Catalog=ZfInfo';
type
TServerMainForm = class(TForm)
Image1: TImage;
ListView1: TlistView;
Label1: TLabel;
ImageList1: TImageList;
ADOConnection: TADOConnection;
ADOQuery: TADOQuery;
PopupMenu1: TPopupMenu;
N1: TMenuItem;
N2: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure N1Click(Sender: TObject);
procedure N2Click(Sender: TObject);
private
{ Private declarations }
FRecNumber: Integer;
FSendDate: TDate;
FSystemPath: String;
FUpdateFlag: Integer;
function GetRecNumber: Integer;
procedure SetSendDate(aDate: TDate);
procedure ClearClients;
public
{ Public declarations }
procedure RegUpdateFlag(Flag: Integer);
function InsertClient: TListItem;
// SendDate,RecNumber属性为远程数据模块自动填充信息记录
// 主键(记录发送时间和编号)用
property RecNumber: Integer read GetRecNumber;
property SendDate: TDate read FSendDate write SetSendDate;
// 系统路径
property SystemPath: String read FSystemPath;
// 二进制文件存取路径
property UpdateFlag: Integer read FUpdateFlag;
end;var
ServerMainForm: TServerMainForm;implementationuses Registry, ServerRes;{$R *.DFM}{ TServerMainForm }
// 主Form建立事件
procedure TServerMainForm.FormCreate(Sender: TObject);
var
Reg: TRegistry;
begin
Reg := TRegistry.Create; // 建立注册表对象,默认Root:KKEY_CURRENT_USER
try
if Reg.OpenKey(RegPath, False) then // 如果登记路径存在,读系统路径
FSystemPath := Reg.ReadString('SystemPath')
else Halt; // 否则程序退出(非正常安装程序)
if Reg.OpenKey(UpdatePath, False) then
FUpdateFlag := Reg.ReadInteger('UpdateFlag')
else FUpdateFlag := 0;
finally
Reg.Free; // 释放注册表对象
end;
if SystemPath[Length(SystemPath)] <> '\' then
FSystemPath := SystemPath + '\';
ADOConnection.ConnectionString := ConnectionStr;
ADOConnection.Connected := True;
if not ADOConnection.Connected then
ShowMessage('连接数据库失败!');
SendDate := Date;
end;
// 从列表中清除所有已经完成任务的的客户记载
procedure TServerMainForm.ClearClients;
var
I: Integer;
begin
I := 0;
while I < ListView1.Items.Count do
if ListView1.Items.Item[I].ImageIndex = 1 then Inc(I)
else ListView1.Items.Delete(I);
end;
// RecNumber属性(信息记录编号)的Get方法
function TServerMainForm.GetRecNumber: Integer;
begin
Inc(FRecNumber); // 现有记录编号+1,并返回
Result := FRecNumber;
end;
// 在客户列表中插入一个客户记载(列表项),返回列表项
function TServerMainForm.InsertClient: TListItem;
begin
if SendDate <> Date then // 如果信息记录时间<>当前时间
begin
SendDate := Date; // 设置信息记录时间=当前时间,取当日最大的记录编号
ClearClients; // 从列表中清除所有已经完成任务的的客户记载
end;
Result := ListView1.Items.Insert(0);
Result.ImageIndex := 1;
end;
// SendDate属性(信息记录时间)的Put方法
procedure TServerMainForm.SetSendDate(aDate: TDate);
begin
FSendDate := aDate;
ADOQuery.Parameters[0].Value := aDate;
ADOQuery.Active := True;
FRecNumber := ADOQuery.Fields[0].AsInteger;
ADOQuery.Active := False;
end;procedure TServerMainForm.RegUpdateFlag(Flag: Integer);
var
Reg: TRegistry;
begin
Reg := TRegistry.Create;
try
if Reg.OpenKey(UpdatePath, True) then
Reg.WriteInteger('UpdateFlag', Flag);
finally
Reg.Free;
FUpdateFlag := Flag;
end;
end;procedure TServerMainForm.N1Click(Sender: TObject);
begin
ResultForm.Show;
end;procedure TServerMainForm.N2Click(Sender: TObject);
begin
Close;
end;end.
// 服务器远程数据模块单元
unit ServerData;interfaceuses
Windows, Messages, SysUtils, Classes, ComServ, ComObj, VCLCom, DataBkr,
DBClient, ZfServer_TLB, StdVcl, Provider, Db, DBTables, ComCtrls, ADODB;type
TZfInfoServer = class(TRemoteDataModule, IZfInfoServer)
ClassProvider: TDataSetProvider;
TypeProvider: TDataSetProvider;
UsersProvider: TDataSetProvider;
ItemsProvider: TDataSetProvider;
ItemsProvider1: TDataSetProvider;
NewProvider: TDataSetProvider;
RecProvider: TDataSetProvider;
ClassQuery: TADOQuery;
TypeQuery: TADOQuery;
UsersQuery: TADOQuery;
ItemsQuery: TADOQuery;
ItemsQuery1: TADOQuery;
NewQuery: TADOQuery;
RecQuery: TADOQuery;
procedure RemoteDataModuleDestroy(Sender: TObject);
procedure ItemsQueryAfterOpen(DataSet: TDataSet);
procedure NewProviderBeforeUpdateRecord(Sender: TObject;
SourceDS: TDataSet; DeltaDS: TClientDataSet; UpdateKind: TUpdateKind;
var Applied: Boolean);
private
{ Private declarations }
FItem: TListItem;
protected
class procedure UpdateRegistry(Register: Boolean; const ClassID, ProgID: string); override;
procedure SetClientInfo(const UserName, WorkInfo: WideString); safecall;
procedure SetUpdateFlag(Flag: Integer); safecall;
public
{ Public declarations }
end;implementationuses ServerMain;{$R *.DFM}class procedure TZfInfoServer.UpdateRegistry(Register: Boolean; const ClassID, ProgID: string);
begin
if Register then
begin
inherited UpdateRegistry(Register, ClassID, ProgID);
EnableSocketTransport(ClassID);
EnableWebTransport(ClassID);
end else
begin
DisableSocketTransport(ClassID);
DisableWebTransport(ClassID);
inherited UpdateRegistry(Register, ClassID, ProgID);
end;
end;// 远程数据模块摧毁事件。本服务器的远程数据模块是多用户方式
//(每客户都启用一个独立的远程数据模块)
procedure TZfInfoServer.RemoteDataModuleDestroy(Sender: TObject);
begin
if Tag <> 0 then FItem.ImageIndex := 0;
end;
// 信息记录表Items已打开事件
procedure TZfInfoServer.ItemsQueryAfterOpen(DataSet: TDataSet);
var
Code: String;
InfoDate: TDateTime;
begin
if Tag = 0 then Exit;
with TADOQuery(DataSet) do // 日记表中插入一条接收信息的记录
begin
Code := Parameters[2].Value; // 在ItemsQuery参数表中取用户代码和信息时间
InfoDate := Parameters[0].Value;
end;
with RecQuery do // 设置RecQuery的SQL语句并执行
begin
// SQL插入语句中的字串和日期串必须用引号(单双均可),只能用ExecSQL不能用Open
Code := '(' + #39 + Code + #39 + ',' + #39 + FormatDateTime('mm/dd/yyyy hh:mm:ss', Now) +
#39 + ',' + #39 + FormatDateTime('mm/dd/yyyy', InfoDate) + #39 + ')';
SQL.Add('Insert Into QueryRec Values' + Code);
ExecSQL;
end;
end;
// NewQuery接口NewProvider的数据更新事件
procedure TZfInfoServer.NewProviderBeforeUpdateRecord(Sender: TObject;
SourceDS: TDataSet; DeltaDS: TClientDataSet; UpdateKind: TUpdateKind;
var Applied: Boolean);
begin
// 如果客户程序插入信息记录同时未设定主键,
// 从主窗口获取唯一的记录主键(发送时间和当日记录序号)
if (UpdateKind = ukInsert) and (DeltaDS.FieldByName('NUM').Asinteger <= 0)
and (ServerMainForm.UpdateFlag = 0) then
begin
DeltaDS.Edit;
DeltaDS.FieldByName('NUM').AsInteger := ServerMainForm.RecNumber;
DeltaDS.FieldByName('SENDDATE').AsDateTime := ServerMainForm.SendDate;
end;
end;
// 以下是在类型库中自定义的客户接口过程,这些过程可由不同语言客户程序使用多种接口访问。
// Delphi中客户一般使用连接元件的AppServer访问// 设置用户操作信息,参数:用户名,操作信息
procedure TZfInfoServer.SetClientInfo(const UserName, WorkInfo: WideString);
begin
Tag := 1; // 使用Tag属性作标记,1表示已插入客户访问列表项
FItem := ServerMainForm.InsertClient; // 插入并返回一个客户列表项
FItem.Caption := UserName; // 项标题=用户名
FItem.SubItems.Add(WorkInfo); // 增加一个子项描述操作信息
end;procedure TZfInfoServer.SetUpdateFlag(Flag: Integer);
begin
ServerMainForm.RegUpdateFlag(Flag);
end;initialization
TComponentFactory.Create(ComServer, TZfInfoServer,
Class_ZfInfoServer, ciMultiInstance, tmApartment);
end.// 一个利用聊天元件制作的用户快速回复反馈单元
unit ServerRes;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Menus, StdCtrls, Buttons, ScktComp, ExtCtrls, ComCtrls;type
TResultForm = class(TForm)
Bevel1: TBevel;
Panel1: TPanel;
Memo1: TMemo;
SpeedButton1: TSpeedButton;
ServerSocket: TServerSocket;
SpeedButton2: TSpeedButton;
procedure FormCreate(Sender: TObject);
procedure ServerSocketError(Sender: TObject; Number: Smallint;
var Description: string; Scode: Integer; const Source,
HelpFile: string; HelpContext: Integer; var CancelDisplay: Wordbool);
procedure ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure SpeedButton1Click(Sender: TObject);
procedure SpeedButton2Click(Sender: TObject);
protected
end;var
ResultForm: TResultForm;implementation{$R *.DFM}procedure TResultForm.FormCreate(Sender: TObject);
begin
ServerSocket.Active := True;
end;procedure TResultForm.ServerSocketError(Sender: TObject; Number: Smallint;
var Description: string; Scode: Integer; const Source, HelpFile: string;
HelpContext: Integer; var CancelDisplay: Wordbool);
begin
ShowMessage(Description);
end;procedure TResultForm.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
if not Visible then Show;
Memo1.Lines.Add(ForMatDateTime('(yyyy/mm/dd tt)', Now) + Socket.ReceiveText);
end;procedure TResultForm.SpeedButton1Click(Sender: TObject);
begin
Close;
end;procedure TResultForm.SpeedButton2Click(Sender: TObject);
begin
Memo1.Lines.Clear;
end;end.
还是有不同的习惯,我这人不喜欢写注解,呵呵,我旁边的人也这样说我
还有你的Remote Data Module需要那么多的DataProvider吗,我写的一般就是TADOConnection,TADOQuery,TADOCommand,TDataSetProvider这几个,呵呵不超过十个吧。
两台机上为什么DCOMConnection不成功?
只能用SocketConnection了?!
谢谢你的指点,要完成数据库查询,一套元件就够了。不过这有几个弊端:
1、增加客户终端程序中ClientDataSet.CommandText大量的更新代码。
2、不易维护。
3、程序的可读性下降。
4、使用ClientDataSet.CommandText发送代码,执行效率比较低。不信你可以试。
再说,你没了解我的整个程序,我的中间服务器供三套程序使用,一是局域网在线用户查询;二是远程拨号上网用户公文包下载方式查询;三是供内部网站ISAPI程序查询。
至于你说我的代码中有注释,解释一下,注释本来是一个好的编程人员的良好习惯,不过我并不喜欢写注释,但我比较喜欢对代码进行提炼,这样没有注释也具有很好的可读性,我的注释是为一个年轻人写的,他要我的全部源代码学习。我也只在服务器和客户程序的主模块写了,对你这样的高手,看起来当然很罗嗦了。
非常感谢,我两台win2000,都是工作组方式,相当于对等网,
果然可以用DCOMConnect连接,win98为什么不行呢
再试试,我舍得分呀,任意两台机子如何DCOMConnection?
大家不肯再试了,只有发分了,论功发