Aplikasi Office tidak keluar setelah otomatisasi dari klien .NET Visual Studio

Berlaku Untuk
Visual Studio 2015

Lihat produk lain yang berlaku untuk artikel ini.

Gejala

Saat Anda mengotomatisasi aplikasi Microsoft Office dari Microsoft Visual Basic .NET atau Microsoft Visual C# .NET, aplikasi Office tidak keluar saat Anda memanggil metode Keluar.

Penyebab

Ketika Visual Studio .NET memanggil objek COM dari kode terkelola, secara otomatis membuat Runtime Callable Wrapper (RCW). RCW marshals panggilan antara aplikasi .NET dan objek COM. RCW menyimpan hitungan referensi pada objek COM. Oleh karena itu, jika semua referensi belum dirilis di RCW, objek COM tidak berhenti.

Resolusi

Untuk memastikan bahwa aplikasi Office keluar, tentukan apakah kode otomatisasi Anda memenuhi kriteria berikut:

  • Mendeklarasikan setiap objek sebagai variabel baru. Misalnya, ubah baris kode berikut ini:

    oBook = oExcel.Workbooks.Add()
    
    

    Ubah ini ke hal berikut ini:

    dim oBooks as Excel.Workbooks
    oBooks = oExcel.Workbooks
    oBook = oBooks.Add()
    
    
  • Gunakan System.Runtime.InteropServices.Marshal.ReleaseComObject dalam pengulangan hingga mengembalikan 0 setelah selesai menggunakan objek. System.Runtime.InteropServices.Marshal.ReleaseComObject menentukan hitungan referensi RCW, dan pengulangan memastikan bahwa komponen COM yang mendasarinya dirilis terlepas dari berapa kali komponen tersebut telah masuk kembali ke CLR.

  • Untuk melepaskan referensi ke variabel, atur variabel sama dengan Tidak Ada atau Null.

  • Gunakan metode Keluar dari objek aplikasi Office untuk memberi tahu server untuk mematikan.

Status

Perilaku ini memang direncanakan.

Informasi Selengkapnya

Langkah-langkah untuk mereprodusi perilaku

  1. Mulai Visual Studio .NET.

  2. Pada menu File, klik Baru, lalu klik Proyek. Di bawah Proyek Visual Basic, pilih Aplikasi Windows, lalu klik OK.

    Catatan Formulir1 dibuat secara default.

  3. Tambahkan referensi ke Pustaka Objek Microsoft Excel. Untuk melakukannya, ikuti langkah-langkah berikut:

    1. Pada menu Proyek, klik Tambahkan Referensi.

    2. Pada tab COM, temukan Pustaka Objek untuk Excel, lalu klik Pilih.

      Untuk Microsoft Excel 2002: Pustaka Objek Microsoft Excel 10.0

      Catatan Jika Anda belum melakukan ini, kami menyarankan agar Anda mengunduh dan menginstal Microsoft Office XP Primary Interop Assemblies (PIAS).

      Untuk informasi selengkapnya tentang Office XP PIAS, masuk ke artikel Pangkalan Pengetahuan Microsoft berikut ini:

      328912 Microsoft Office XP primary interop assemblies (PIAS) tersedia untuk diunduh
       Untuk Microsoft Office Excel 2003: Pustaka Objek Microsoft Excel 11.0

    3. Klik OK dalam kotak dialog Tambahkan Referensi untuk menerima pilihan Anda.

  4. Pada menu Tampilan, klik Kotak Alat, lalu seret kontrol Tombol ke Formulir1.

  5. Klik ganda Tombol1.

    Catatan Jendela kode untuk formulir akan muncul.

  6. Tambahkan kode berikut ke bagian atas Form1.vb:

    Imports Microsoft.Office.Interop
    
    
  7. Ganti kode berikut di jendela kode:

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

    Ganti kode berikut:

    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. Tekan F5 untuk menjalankan aplikasi.

  9. Buka Manajer Tugas Windows. Di Visual Studio, tampilkan jendela Output untuk melihat pesan debug. Klik tombol perintah. Perhatikan bahwa contoh Excel.exe muncul dalam daftar Proses.

  10. Contoh Excel masih berjalan dalam daftar tugas bahkan setelah aplikasi selesai tidur. Tutup kotak dialog dan perhatikan bahwa Excel tidak lagi muncul dalam daftar Proses.

  11. Saat Anda melakukan langkah-langkah di bagian "Resolusi", aplikasi Office keluar setelah merilis variabel terakhir. Ganti fungsi di Langkah 5 dengan menggunakan kode berikut:

      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
    
    

Jika Anda menggunakan Visual C# .NET, referensikan kode untuk fungsi NAR():


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

Catatan Dimulai dari .NET Framework 2.0, Anda dapat menggunakan System.Runtime.InteropServices.Marshal.FinalReleaseComObject, bukan mengulang panggilan System.Runtime.InteropServices.Marshal.ReleaseComObject untuk mendapatkan hasil yang sama.
 

Pemecahan masalah

Catatan Jika Anda mengikuti langkah-langkah yang dijelaskan di bagian "Langkah-langkah untuk Mereproduksi Perilaku", dan server masih tidak dimatikan, Anda bisa menggunakan GC. Metode Collect() dan GC. Metode WaitForPendingFinalizers() setelah Anda melepaskan objek terakhir. Karena runtime melakukan pengumpulan sampah di RCW, GC. Metode Collect() memaksa kolektor sampah untuk berjalan dan mungkin merilis referensi apa pun yang masih dimiliki RCW. The GC. Metode Collect() mencoba mengambil kembali memori maksimum yang tersedia. Perhatikan bahwa ini tidak menjamin bahwa semua memori akan diklaim kembali.

Berlaku untuk

Artikel ini juga berlaku untuk:

  • Microsoft Visual Basic .NET (semua edisi)
  • Microsoft Visual C# .NET (semua edisi)
  • Microsoft Office 2016 (semua edisi)
  • Microsoft Office 2013 (semua edisi)