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 Quit-metoden.
Årsak
Når Visual Studio .NET kaller et COM-objekt fra forvaltet kode, opprettes det automatisk et Runtime Callable Wrapper (RCW). RCW-formidlingene kaller mellom .NET-programmet og COM-objektet. RCW beholder et referanseantall på COM-objektet. Hvis alle referanser ikke er utgitt på RCW, avsluttes derfor ikke COM-objektet.
Løsning
For å sikre at Office avsluttes, må du avgjøre om automatiseringskoden oppfyller følgende kriterier:
-
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 avkryser referanseantallet for RCW, og løkken sørger for at den underliggende COM-komponenten utgis uavhengig av hvor mange ganger den har angitt CLR på nytt.
-
Hvis du vil frigi referansen til variabelen, angir du variabelen lik Ingenting eller Null.
-
Bruk Quit-metoden for Office-programobjektet til å be serveren om å avslutte.
Status
Denne virkemåten er som standard.
Mer informasjon
Fremgangsmåte for å reprodusere virkemåten
-
Start Visual Studio .NET.
-
Klikk Ny på Fil-menyen, og klikk deretter Project. Under Visual Basic prosjekter velger du Windows Program, og deretter klikker du OK.
Obs! Skjema1 opprettes som standard. -
Legg til en referanse i Microsoft Excel objektbiblioteket. Gjør dette ved å følge disse trinnene:
-
Klikk Legg Project referanse på menyen.
-
Finn objektbiblioteket for Excel på COM-fanen, og klikk deretter Velg.
For Microsoft Excel 2002: Microsoft Excel 10.0 Object LibraryNote Hvis du ikke allerede har gjort dette, anbefaler vi at du laster ned og installerer Microsoft Office XP Primary Interop Assemblies (PIAer). Hvis du vil ha mer informasjon om Office XP-PIAer, kan du gå til følgende Microsoft Knowledge Base-artikkel:328912 Microsoft Office XP primære interop-samlinger (PIAer) er tilgjengelige for nedlasting For Microsoft Office Excel 2003: Microsoft Excel 11.0 Object Library
-
Klikk OK i dialogboksen Legg til referanser for å godta valgene.
-
-
Klikk Verktøykasse på Vis-menyen, og dra deretter en knappekontroll til Skjema1.
-
Dobbeltklikk på Knapp1.
Obs! Kodevinduet for skjemaet vises. -
Legg til følgende kode øverst i Form1.vb:
Imports Microsoft.Office.Interop
-
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
-
Trykk F5 for å kjøre programmet.
-
Åpne Windows Oppgavebehandling. I Visual Studio viser du Utdata-vinduet for å se feilsøkingsmeldingene. Klikk kommandoknappen. Legg merke til at en Excel.exe vises i Prosesser-listen.
-
Forekomsten av Excel kjører fortsatt i oppgavelisten selv etter at programmet er ferdig i hvilemodus. Lukk dialogboksen, og legg merke til Excel ikke lenger vises i Prosesser-listen.
-
Når du gjør trinnene i «Løsning»-delen, avsluttes Office programmet etter at den slipper den siste variabelen. Erstatt funksjonen i trinn 5 ved hjelp av 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;
}
}
Obs! Fra og med .NET Framework 2.0 kan du bruke System.Runtime.InteropServices.Marshal.FinalReleaseComObject i stedet for mens loopen ringer System.Runtime.InteropServices.Marshal.ReleaseComObject for å oppnå samme resultat.
Feilsøking
Obs! Hvis du følger trinnene som er beskrevet i delen Fremgangsmåte for å reprodusere virkemåten, og serveren fremdeles ikke avsluttes, kan du bruke GC. Collect()-metoden og GC. WaitForPendingFinalizers()-metoden etter at du har frigjort det siste objektet. Fordi kjøretiden utfører søppelsamlingen på RCW, GC. Collect()-metoden tvinger søppelsamleren til å kjøre og kan frigi eventuelle referanser som RCW fremdeles har. The GC. Collect()-metoden prøver å hente tilbake det maksimale minnet som er tilgjengelig. Legg merke til at dette ikke garanterer at alt minne blir gjenvunnet.
Gjelder
Denne artikkelen gjelder også for:
-
Microsoft Visual Basic .NET (alle versjoner)
-
Microsoft Visual C# .NET (alle versjoner)
-
Microsoft Office 2016 (alle versjoner)
-
Microsoft Office 2013 (alle versjoner)