此篇日志,是上一篇日志的兄弟篇,下面是我使用Delphi2010封装的一个单元,直接使用即可,其解析算法和前两篇中的一致,可供Delphi进行金蝶二次开发的人员参考。
{ Design By M.K Create At 2012.08.14 } unit KingdeeUtils; interface uses SysUtils, ComObj, Generics.Collections; type TKingdeeLogin = class(TObject) private _clsLogin: OleVariant; _connectionString: string; _accountName: string; _userName: string; _userId: Integer; procedure InitialLoginDatas; procedure ParsePropsStringToField(propsString: string); function ReadPropsStringToDictionary(propsString: string): TDictionary<string, string>; function ReadSection(sections: TDictionary<string, string>; source: string): Integer; function ReadKey(source: string; var key: string): Integer; function ReadValue(source: string; var value: string): Integer; function GetValueFromDictionary(key: string; source: TDictionary<string, string>): string; public constructor Create; function CheckLogin: Boolean; property ConnectionString: string read _connectionString; property AccountName: string read _accountName; property UserName: string read _userName; property UserID: Integer read _userId; end; implementation { TKingdeeLogin } constructor TKingdeeLogin.Create; begin _clsLogin := CreateOleObject('K3Login.ClsLogin'); end; function TKingdeeLogin.CheckLogin: Boolean; begin Result := _clsLogin.CheckLogin; if Result then InitialLoginDatas; end; procedure TKingdeeLogin.InitialLoginDatas; begin _accountName := _clsLogin.AcctName; ParsePropsStringToField(_clsLogin.PropsString); end; {$REGION '解析PropsString'} procedure TKingdeeLogin.ParsePropsStringToField(propsString: string); var datas: TDictionary<string, string>; begin datas := ReadPropsStringToDictionary(propsString); _userName := GetValueFromDictionary('UserName', datas); _userId := StrToInt(GetValueFromDictionary('UserID', datas)); _connectionString := GetValueFromDictionary('ConnectString', datas); //这里大家可以继续扩展,因为PropsString里面还有很多字段。 datas.Free; end; function TKingdeeLogin.ReadPropsStringToDictionary( propsString: string): TDictionary<string, string>; var dicResult: TDictionary<string, string>; curIndex: Integer; begin dicResult := TDictionary<string, string>.Create; curIndex := 0; while curIndex < Length(propsString) do curIndex := curIndex + ReadSection(dicResult, Copy(propsString, curIndex + 1, Length(propsString) - curIndex)); Result := dicResult; end; function TKingdeeLogin.ReadSection(sections: TDictionary<string, string>; source: string): Integer; var lengthResult: Integer; key, value: string; begin lengthResult := 0; lengthResult := lengthResult + ReadKey(source, key); lengthResult := lengthResult + ReadValue(Copy(source, lengthResult + 1, Length(source) - lengthResult), value); sections.Add(key, value); Result := lengthResult; end; function TKingdeeLogin.ReadKey(source: string; var key: string): Integer; var i, lengthResult: Integer; begin key := ''; lengthResult := 0; for i := 1 to Length(source) do begin lengthResult := i; if source[i] = Char('=') then Break else key := key + source[i]; end; Result := lengthResult; end; function TKingdeeLogin.ReadValue(source: string; var value: string): Integer; var i, lengthResult: Integer; charStack: TStack<Char>; c: Char; begin value := ''; lengthResult := 0; charStack := TStack<Char>.Create; for i := 1 to Length(source) do begin c := source[i]; lengthResult := i; if c = Char('{') then begin if charStack.Count > 0 then value := value + c; charStack.Push(c); end else if c = Char('}') then begin charStack.Pop; if charStack.Count > 0 then value := value + c; end else if c = Char(';') then begin if charStack.Count > 0 then value := value + c else Break; end else begin value := value + c; end; end; Result := lengthResult; charStack.Free; end; function TKingdeeLogin.GetValueFromDictionary(key: string; source: TDictionary<string, string>): string; var dicKey, sKey: string; begin dicKey := ''; for sKey in source.Keys do begin if UpperCase(Trim(key)) = UpperCase(Trim(sKey)) then begin dicKey := sKey; Break; end; end; if dicKey = '' then Result := '' else Result := source[dicKey]; end; {$ENDREGION} end.
调用方式:
procedure TFrmMain.btnGetConnectionStringClick(Sender: TObject); var clsLogin: TKingdeeLogin; begin try clsLogin := TKingdeeLogin.Create; if clsLogin.CheckLogin then begin ConnectionString := clsLogin.ConnectionString ; mmoConnectionString.Text := ConnectionString; lbledtUserName.Text := clsLogin.UserName; lbledtAccountName.Text := clsLogin.AccountName; end else ShowMessage('UnLogin!'); clsLogin.Free; except ShowMessage('必须在安装了金蝶的客户端上运行!'); end; end;
调用,差不多就和上面类似,当然,也可以放在Project文件中,从入口处来处理程序的逻辑,通过判断是否登录,来决定是否运行主窗体。
至此,关于金蝶登录,并取得ConnectionString的例子算是比较完善了,至于接下来怎么做,我比较喜欢直接对数据库动刀,而不是调用金蝶提供的API接口,所以,基本上我需要一个ConnectionString和UserID就足够了。