繁体   English   中英

通过Outlook和兑换发送电子邮件时显示AV

[英]AV when sending email via Outlook and Redemption

这是我的代码:

const
 olMailItem = 0;

var
 olApp, OlNameSpace, OlItem, rdSafeItem, rdUtils: variant;

begin
 olApp:= CreateOleObject ('Outlook.Application');
 olNameSpace:= olApp.GetNamespace ('MAPI');
 olNameSpace.Logon;
 olItem:= olApp.CreateItem (olMailItem);
 rdSafeItem:= CreateOleObject ('Redemption.SafeMailItem');
 rdSafeItem.Item:= olItem;

 rdSafeItem.Subject:= 'Testing';
 rdSafeItem.attachments.Add ('c:\windows\win.ini');
 rdSafeItem.Recipients.Add ('test@testing.com');
 rdSafeItem.Send;
 rdUtils:= CreateOleObject ('Redemption.MAPIUtils');
 rdUtils.DeliverNow;
 olNameSpace.Logoff;
 varclear (rdUtils);
 varclear (rdSafeItem);
 varclear (olItem);
 varclear (olNameSpace);
 varclear (olApp);
end;

发送电子邮件后,我在地址A70D6D13收到访问冲突消息(此地址似乎是恒定的)。 如果我使用F8逐步执行整个过程,则在“ end”语句之后,CPU窗口将显示在地址A70D6D13上,所有内存均显示为????。

我正在使用Delphi 7,Outlook 2003,Redemption 4.8.0.1184此代码缺少什么?

编辑:我发现了其他一些代码片段,可以通过Outlook / Redemption发送邮件。 这是一个使用OutlookApplication服务器的片段。

begin
 outlookapplication1.Connect;
 NmSpace:= outlookapplication1.GetNamespace('MAPI');
 NmSpace.Logon('', '', False, False);
 oItem:= outlookapplication1.CreateItem(olMailItem);
 sItem:= CreateOleObject('Redemption.SafeMailItem');
 oItem.Subject:= 'my subject';
 oItem.save;
 sItem.Item:= oItem;
 sItem.Recipients.Add('test@test.com');
 sItem.Attachments.Add('C:\windows\win.ini');
 sItem.save;
 SItem.send;
 outlookapplication1.Disconnect;
end;

这也给出了相同的错误。 AV的地址有什么神奇之处? 它必须是解决方案的线索。

TIA,

不行

尝试删除varclear语句。

您所描述的症状表明您正在设法从例程中的内存中逐出COM对象,然后,当方法变量超出范围时,Delphi会尝试再次释放它们。

更新资料

正如No'am正确评论的那样,Outlook的应用程序COM接口不支持“连接和断开连接”。 让我感到惊讶的是,但是我通常使用Delphi包装器,实际上TOutlookApplication的Connect实现只是返回CreateOleObject或GetActiveObject的结果。 TOutlookApplication的Disconnect方法的实现实际上除了发布接口之外还做其他事情。 如果AutoQuit为true,它将在应用程序的COM接口上调用Quit。

但是,由于它似乎是可选的,所以我认为不致电olApp.Quit不会引起No'am遇到的问题。 把我的答案留作“教育性”材料,这样其他人就不必检查了。


不确定这实际上是造成您问题的原因,但是我在您的代码中缺少的是与Outlook应用程序的连接和断开连接。 尽管显然不需要使用Outlook COM服务器(如所发送的邮件所示),但它们是我所知道的“常规” COM使用模式的一部分。 我完全可以想象,当由var超出范围(在end语句之后)触发时,不连接/断开连接很可能会导致完成代码掉落。

我通常使用的模式是:

Create / CreateOleObject
try
  Connect
  try
    ...
  finally
    Disconnect
  end
finally
  Free / Release 
end

如果使用“直接” COM,则在使用Delphi提供的TxxxApplication包装程序,CreateOleObject和释放接口(将其设置为nil / unssigned)之一时,可以使用Create和Free。

在您的示例中,这意味着添加

olApp.Connect;

在CreateOleObject和olNameSpace分配行之间添加

olApp.Disconnect;

在olNameSpace.LogOff之后;

添加几个try / finally块也不会浪费。

我正在使用Redemption 5.0.0.2174,Delphi 7,Outlook 2003

我修改了您的代码,如下所示,并且能够发送电子邮件而没有任何错误

const
 olMailItem = 0;
var
 olApp, OlNameSpace, OlItem, rdSafeItem, rdUtils: variant;
begin
 olApp:= CreateOleObject ('Outlook.Application');
 olNameSpace:= olApp.GetNamespace ('MAPI');
 olNameSpace.Logon;
 olItem:= olApp.CreateItem (olMailItem);
 rdSafeItem:= CreateOleObject ('Redemption.SafeMailItem');
 rdSafeItem.Item:= olItem;
 rdSafeItem.Subject:= 'Testing';
 rdSafeItem.attachments.Add ('c:\windows\win.ini');
 rdSafeItem.Recipients.Add ('test@testing.com');
 rdSafeItem.Recipients.ResolveAll;                       // added
 rdSafeItem.Send;
// rdUtils:= CreateOleObject ('Redemption.MAPIUtils');
// rdUtils.DeliverNow;
 olNameSpace.Logoff;
// varclear (rdUtils);
// varclear (rdSafeItem);
// varclear (olItem);
// varclear (olNameSpace);
// varclear (olApp);
end;

首先,没有理由使用DeliverNow-MS在OUtlook 2002中将其破坏: http : //www.dimastr.com/redemption/faq.htm#1

其次,如果您删除了Logoff语句,是否有效? 如果Outlook已经在运行,则需要小心-如果用户正在运行,则不想杀死它。

您会在end语句中看到错误,这意味着在清理一些临时变量时可能会抛出该错误。 可能是清理rdSafeItem.Recipients的临时变量或与CreateOleObject使用的某些中间变量。 您可以做的是将代码切成小段,在那些较小的过程中(至少是使用中间变量的过程)而不是在main方法中进行所有与com相关的工作。 这可以使查找问题更容易,甚至可以解决问题。

像这样:

function CreateOutlookApp: OleVariant;
begin
  Result := CreateOleObject ('Outlook.Application');
end;

function GetAndLogonNamespace(const olApp: OleVariant): OleVariant;
begin
  Result := olApp.GetNamespace ('MAPI');
  Result.Logon;
end;

function GetSafeMailItem(const olApp: OleVariant): OleVariant;
const
 olMailItem = 0;
var
  olItem: OleVariant;
begin
  olItem:= olApp.CreateItem (olMailItem);
  Result := CreateOleObject ('Redemption.SafeMailItem');
  Result.Item:= olItem;

  Result.Subject:= 'Testing';
  Result.attachments.Add ('c:\windows\win.ini');
  Result.Recipients.Add ('test@testing.com');
end;

procedure SendTestMail;
var
 olApp, olNameSpace, rdSafeItem: OleVariant
begin
 OutputDebugString('CreateOutlookApp');
 olApp := CreateOutlookApp;
 OutputDebugString('GetAndLogonNamespace');
 olNameSpace := GetAndLogonNamespace(olApp);
 OutputDebugString('GetSafeMailItem');
 rdSafeItem := GetSafeMailItem(olApp);
 OutputDebugString('rdSafeItem.Send');
 rdSafeItem.Send;
 OutputDebugString('DeliverNow');
 DeliverNow; //implement this yourself
 OutputDebugString('LogoffNamespace');
 LogoffNamespace(olNamespace); //implement this yourself
 OutputDebugString('Cleaning up');
end;

编辑:添加了OutputDebugStrings,因为该错误似乎仅在没有调试器的情况下运行应用程序时发生。 当您发现有问题的函数时,可以在其中添加更多OutputDebugStrings。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM