1

これが私のコードです:

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 サーバーを使用するスニペットの 1 つです。

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のアドレスの魔法とは?解決の糸口になるはずです。

ティア、

ノアム

4

5 に答える 5

0

アップデート

No'amが正しくコメントしているように、OutlookのアプリケーションCOMインターフェイスは接続と切断をサポートしていません。私はそれに驚きましたが、私は通常Delphiラッパーを使用しており、実際、TOutlookApplicationのConnectの実装は、CreateOleObjectまたはGetActiveObjectの結果を返すだけです。TOutlookApplicationのDisconnectメソッドの実装は、実際にはインターフェイスを解放するだけではありません。AutoQuitがtrueの場合、アプリケーションのCOMインターフェイスでQuitを呼び出します。

ただし、オプションのように思われるので、olApp.Quitを呼び出さなくても、No'amが抱えている問題は発生しないはずです。私の答えを「教育的な」資料として残し、他の人がこれをチェックする必要がないようにします。


これが実際に問題の原因であるかどうかはわかりませんが、コードで見逃しているのは、Outlookアプリケーションへの接続と切断です。Outlook COMサーバーを使用するためにそれらは明らかに必要ではありませんが(送信されるメールによって示唆されるように)、それらは私が知っている「通常の」COM使用パターンの一部です。接続/切断しないと、varsがスコープ外になることによってトリガーされたときにファイナライズコードがフォールオーバーする可能性があることをよく想像できます(endステートメントの後)。

私が通常使用するパターンは次のとおりです。

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

Delphiが提供するTxxxApplicationラッパーの1つであるCreateOleObjectを使用する場合は、Create and Freeを使用し、「ストレート」COMを使用している場合は、インターフェイスを解放します(nil / unassignedに設定します)。

あなたの例では、それは追加することを意味します

olApp.Connect;

CreateOleObjectとolNameSpaceの割り当て行の間に、追加します

olApp.Disconnect;

olNameSpace.LogOffの後;

try/finallyブロックをいくつか追加しても無駄にはなりません。

于 2011-04-25T17:15:53.843 に答える
0

Redemption 5.0.0.2174、Delphi 7、Outlook2003を使用しています

次のようにコードを変更し、エラーなしでメールを送信できました

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;
于 2011-04-25T19:17:31.433 に答える
0

まず、DeliverNow を使用する理由はありません - MS は OUtlook 2002 でそれを破りました: http://www.dimastr.com/redemption/faq.htm#1

次に、Logoff ステートメントを削除すると機能しますか? Outlook が既に実行されている場合は注意する必要があります。ユーザーが実行している場合は、それを強制終了したくありません。

于 2011-04-25T22:53:26.073 に答える
0

end ステートメントでエラーが発生します。これは、いくつかの一時変数をクリーンアップしているときにエラーがスローされる可能性があることを意味します。たぶん、一時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 ('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 を追加できます。

于 2011-04-26T07:07:25.283 に答える
0

varclearステートメント を削除してみてください。

あなたが説明している症状は、ルーチンで COM オブジェクトをメモリから追い出し、メソッド変数が範囲外になったときに Delphi がそれらを再度解放しようとしていることを示唆しています。

于 2011-04-25T14:38:16.313 に答える