Office-programmet afsluttes ikke efter automatisering fra Visual Studio .NET-klienten

Gælder for
Visual Studio 2015

Se de andre produkter, som denne artikel gælder for.

Symptomer

Når du automatiserer et Microsoft Office-program fra Microsoft Visual Basic .NET eller Microsoft Visual C# .NET, afsluttes Office-programmet ikke, når du kalder metoden Afslut.

Årsag

Når Visual Studio .NET kalder et COM-objekt fra administreret kode, opretter det automatisk en Runtime Callable Wrapper (RCW). RCW overvåger kald mellem .NET-programmet og COM-objektet. RCW holder et referenceantal for COM-objektet. Så hvis alle referencer ikke er blevet frigivet på RCW, afsluttes COM-objektet ikke.

Løsning

For at sikre, at Office-programmet afsluttes, skal du afgøre, om din automatiseringskode opfylder følgende kriterier:

  • Definer hvert objekt som en ny variabel. Du kan f.eks. ændre følgende kodelinje:

    oBook = oExcel.Workbooks.Add()
    
    

    Skift dette til følgende:

    dim oBooks as Excel.Workbooks
    oBooks = oExcel.Workbooks
    oBook = oBooks.Add()
    
    
  • Brug System.Runtime.InteropServices.Marshal.ReleaseComObject i en løkke, indtil 0 returneres, når du er færdig med at bruge et objekt. System.Runtime.InteropServices.Marshal.ReleaseComObject reducerer referenceantallet for RCW'en, og løkken sikrer, at den underliggende COM-komponent frigives, uanset hvor mange gange den er genindsat i CLR.

  • Hvis du vil frigive referencen til variablen, skal du sætte variablen til lig med Nothing eller Null.

  • Brug metoden Afslut i Office-programobjektet til at bede serveren om at lukke ned.

Status

Denne funktionsmåde er tilsigtet.

Flere oplysninger

Trin til genskabelse af problemet

  1. Start Visual Studio .NET.

  2. Klik på Ny i menuen Filer, og klik derefter på Projekt. Vælg Windows-program under Visual Basic-projekter, og klik derefter på OK.

    Bemærk Formular1 oprettes som standard.

  3. Føj en reference til Microsoft Excel-objektbiblioteket. Det kan du gøre ved at udføre disse trin:

    1. Klik på Tilføj reference i menuen Projekter.

    2. Find objektbiblioteket til Excel under fanen COM, og klik derefter på Markér.

      Til Microsoft Excel 2002: Microsoft Excel 10.0-objektbibliotek

      Bemærk Hvis du ikke allerede har gjort det, anbefaler vi, at du henter og installerer Microsoft Office XP Primary Interop Assemblies (PIA'er).

      Du kan finde flere oplysninger om Office XP PIA'er i følgende artikel i Microsoft Knowledge Base:

      328912 Primære interop-samlinger (PIA'er) i Microsoft Office XP kan downloades
       Microsoft Office Excel 2003: Microsoft Excel 11.0-objektbibliotek

    3. Klik på OK i dialogboksen Tilføj referencer for at acceptere dine valg.

  4. Klik på Værktøjskasse i menuen Vis, og træk derefter en knap til Formular1.

  5. Dobbeltklik på knap1.

    Bemærk Kodevinduet for formularen vises.

  6. Føj følgende kode til toppen af Form1.vb:

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

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

    Erstat med 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. Tryk på F5 for at køre programmet.

  9. Åbn Windows Jobliste. I Visual Studio skal du vise vinduet Output for at få vist fejlfindingsmeddelelserne. Klik på kommandoknappen. Bemærk, at der vises en forekomst af Excel.exe på listen Processer.

  10. Excel-forekomsten kører stadig på opgavelisten, også efter programmet er færdigt med at slumre. Luk dialogboksen, og bemærk, at Excel ikke længere vises på listen over processer.

  11. Når du følger trinnene i afsnittet "Løsning", afsluttes Office-programmet, efter at den sidste variabel er udgivet. Erstat funktionen i trin 5 ved hjælp af 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 bruger Visual C# .NET, skal du referere til koden for funktionen NAR():


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

Bemærk: Fra og med .NET Framework 2.0 kan du bruge System.Runtime.InteropServices.Marshal.FinalReleaseComObject i stedet for while-løkken, der kalder System.Runtime.InteropServices.Marshal.ReleaseComObject for at opnå det samme resultat.
 

Fejlfinding

Bemærk Hvis du følger de trin, der er beskrevet i afsnittet "Trin til at genskabe funktionsmåden", og serveren stadig ikke lukker, kan du bruge GC. Collect()-metoden og GC. WaitForPendingFinalizers()-metoden, når du har sluppet det sidste objekt. Da runtime udfører affaldsindsamling på RCW, GC. Collect()-metoden tvinger garbage collector til at køre og kan frigive eventuelle referencer, som RCW'en stadig har. The GC. Collect()-metoden forsøger at frigøre den maksimale hukommelse, der er tilgængelig. Bemærk, at dette ikke garanterer, at al hukommelse vil blive frigjort.

Gælder for

Denne artikel gælder også for:

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