这是我的代码:
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,
No'am
答案 0 :(得分:0)
尝试删除varclear
语句。
您所描述的症状表明您正在设法从例程中的内存中驱逐COM对象,然后当方法变量超出范围时,Delphi会尝试再次释放它们。
答案 1 :(得分:0)
<强>更新强>
正如No'am正确评论的那样,Outlook的应用程序COM接口不支持Connect和Disconnect。我很惊讶,但我通常使用Delphi包装器,而实际上TOutlookApplication的Connect实现只返回CreateOleObject或GetActiveObject的结果。 TOutlookApplication的Disconnect方法的实现实际上不仅仅是发布接口。如果AutoQuit为true,则在应用程序的COM接口上调用Quit。
然而,由于它似乎是可选的,我认为不要叫olApp.Quit不应该导致No'am有问题。留下我的答案作为“教育”材料,所以其他人不必检查这个。
不确定这实际上是您的问题的原因,但我在您的代码中遗漏的是与Outlook应用程序的连接和断开连接。虽然他们显然不需要使用Outlook COM服务器(正如发送邮件所建议的那样),但它们是我所知道的“正常”COM使用模式的一部分。我可以想象,当vars超出范围(在结束语句之后)触发时,不连接/断开连接可能会导致终结代码失效。
我通常使用的模式是:
Create / CreateOleObject
try
Connect
try
...
finally
Disconnect
end
finally
Free / Release
end
如果您使用“直接”COM,则在使用Delphi提供的TxxxApplication包装器,CreateOleObject和释放界面(将其设置为nil / unassigned)时,您将使用Create和Free。
在您的示例中,这意味着要添加
olApp.Connect;
在CreateOleObject和olNameSpace赋值行之间,并添加
olApp.Disconnect;
添加几个try / finally块也不会浪费。
答案 2 :(得分:0)
我正在使用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;
答案 3 :(得分:0)
首先,没有理由使用DeliverNow - MS在OUtlook 2002中打破了它: http://www.dimastr.com/redemption/faq.htm#1
其次,如果你忘掉了Logoff语句,它会起作用吗? 如果Outlook已经在运行,您需要小心 - 如果用户正在运行它,则不希望将其终止。
答案 4 :(得分:0)
你在结束语句中得到错误,这意味着在清理一些临时变量时可能会抛出错误。也许它会清除rdSafeItem.Recipients
的临时变量或与CreateOleObject
一起使用的某个中间变量。你可以做的是将你的代码分成更小的部分,在那些较小的程序中完成所有与com相关的东西(至少是使用中间变量的程序),而不是在你的main方法中。这可以更容易地追踪问题,甚至可以解决问题。
这样的事情:
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。