0

We have an internally written program in C# that use RDO in Outlook Redemption to create, modify, or delete contacts in an Outlook Contacts folder. This is Outlook 2019 connected to on-premise Exchange. The program is successful is creating, modifying or deleting contacts. However, if Outlook is not running, when the C# program tries to exit, it hangs. I can see the process is idle in Task Manager. Even if I wait overnight, the program never exits.

If I run the C# program with Outlook running, the program runs to completion, doing what it needs to do, and exits successfully.

What do I need to change, whether it's in the C# code, in Outlook settings, or in Windows settings, that will allow the program to exit cleanly?

Eugene Astafiev
  • 47,483
  • 3
  • 24
  • 45
  • Wow Outlook Redemption, that’s something I used a very long time ago! Are you sure the tool’s code isn’t just waiting for Outlook to respond? – stuartd Aug 01 '22 at 22:35
  • @stuartd, pretty sure the code is not waiting for Outlook to respond. It's a console program, and reads its parameters from an INI file. It writes a "**** DONE ****" at the end of its processing, and the last things it's supposed to do is write to a text log, then Environment.ExitCode(0). At no obvious point is it interacting with Outlook; Outlook interop insn't ever referenced in the Using statements. – REsguerra Aug 01 '22 at 22:53
  • Remember that OOM is an out-of-proc COM library and no Outlook objects live in your process, only the proxies that talk to the objects inside the outlook.exe address space. Redemption library is in-proc, which means MAPI system and common Office runtime are loaded in your process, and they can be picky how they are shut down. – Dmitry Streblechenko Aug 01 '22 at 23:02

3 Answers3

0

This is a guess, as you don't share enough code. But I would suspect that your program is not disposing the resources. Make sure "using" is being used wherever you create the RDO objects, to make sure your program is not leaking them

Bruno Guardia
  • 453
  • 4
  • 14
  • Bruno, there is quite a bit of code, so I'm not sure what code I should be sharing. This console program is a modification of the original, which used Outlook interop instead of Outlook Redemption. I'm puzzled why Outlook running would allow the program to exit if the cause is improperly disposed RDO objects. Nevertheless, I'll take a close look. Thanks. – REsguerra Aug 01 '22 at 22:56
  • Keep in mind that OOM is an out-of-proc COM library - all Outlook objects live in the outlook.exe address space. Redemption is an in-proc COM library that loads Extended MAPI and Common Office runtime in-proc, and they can be picky how they are released on shutdown. – Dmitry Streblechenko Aug 01 '22 at 23:06
0

Yes, most likely you are not making sure all Redemption objects and RDOSession in particular, are not being released on the main thread.

Before shutdown, make sure all global Redemption objects are either explicitly released by calling Marshal.ReleaseComObject or go out of scope. In the latter case, call GC.Collect() (to make sure all out-of-scope objects are immediately released) before releasing RDOSession with Marshal.ReleaseComObject.

In the worst case, try calling RDOSession.DoFastShutdown() before closing.

Dmitry Streblechenko
  • 62,942
  • 4
  • 53
  • 78
0

Outlook programming (and Redemption) is based on dealing with underlying COM objects. You need to keep that in mind when dealing with Outlook or Redemption.

To deal with underlying COM objects correctly I'd recommend using the ReleaseComObject method of the Marshal class which decrements the reference count of the specified Runtime Callable Wrapper (RCW) associated with the specified COM object, however it doesn't release an object. So, to release the object the number of increment and decrement operations should be equal.

Typically you need to release every object returned from the Office (Outlook or Redemption in your case) object model. Exceptions are objects passed to event handlers as parameters.

Also you may consider using the following sequence of calls to release objects:

GC.Collect
GC.WaitForPendingFinalizers
GC.Collect
GC.WaitForPendingFinalizers

As soon as all underlying COM objects are released the managed application can be closed. You may read more about that and find answers to your multiple questions in the When to release COM objects in Office add-ins developed in .NET article.

Eugene Astafiev
  • 47,483
  • 3
  • 24
  • 45