I have some older code connecting to Outlook through OLE that no longer works running on Win10 where Outlook is set up to connect to Exchange online: It raises an exception with message (Dutch) "De bewerking is afgebroken", probably translated as "The operation was aborted" *, when I try to get properties in two different places indicated by !!!:
const
scxOutlookApp = 'outlook.application';
scxNameSpace = 'MAPI';
type
TDataModuleSyncOutlook = class(TTimeTellDataModule)
private
FOutlookApp,
FNameSpace,
FCalendarFolder: OleVariant;
function TDataModuleSyncOutlook.ConnectToOutlook(AUserSMTP: String = ''): Boolean;
var
lRecipient,
lVar : OleVariant;
lLog,
lLoginSMTP: String;
begin
Result := false;
FWasCreated := False;
try
FOutlookApp := GetActiveOleObject(scxOutlookApp);
Result := True;
except
try
FOutlookApp := CreateOleObject(scxOutlookApp);
FWasCreated := True;
Result := True;
except
on E:Exception do
TSyncLogger.LogError('Inner exception 1: ' + E.Message); // Just some logging
end;
end;
if Result then
begin
try
FNameSpace := FOutlookApp.GetNamespace(scxNameSpace);
// From https://stackoverflow.com/questions/18053110/retrieve-outlook-logged-in-user-smtp-address-after-connecting-through-ole/
lLog := Format('Connected to Outlook; Application.DefaultProfilename: %s, Application.Name: %s, Application.Version: %s, NameSpace.CurrentProfileName: %s, NameSpace.ExchangeMailboxServerName: %s, NameSpace.Type: %s',
[FOutlookApp.DefaultProfileName,
FOutlookApp.Name,
FOutlookApp.Version,
FNameSpace.CurrentProfileName,
FNameSpace.ExchangeMailboxServerName,
FNameSpace.Type]);
TSyncLogger.LogDebug(lLog);
// Output here is:
// Connected to Outlook; Application.DefaultProfilename: Office365, Application.Name: Outlook, Application.Version: 16.0.0.13801, NameSpace.CurrentProfileName: Office365, NameSpace.ExchangeMailboxServerName: https://outlook.office365.com/mapi/emsmdb/?MailboxId=23[snip]1de@timetell.nl, NameSpace.Type: Mapi
lVar := FOutlookApp.Session; // NameSpace object for the current session
// VarIsClear(lVar) is FALSE here, then this goes wrong: !!!1
if not VarIsClear(lVar) then lVar := lVar.CurrentUser; // Recipient object for the currently logged-on user
if not VarIsClear(lVar) then lVar := lVar.AddressEntry; // AddressEntry object for the recipient
if not VarIsClear(lVar) then lVar := lVar.GetExchangeUser; // Returns an ExchangeUser object that represents the AddressEntry
if not VarIsClear(lVar) then lVar := lVar.PrimarySmtpAddress; // String representing the SMTP address for the ExchangeUser
if not VarIsClear(lVar) then
begin
lLoginSMTP := FOutlookApp.Session.CurrentUser.AddressEntry.GetExchangeUser.PrimarySmtpAddress;
TSyncLogger.LogDebug('Primary Exchange SMTP address detected as: ' + lLoginSMTP);
end
else
begin
TSyncLogger.LogError(sErrNoExchangeAccount);
DisConnectFromOutlook;
Exit;
end;
except
on E:Exception do
begin
TSyncLogger.LogError('Inner exception 2: ' + E.Message); // This is where we come after the CurrentUser error
DisConnectFromOutlook;
Exit;
end;
end;
If I comment out the above section playing with the lVar
to avoid the exception, the following code gets executed, but it then shows the same problem when retrieving lRecipient.Address
:
if LowerCase(AUserSMTP) <> Lowercase(lLoginSMTP) then
begin // Open shared calendar if it's a different user
try
lRecipient := FNameSpace.CreateRecipient(AUserSMTP);
if not VarIsClear(lRecipient) then // Also FALSE at this moment !!! 2
begin
lLog := Format('Logging in as different user (%s), created recipient for %s, calling GetSharedDefaultFolder',[AUserSMTP,lRecipient.Address]);
TSyncLogger.LogDebug(lLog);
end
else
OutputDebugString('lRecipient unassigned');
FCalendarFolder := FNameSpace.GetSharedDefaultFolder(lRecipient, olFolderCalendar);
if not VarIsClear(FCalendarFolder) then
begin
lLog := Format('GetSharedDefaultFolder folder path = %s',[FCalendarFolder.FolderPath]);
TSyncLogger.LogDebug(lLog);
end
else
OutputDebugString('FCalendarFolder unassigned');
except
on E:Exception do
begin
Result := false; // This is where we come after the lRecipient.Address error
TSyncLogger.LogError(Format(sErrOpenGedeeldeAgenda,[AUserSMTP]));
end;
end;
end
else // ... otherwise open default calendar folder
begin
FCalendarFolder := FNameSpace.GetDefaultFolder(olFolderCalendar);
TSyncLogger.LogDebug('Opened default calendar folder, folder path = ' + FCalendarFolder.FolderPath);
end;
end; // if Result
if Result then TSyncLogger.LogDebug('Connected to Outlook') else TSyncLogger.LogAlways('Connection to Outlook failed');
end;
- OLE is already properly initialized at this stage
- I have verified that the NameSpace.CurrentUser and Recipient.Address properties still exist
- It makes no difference if I have Outlook running or not at these moments
- AUserSMTP is a valid Exchange user who has shared his calendar with me on this machine, it is the primary SMTP address of the user which we use in FNameSpace.CreateRecipient.
(FWIW We also do calendar synchronisation with the same users and data through EWS, and that works fine, so rights don't seem to be the issue). - Registry keys for MAPI access are correct
- This is a 32 bit Delphi 10.4.1 desktop app running on Win 10; the code is running in the main thread
- FNameSpace.ExchangeConnectionMode is 700=olCachedConnectedFull
- CurrentUser is defined: In Outloik, when I use Alt+F11 to open the VBA project, select View, Immediate Window, type
? Application.Session.CurrentUser.Name
I get my name - Trust Center settings are greyed out (but I would have expected an error earlier if they were interfering):
What can be going on? Why does accessing these two properties NameSpace.CurrentUser
and Recipient.Address
cause an exception or what can I try to resolve this (e.g. get more error info than "The operation was aborted")?
* It's probably the 0x80004004 Operation aborted error