Office-programmet avsluttes ikke etter automatisering fra Visual Studio .NET-klienten

Gjelder for
Visual Studio 2015

Se de andre produktene denne artikkelen gjelder for.

Symptomer

Når du automatiserer et Microsoft Office-program fra Microsoft Visual Basic .NET eller Microsoft Visual C# .NET, avsluttes ikke Office-programmet når du kaller Avslutt-metoden.

Årsak

Når Visual Studio .NET kaller et COM-objekt fra administrert kode, oppretter det automatisk en Runtime Callable Wrapper (RCW). RCW sørger for kall mellom .NET-programmet og COM-objektet. RCW beholder et referanseantall for COM-objektet. Hvis ikke alle referanser er publisert på RCW, avsluttes derfor ikke COM-objektet.

Oppløsning

Finn ut om automatiseringskoden oppfyller følgende kriterier for å sikre at Office-programmet avsluttes:

  • Deklarer hvert objekt som en ny variabel. Du kan for eksempel endre følgende kodelinje:

    oBook = oExcel.Workbooks.Add()
    
    

    Endre dette til følgende:

    dim oBooks as Excel.Workbooks
    oBooks = oExcel.Workbooks
    oBook = oBooks.Add()
    
    
  • Bruk System.Runtime.InteropServices.Marshal.ReleaseComObject i en løkke til den returnerer 0 når du er ferdig med å bruke et objekt. System.Runtime.InteropServices.Marshal.ReleaseComObject reduserer referanseantallet for RCW, og løkken sørger for at den underliggende COM-komponenten frigis uavhengig av hvor mange ganger den har gått inn i CLR på nytt.

  • Hvis du vil frigi referansen til variabelen, setter du variabelen til Ingenting eller Null.

  • Bruk Avslutt-metoden til Office-programobjektet til å be serveren om å avslutte.

Status

Denne virkemåten er laget med hensikt.

Mer informasjon

Trinn for å reprodusere virkemåten

  1. Start Visual Studio .NET.

  2. Klikk Ny på Fil-menyen, og klikk deretter Prosjekt. Velg Windows-programmet under Visual Basic-prosjekter, og klikk deretter OK.

    Vær oppmerksom på Skjema1 opprettes som standard.

  3. Legge til en referanse til objektbiblioteket i Microsoft Excel. Gjør dette ved å følge disse trinnene:

    1. Klikk Legg til referanse på Prosjekt-menyen.

    2. Finn objektbiblioteket for Excel på COM-fanen, og klikk deretter Velg.

      For Microsoft Excel 2002: Microsoft Excel 10.0-objektbibliotek

      Vær oppmerksom på Hvis du ikke allerede har gjort dette, anbefaler vi at du laster ned og installerer Microsoft Office XP Primary Interop Assemblies (PIAs).

      Hvis du vil ha mer informasjon om Office XP PIA-er, kan du gå til følgende artikkel i Microsoft Knowledge Base:

      328912 Microsoft Office XP Primary Interop Assemblies (PIAs) er tilgjengelig for nedlasting
       For Microsoft Office Excel 2003: Microsoft Excel 11.0-objektbibliotek

    3. Klikk OK i dialogboksen Legg til referanser for å godta valgene dine.

  4. Klikk Verktøykasse på Visning-menyen, og dra deretter en knappekontroll til Skjema1.

  5. Dobbeltklikk på Knapp1.

    Vær oppmerksom på Kodevinduet for skjemaet vises.

  6. Legg til følgende kode øverst i Form1.vb:

    Imports Microsoft.Office.Interop
    
    
  7. Erstatt følgende kode i kodevinduet:

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

    Erstatt følgende kode:

    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. Trykk på F5 for å kjøre programmet.

  9. Åpne Windows Oppgavebehandling. Vis Utdata-vinduet i Visual Studio for å se feilsøkingsmeldingene. Klikk på kommandoknappen. Legg merke til at en forekomst av Excel.exe vises i listen over prosesser.

  10. Excel-forekomsten kjører fortsatt i oppgavelisten selv etter at programmet er ferdig med hvilemodus. Lukk dialogboksen, og legg merke til at Excel ikke lenger vises i listen over prosesser.

  11. Når du følger trinnene i delen «Løsning», avsluttes Office-programmet etter at den siste variabelen har blitt utgitt. Erstatt funksjonen i trinn 5 ved å bruke følgende kode:

      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
    
    

Hvis du bruker Visual C# .NET, refererer du til koden for NAR()-funksjonen:


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

Fra og med .NET Framework 2.0 kan du bruke System.Runtime.InteropServices.Marshal.FinalReleaseComObject i stedet for while-løkken som kaller System.Runtime.InteropServices.Marshal.ReleaseComObject for å oppnå samme resultat.
 

Feilsøking

Vær oppmerksom på Hvis du følger trinnene som er beskrevet i delen «Trinn for å reprodusere virkemåten», og serveren fortsatt ikke avsluttes, kan du bruke GC. Collect()-metode og GC. WaitForPendingFinalizers()-metoden etter at du har frigitt det siste objektet. Fordi kjøretiden utfører søppelinnsamling på RCW, GC. Collect()-metoden tvinger garbage collector til å kjøre og kan frigi eventuelle referanser som RCW fortsatt har. Forbundsbanken. Collect()-metoden prøver å frigjøre maksimalt minne som er tilgjengelig. Vær oppmerksom på at dette ikke garanterer at alt minne blir gjenvunnet.

Gjelder

Denne artikkelen gjelder også for:

  • Microsoft Visual Basic .NET (alle utgaver)
  • Microsoft Visual C# .NET (alle utgaver)
  • Microsoft Office 2016 (alle utgaver)
  • Microsoft Office 2013 (alle utgaver)