How to avoid RPC_E_CALL_REJECTED exceptions during PowerPoint automation?

When my code tries to create a new instance of Microsoft.Office.Interop.PowerPoint.Application , I sometimes get the following exception:

 System.Runtime.InteropServices.COMException (0x80010001): Retrieving the COM class factory for component with CLSID {91493441-5A91-11CF-8700-00AA0060263B} failed due to the following error: 80010001 Call was rejected by callee. (Exception from HRESULT: 0x80010001 (RPC_E_CALL_REJECTED)). at System.Runtime.Remoting.RemotingServices.AllocateUninitializedObject(RuntimeType objectType) at System.Runtime.Remoting.Activation.ActivationServices.CreateInstance(RuntimeType serverType) at System.Runtime.Remoting.Activation.ActivationServices.IsCurrentContextOK(RuntimeType serverType, Object[] props, Boolean bNewObj) at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) at System.Activator.CreateInstance(Type type, Boolean nonPublic) 

I say sometimes because this does not happen sequentially even with the same input. In addition, it also occurs (with the same lack of consistency) in other parts of my code, where I also interact with the PowerPoint Automation API.

I tried this solution from MSDN itself, which seems to be the most recommended solution. However, this does not seem to have any effect, as I am still observing the same behavior.

My questions:

  • Does MSDN solution work for PowerPoint automation?
  • How can I check if I applied it correctly to my code?
  • Does anyone have an alternative solution?

I am using C #, .NET 4 and PowerPoint 2007.

+7
source share
2 answers
+2
source

I have come across this before and Paul B is really right. It depends on whether you are calling Powerpoint OM from the main thread (i.e. This_AddIn ) or not. If you, ppt should not throw these exceptions. However, if you call ppt from another thread, you must implement IMessageFilter to effectively manage these messages with message pump errors, since ppt prioritizes the main thread calls for OM over calls from other threads, hence rejecting the call.

There is another caveat that requires additional boiler plate code to handle additional COMException , such as 0x800AC472 (VBA_E_IGNORE) . The following is an example.

So, the complete solution is to implement IMessageFilter and use something like sepp2k in which you can wrap your OM calls in order to handle other types of COMException that might be thrown.

So, for wrapping code like this:

 private void TryUntilSuccess(Action action) { bool success = false; while (!success) { try { action(); success = true; } catch (System.Runtime.InteropServices.COMException e) { if ((e.ErrorCode & 0xFFFF) == 0xC472) { // Excel is busy Thread.Sleep(500); // Wait, and... success = false; // ...try again } else { // Re-throw! throw e; } } } } 

which you could call using lamdas as follows:

 TryUntilSuccess(() => { RegisterFilter(); // register this thread for IMessageFilter use ppt_app.DoSomething(); UnRegisterFilter(); // unregister this thread for IMessageFilter use };) 

The reason for this bi-directional approach is that the IMessageFilter strategy is more efficient than throwing exceptions and there will be more time than it will not be able to process busy messages coming from the application. However, at another time you will have to handle the exceptions, so you need to do both ...

See here Implementing IMessageFilter , which Includes Wrappers

Hth!

+2
source

All Articles