2011-04-25 444 views
1

這裏是我的代碼:AV發送通過Outlook電子郵件和贖回時

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 ('[email protected]'); 
rdSafeItem.Send; 
rdUtils:= CreateOleObject ('Redemption.MAPIUtils'); 
rdUtils.DeliverNow; 
olNameSpace.Logoff; 
varclear (rdUtils); 
varclear (rdSafeItem); 
varclear (olItem); 
varclear (olNameSpace); 
varclear (olApp); 
end; 

的電子郵件發送後,我得到一個訪問衝突消息在地址A70D6D13(這個地址似乎是不變)。如果我用F8逐步完成整個過程,在'結束'語句之後,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('[email protected]'); 
sItem.Attachments.Add('C:\windows\win.ini'); 
sItem.save; 
SItem.send; 
outlookapplication1.Disconnect; 
end; 

這也給出了同樣的錯誤。什麼是AV的地址神奇?它必須是解決方案的線索。

TIA,

No'am

+0

真的在這裏抓着吸管 - 你有沒有嘗試過在參數聲明中使用'OleVariant'類型,而不是'Variant'? – 2011-04-25 15:41:00

+0

請在第二個代碼片段中顯示變量的聲明。 – crefird 2011-04-29 01:23:34

+0

我剛剛嘗試了全新的Redemption 4.4安裝代碼片段,兩者都運行無誤。所以我懷疑你的問題可能與安裝Redemption及其類型lib有關。我建議你卸載Redemption,從磁盤上刪除dll和tlb的所有副本,然後重新安裝。 – crefird 2011-04-29 17:38:20

回答

0

嘗試丟棄varclear語句。

您描述的症狀表明您正在設法從例程中的內存中驅逐COM對象,然後Delphi在方法變量超出範圍時嘗試再次釋放它們。

+0

唉,刪除'varclear'語句或將其更改爲'olApp:= unassigned'沒有區別。即使在重新啓動後,我也會收到相同地址的錯誤消息。 – 2011-04-25 14:48:31

0

更新

由於No'am正確地評論說,Outlook的應用COM接口不支持連接和斷開。我很驚訝,但我通常使用Delphi包裝器,而TOutlookApplication的Connect實現只是返回CreateOleObject或GetActiveObject的結果。 TOutlookApplication的Disconnect方法的實現實際上不僅僅是發佈接口。如果AutoQuit爲true,它將在應用程序的COM接口上調用Quit。

但是,因爲它似乎是可選的,我認爲不叫olApp.Quit不應該導致No'am遇到的問題。留下我的答案爲「教育」材料,所以其他人不必檢查。


不知道這其實是你的問題的原因,但我在你的代碼錯過的是從Outlook應用程序連接和斷開。儘管他們顯然不需要使用Outlook COM服務器(正如發送的郵件所建議的那樣),但它們是我所知道的「常規」COM使用模式的一部分。我可以很好地想象,當連接/斷開連接/斷開連接超出範圍(在結束語句之後)觸發時,可能導致終結代碼崩潰。

我通常使用的模式是:

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

你會使用創建和免費使用時,德爾福的一個提供TxxxApplication包裝,CreateOleObject和釋放接口(將其設置爲無/未分配),如果你是使用「直線」COM。

在您的例子,這將意味着增加

olApp.Connect; 

的CreateOleObject和olNameSpace分配線間,和olNameSpace.LogOff後加入

olApp.Disconnect; 

;

添加一對try/finally塊也不會被浪費。

+0

連接和斷開連接不是olApp支持的方法。 – 2011-04-25 18:08:03

+0

@ No'am:我很驚訝,但你當然是對的。相應地更新我的答案。 – 2011-04-25 18:29:04

0

我使用贖回5.0.0.2174,德爾福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 ('[email protected]'); 
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; 
+0

唉,同樣的錯誤出現了。 – 2011-04-26 14:41:12

0

˚Firstly,沒有理由使用DeliverNow - MS破壞它在OUtlook 2002: http://www.dimastr.com/redemption/faq.htm#1

其次,它是否工作,如果你忘了Logoff語句? 如果Outlook已經在運行,你需要小心 - 如果用戶正在運行它,你不想殺死它。

0

您在結束語句處得到錯誤,這意味着錯誤可能在清理一些臨時變量時拋出。也許是清理rdSafeItem.Recipients的臨時變量或者與CreateOleObject一起使用的一些中間變量。你可以做的是把你的代碼分割成更小的部分,在那些較小的過程中(至少那些使用中間變量的)做所有與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 ('[email protected]'); 
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。

+0

在更正上述語法(過程應該是函數,CreateSafeMailItem後面稱爲GetSafeMailItem - 但沒關係)後,該程序在作爲獨立程序運行時會提供完全相同的錯誤消息。當通過F8運行時,程序運行正常,沒有錯誤!我不明白這種行爲。我要下載一個新版本的Redemption,看看這是否有所作爲。 – 2011-04-26 14:56:47

+0

更新版本的Redemption沒有任何區別。 – 2011-04-26 15:03:30

+0

@諾曼紐曼:我改正了錯別字。你可以做什麼來進一步診斷問題:在調用函數之前和之後添加OutputDebugStrings。然後啓動DbgView.exe並在調試器外部運行您的應用程序。當出現錯誤時,請檢查dbgview.exe以查看哪個函數失敗。 – 2011-04-27 11:46:19