我目前正致力于将我们的应用程序中的日历约会同步到Win Server 2008上的Exchange Server 2007 SP1。它应该处理删除和添加多个用户帐户的约会。该接口是使用Delphi XE5的WDSL-Import组件创建的。它生成一个类型'ExchangeServicePortType',使用如下:
var
ws: ExchangeServicePortType;
exCreate: CreateItem;
exItemResp: CreateItemResponse;
exImper: ExchangeImpersonation;
secContext: SerializedSecurityContext;
exMailboxCult: MailboxCulture;
exReqServerVersion: RequestServerVersion;
exServerVersion: ServerVersionInfo;
....
ws := GetExchangeServicePortType(false);
...
exImper.ConnectingSID.SID := <useraccount>;
...
ws.CreateItem(exCreate, exImper, secContext, exMailboxCult, exReqServerVersion,
exCreateItemResponse, exServerVersion);
问题: 在以下情况下,它只适用于“假冒”:
问题:在Delphi XE中是否有可能在没有“假冒”的情况下调用EWS,它是如何工作的?
在托管API中,可以调用:
ExchangeServiceBinding ws = new ExchangeServiceBinding();
ws.Credentials = new NetworkCredential("user", "password", "domain");
任何帮助/想法/解释/建议都非常感谢。
感谢David Heffernan。 我尝试了使用C#-dll(Visual Studio 2010)和R. Giesecke的.DllExport扩展以及EWS托管api 1.2的建议方法。代码如下:
EWSTerminSync.cs
...
using System.Runtime.InteropServices;
using RGiesecke.DllExport;
...
public class EWSSync
{
public static ExchangeService service;
private static bool CertificateValidationCallBack(
object sender,
System.Security.Cryptography.X509Certificates.X509Certificate certificate,
System.Security.Cryptography.X509Certificates.X509Chain chain,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
...
}
[DllExport]
public static int InitEWS()
{
(0)ServicePointManager.ServerCertificateValidationCallback = CertificateValidationCallBack;
(1) service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Credentials = new WebCredentials("name", "pwd", "domain");
service.Url = new Uri("https://myServer/EWS/Exchange.asmx");
...
}
[DllExport]
public static int DoSomething()
{
...
}
}
C#-dll加载到Delphi7应用程序中,如下所示:
type
TCreateInstance = function(): integer; stdcall;
FDLLHandle: THandle;
...
procedure Execute()
var
res: integer;
begin
FDLLHandle := LoadLibrary(pansichar('EWSTerminSync.dll'));
if FDLLHandle >= 32 then
begin
@FCreateInstance := GetProcAddress(FDLLHandle, 'InitEWS');
res := FCreateInstance;
...
end;
...
end;
如果它作为delphi应用程序执行,一切正常。我可以创建/删除约会和日历等内容。 但我必须在作为Windows服务运行的delphi应用程序中使用它。相同的代码产生错误“EXCEPTION:EExternalException / Externe Exception E0434352”。 在函数InitEWS()中运行第(1)行。如果不调用任何ews托管的api函数,只需在函数InitEWS()中执行一些字符串操作,一切都可以在服务中正常工作。 应用程序和服务在相同的用户凭据下运行。
在Windows服务中使用ews托管api有任何限制吗? 为了在服务中调用ews托管api函数,必须执行哪些设置?
答案 0 :(得分:0)
你可以在没有模仿的情况下使用Ews,问题就是Delphi添加了一个xml节点,即使是nil参数(无论soDontSendEmptyNodes选项如何)。我找不到更好的方法来消除这个,而不是创建一个新的TOPToSoapDomConvert类,它只是跳过nil参数。
unit SoapHelpers;
interface
uses
System.Classes, Soap.IntfInfo, Soap.InvokeRegistry, Soap.OPToSOAPDomConv;
type
TOPToSoapDomConvert2 = class(TOPToSoapDomConvert)
public
function InvContextToMsg(const IntfMD: TIntfMetaData;
MethNum: Integer;
Con: TInvContext;
Headers: THeaderList): TStream; override;
end;
implementation
uses
System.SysUtils, System.TypInfo;
type
TInvContextTmp = class(TInvContext)
public
procedure CopyPointers(Cont: TInvContext);
procedure RemovePointer(Index: Integer);
end;
const
IS_OUT = $0200;
{ TOPToSoapDomConvert2 }
// Skip null parameters they are always being sent regardless of sendemptynodes settings
function TOPToSoapDomConvert2.InvContextToMsg(const IntfMD: TIntfMetaData;
MethNum: Integer; Con: TInvContext; Headers: THeaderList): TStream;
var
MethMD: TIntfMethEntry;
Params, ParamsSave: TIntfParamEntryArray;
Con2: TInvContextTmp;
P: Pointer;
I, K, XmlOptions, ParamCountSave, ParamCount: Integer;
ExtParamName, ParamNamespace: string;
begin
MethMD := IntfMD.MDA[MethNum];
ParamsSave := MethMD.Params;
ParamCountSave := MethMD.ParamCount;
ParamCount := MethMD.ParamCount;
SetLength(Params, Length(MethMD.Params));
for I := Low(Params) to High(Params) do
Params[I] := MethMD.Params[I];
Con2 := TInvContextTmp.Create;
Con2.CopyPointers(Con);
for I := High(Params) downto Low(Params) do
begin
InvRegistry.GetParamInfo(IntfMD.Info, MethMD.Name, Params[I].Name,
ExtParamName, ParamNamespace, XMLOptions);
if not ((pfOut in Params[I].Flags) or ((XMLOptions and IS_OUT) = IS_OUT)) then
begin
P := Con.GetParamPointer(I);
if (Params[I].Info <> nil) and (Params[I].Info.Kind = tkClass) and (Pointer(P^) = nil) then
begin
for K := I + 1 to High(Params) do
Params[K-1] := Params[K];
SetLength(Params, Length(Params)-1);
Dec(ParamCount);
Con2.RemovePointer(I);
end;
end;
end;
if Length(MethMD.Params) <> Length(Params) then
begin
MethMD.ParamCount := ParamCount;
MethMD.Params := Params;
IntfMD.MDA[MethNum] := MethMD;
end;
try
Result := inherited InvContextToMsg(IntfMD, MethNum, Con2, Headers);
finally
if Length(MethMD.Params) <> Length(ParamsSave) then
begin
MethMD.ParamCount := ParamCountSave;
MethMD.Params := ParamsSave;
IntfMD.MDA[MethNum] := MethMD;
end;
Con2.Free;
end;
end;
{ TInvContextTmp }
procedure TInvContextTmp.CopyPointers(Cont: TInvContext);
var
k: Integer;
begin
SetLength(DataP, Length(TInvContextTmp(Cont).DataP));
for k := Low(TInvContextTmp(Cont).DataP) to High(TInvContextTmp(Cont).DataP) do
DataP[k] := TInvContextTmp(Cont).DataP[k];
end;
procedure TInvContextTmp.RemovePointer(Index: Integer);
var
k: Integer;
begin
for k := Index+1 to High(DataP) do
DataP[k-1] := DataP[k];
end;
end.
何时,你可以像这样使用它:
...
lRIO := THTTPRio.Create(nil);
lRIO.Converter := TOPToSoapDomConvert2.Create(lRIO);
lRIO.Converter.WSDLView := nil;
...