How to release COM objects in Silverlight 4

谁都会走 提交于 2019-12-04 05:23:48

You could implement the IDisposable interface. The best example of this I've seen is at http://csfun.blog49.fc2.com/blog-entry-79.html. The blog entry is in Japanese, but open in Chrome and let Google do the page translation for you if you don't read Japanese.

Also, if you just want the source code example of the COM wrapper directly you can download the sample app it comes in: SilverOffice.

Take look at this code:-

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        dynamic app = AutomationFactory.CreateObject("Excel.Application");
        dynamic book = app.Workbooks.Add();
        dynamic sheet = app.ActiveSheet();

        sheet = null;
        book.Close(false);
        book = null;
        app.Quit();
        app = null;

        GC.Collect();
    }

The Excel process appears and then disappears. Remove the GC and the Excel process will continue. Do you get the same if you copy this code verbatim? If so then it would suggest that somewhere in your code a reference to an excel object remains reachable from one of the thread stacks or static fields.

Do you ever hold an excel object in a field (as opposed to a local variable)?

Do you hold an excel object in what appears to be variable but is referenced from a dynamic delegate or lambda that is used as an event handler?

Are you attaching event handlers to long-lived objects from an object that has a short lifespan? If so are you ensuring you detach from those handlers properly?

Many of these things can catch devs out into leaving what they think are objects ready for GC but the GC finds them accessible and therefore not candidates for collection.

If the code above doesn't behave the same then we a looking for another issue entirely. I'm using Office 2007 on Server 2008 R2 from the latest SL 4 runtime. However if we are having a varition because of setup then we're on very shakey ground.

Edit

With some testing this appears to be effective:-

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        using (dynamic app = AutomationFactory.CreateObject("Excel.Application"))
        {
            using (dynamic book = app.Workbooks.Add())
            {
                using (dynamic sheet = app.ActiveSheet())
                {

                }
                book.Close();
            }
            app.Quit();
        };

        GC.Collect();
    }

However leave off the GC and you will end up with unwanted Excel processes left running eventually.

I would consider building the Excel file in a WCF service. You can do all the clean up there. Send to bytes to your Silverlight app and use a SaveFileDialog to send them to the user.

Silverlight has a restriction on access to the client file system. Manipulating an Excel file on the client's system, or even assuming the client has Excel installed seems like a violation of this.

Dr. René Koch

by wrapping references in a using statement the COM references are released

Please note: using statements are just syntactic sugar for try/catch/finally with Dispose() in the finally clause.

Also, most applications don't allow for using statements in this case, because creation and cleanup of COM objects are distributed among various places/methods.

The critical line which is needed here reads:

((IDisposable)_excel).Dispose();  // Release COM Interface

This assumes:

dynamic _excel = AutomationFactory.CreateObject("Excel.Application");
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!