Вижте другите продукти, за които се отнася тази статия.

Симптоми

Когато автоматизирате приложение на Microsoft Office от Microsoft Visual Basic .NET или Microsoft Visual C# .NET, приложението Office не излиза, когато се обадите на метода Quit.

Причина

Когато Visual Studio .NET извива COM обект от управляван код, той автоматично създава обвивка, която може да се използва по време на изпълнение (RCW). RCW-тата се обажда между .NET приложението и COM обекта. RCW запазва броя на препратките към COM обекта. Следователно ако всички препратки не са издадени в RCW, COM обектът не се отказва.

Решение

За да се уверите, Office приложението излиза, определете дали вашият код за автоматизация отговаря на следните критерии:

  • Декларирайте всеки обект като нова променлива. Например променете следния ред с код:

    oBook = oExcel.Workbooks.Add()
    

    Променете това на следното:

    dim oBooks as Excel.Workbooks
    oBooks = oExcel.Workbooks
    oBook = oBooks.Add()
    
  • Използвайте System.Runtime.InteropServices.Marshal.ReleaseComObject в цикъл, докато не се върне 0, когато приключите с използването на обект. System.Runtime.InteropServices.Marshal.ReleaseComObject намалява броя на препратките на RCW, а цикълът гарантира, че базовият COM компонент се издава независимо колко пъти е влязъл отново в CLR.

  • За да освободите препратката към променливата, задайте променливата равна на Нищо или Null.

  • Използвайте метода Quit на обекта Office приложение, за да кажете на сървъра да се изключи.

Състояние

Това поведение е по проект.

Повече информация

Стъпки за възпроизвеждане на поведението

  1. Стартирайте Visual Studio .NET.

  2. В менюто Файл щракнете върху Създаване и след това щракнете върху Project. Под Visual Basic проекти изберете Windows приложение и след това щракнете върху OK.Забележка Формуляр1 се създава по подразбиране.

  3. Добавете препратка към библиотеката с Microsoft Excel обекти. За да направите това, изпълнете следните стъпки:

    1. В менюто Project щракнете върху Добавяне на препратка.

    2. В раздела COM намерете библиотеката с обекти за Excel и след това щракнете върху Избор.За Microsoft Excel 2002: Microsoft Excel 10.0 Object LibraryNote Ако все още не сте направили това, ви препоръчваме да изтеглите и инсталирате основните междуопрочни асемблии на Microsoft Office XP (PIAs).За повече информация относно Office XP PIAs отидете на следната статия в базата знания на Microsoft:

      328912 Microsoft Office основни interop асемблирания на XP (PIAs) са налични за изтегляне   За Microsoft Office Excel 2003: Microsoft Excel 11.0 Библиотека с обекти

    3. Щракнете върху OK в диалоговия прозорец Добавяне на препратки, за да приемете избора си.

  4. В менюто Изглед щракнете върху Кутия с инструменти и след това плъзнете контрола на бутон във Формуляр1.

  5. Щракнете двукратно върху Бутон1.Забележка Показва се прозорецът с код за формуляра.

  6. Добавете следния код в горната част на Form1.vb:

    Imports Microsoft.Office.Interop
    
  7. Заместете следния код в прозореца на кода:

        Private Sub Button1_Click(ByVal sender As System.Object, _
           ByVal e As System.EventArgs) Handles Button1.Click
        End Sub
    

    Заместете следния код:

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim oApp As New Excel.Application()
        Dim oBook As Excel.Workbook = oApp.Workbooks.Add
        Dim oSheet As Excel.Worksheet = oApp.ActiveSheet
    
        oSheet = Nothing
        oBook.Close(False)
        oBook = Nothing
        oApp.Quit()
        oApp = Nothing
    
        Debug.WriteLine("Sleeping...")
        System.Threading.Thread.Sleep(5000)
        Debug.WriteLine("End Excel")
    End Sub
    
  8. Натиснете F5, за да изпълните приложението.

  9. Отворете Windows на задачите. В Visual Studio показва прозореца Изход, за да видите съобщенията за отстраняване на грешки. Щракнете върху командния бутон. Обърнете внимание, че екземпляр на Excel.exe се показва в списъка Процеси.

  10. Екземплярът на Excel се изпълнява в списъка със задачи дори след като приложението завърши спи. Затворете диалоговия прозорец и обърнете внимание, че Excel вече не се показва в списъка Процеси.

  11. Когато изпълните стъпките в секцията "Разделителна способност", приложението Office излезе, след като освободи последната променлива. Заместете функцията в стъпка 5 с помощта на следния код:

      Private Sub NAR(ByVal o As Object)
        Try
          While (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0)
          End While
        Catch
        Finally
          o = Nothing
        End Try
      End Sub
    
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim oApp As New Excel.Application()
        Dim oBooks As Excel.Workbooks = oApp.Workbooks
        Dim oBook As Excel.Workbook = oBooks.Add
        Dim oSheet As Excel.Worksheet = oApp.ActiveSheet
    
        NAR(oSheet)
        oBook.Close(False)
        NAR(oBook)
        NAR(oBooks)
        oApp.Quit()
        NAR(oApp)
    
        Debug.WriteLine("Sleeping...")
        System.Threading.Thread.Sleep(5000)
        Debug.WriteLine("End Excel")
    End Sub
    

Ако използвате Visual C# .NET, прегледайте кода за функцията NAR():

private void NAR(object o)
{
    try 
    {
        while (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0) ;
    }
    catch {}
    finally 
    {
        o = null;
    }
}

Забележка: Започвайки от .NET Framework (платформа) 2.0, можете да използвате System.Runtime.InteropServices.Marshal.FinalReleaseComObject вместо при циклична извикване System.Runtime.interopServices.Marshal.ReleaseComObject, за да постигнете същия резултат.  

Отстраняване на неизправности

Забележка Ако следвате стъпките, описани в раздела "Стъпки за възпроизвеждане на поведението", а сървърът все още не се изключва, можете да използвате GC. Събира() метода и GC. Метод waitForPendingFinalizers(), след като освободите последния обект. Тъй като runtime извършва събирането на отпадъци в RCW, GC. Методът за събиране() принуждава събирателя на отпадъци да се изпълнява и може да освободи всички препратки, които все още има RCW. The GC. Методът Collect() се опитва да си възстановя максималната налична памет. Обърнете внимание, че това не гарантира, че цялата памет ще бъде възвратена.

Отнася се за

Тази статия се отнася и за:

  • Microsoft Visual Basic .NET (всички издания)

  • Microsoft Visual C# .NET (всички издания)

  • Microsoft Office 2016 г. (всички издания)

  • Microsoft Office 2013 (всички издания)

Нуждаете ли се от още помощ?

Искате ли още опции?

Разгледайте ползите от абонамента, прегледайте курсовете за обучение, научете как да защитите устройството си и още.

Общностите ви помагат да задавате и отговаряте на въпроси, да давате обратна връзка и да получавате информация от експерти с богати знания.