views:

1076

answers:

2

Hello

I'm developing word automation application and I'm facing serious issue with unexpected RPC/COM cast exception

[System.InvalidCastException: Nie można rzutować obiektu modelu COM typu 'System.__ComObject' na typ interfejsu 'Microsoft.Office.Interop.Word._Application'. Ta operacja nie powiodła się, ponieważ wywołanie metody QueryInterface dla składnika modelu COM w celu uzyskania interfejsu o identyfikatorze IID '{00020970-0000-0000-C000-000000000046}' nie powiodło się z powodu następującego błędu: Serwer RPC jest niedostępny. (Wyjątek od HRESULT: 0x800706BA).]

translation from polish to english:

Unable to cast System.__ComObject to Microsoft.Office.Interop.Word._Application. The reason is that QueryInterface for IID '{00020970-0000-0000-C000-000000000046}' failed - RPC server is unavailable - error code HRESULT: 0x800706BA

Here the brief of wordapp module:

Initialization - after user is logged in.

using Microsoft.Office.Interop.Word;

    public class WordApp       
    {
        Application app = null;
        object m = System.Reflection.Missing.Value; 
        object oFalse = false;  
        object oTrue = true;

....

            app = Activator.CreateInstance(Type.GetTypeFromProgID("Word.Application.12")) as Application;
            app.Visible = false;
            app.DisplayAlerts = WdAlertLevel.wdAlertsNone;
            app.PrintPreview = false;

I'm using Activator.CreateInstance instead of app = new Application() - here the explanation.

Then user can execute 2 actions in wordapp module

a) print prepared docx document

        System.Windows.Forms.PrintDialog pd = new System.Windows.Forms.PrintDialog();
        ...

        this.app.ActivePrinter = pd.PrinterSettings.PrinterName;
        object oNumcopies = pd.PrinterSettings.Copies;
        object oRange = WdPrintOutRange.wdPrintAllDocument;
        object inputname = fullPath;
        Document doc = app.Documents.Add(
                              ref inputname,
                              ref m,
                              ref m,
                              ref m);
        try
        {
            // Print the document 
            doc.PrintOut(ref oFalse, ref oFalse, ref oRange,
                    ref m, ref m, ref m,
                    ref m, ref oNumcopies, ref m, ref m,
                    ref oFalse, ref m, ref m,
                    ref m, ref m, ref m, ref m,
                    ref m);
        }
        finally
        {
            doc.Close(ref oFalse, ref m, ref m);
            doc = null;
        }

b) convert docx to mht

        object inputname = docxname;
        object outputname = htmlname;
        object fileType = WdSaveFormat.wdFormatWebArchive;

        Document doc = app.Documents.Add( 
                              ref inputname,
                              ref m,
                              ref m,
                              ref m);
        try
        {
            doc.SaveAs(ref outputname, ref fileType,
                ref m, ref m, ref m, ref m, ref m, ref m, ref m,
                ref m, ref m, ref m, ref m, ref m, ref m, ref m);
        }
        finally
        {
            doc.Close(ref oFalse, ref m, ref m);
            doc = null;
        }

When user logout, then I release word instance:

            object oSaveChanges = WdSaveOptions.wdDoNotSaveChanges;
            app.Quit(
         ref oSaveChanges,
         ref m,
         ref m);

The exception is thrown out in random places - but the most common place is near app.Documents.Add. After that exception it's not possible to app.Quit. It seems that word instance is dead.

I found that thing in eventlog (application scope):

EventType offdiag12, P1 585d8a02-f370-4c04-85b6-fccad7e80459255ec053-6dbd-4a22-9e59-112a79de8c6a, P2 NIL, P3 NIL, P4 NIL, P5 NIL, P6 NIL, P7 NIL, P8 NIL, P9 NIL, P10 NIL.

I run office diagnostic and it didn't find any error.

Is there possible to enable / find more error informations from system?

This code runs perfectly well on my dev machine (vista). The issue occurs at customers machines (usually winxp sp2/sp3).

Is there an error in my code or what?

The only one thing I need to add. WordModule init/close/print functions are called from main thread and savetomht from backgroundworkders' thread.

+1  A: 

I don't know, but here are some suggestions based on general experience. You might try using distinct m s rather than sharing one between all parameters (the idea being that if the value is being messed with inside it could be having unpredictable results). You also may want to try providing reasonable values (rather than the m s) wherever you can. Some versions of the API may be more forgiving than others.

MarkusQ
+1  A: 

What you describe often refers to the following situation. You use a COM out-proc server (a COM object instantiated in a separate process rather then in the same process as your program) and for some reason that COM server encounters a fatal error and terminates unexpectedly. The COM object you were using no longer exists. Since RPC is used for interacting with out-proc COM servers and the server side no longer exists after termination you receive the error message saying that the RPC server is unavailable which is true but looks confusing.

You have to research and eliminate the reason of COM server termination. The most likely reasons are the following:

  • some unreasonable input values you pass to the calls and
  • an unhandled exception in an event handler. If you have any handling for events fired from a COM component you should catch all the exceptions that may be thrown inside your handler and not let them propagate outside the handler.
sharptooth
Yeah, I agree it could be like that.Now the problem is I have no idea how to detect why word app instance was shutdown. Is there possible to enable logging errors for word?
tomo
No idea of how to enable logging, but you can try to deduce the source of the problem. Do you have event handlers? If so, does any of them propagate exceptions outside? Do you pass nulls for parameters that most likely shouldn't be nulls?
sharptooth
I don't think it's the problem of invalid parameters - because calling these office functions usually works, excluding calls when office disapears.I don't get the idea of event handlers.The only one thing I can do is to unhide word and set message level to all and watch if any appears.
tomo
You can try to attach a debugger the the process where the COM server is loaded. When the process crashes you can inspect the call stack. Not likely to help though.
sharptooth