Triệu chứng
Khi bạn tự động hóa một ứng Microsoft Office từ Microsoft Visual Basic .NET hoặc Microsoft Visual C# .NET, ứng dụng Office sẽ không thoát khi bạn gọi phương pháp Thoát.
Nguyên nhân
Khi Visual Studio .NET gọi đối tượng COM từ mã được quản lý, nó sẽ tự động tạo ra Một Runtime Callable Wrapper (RCW). Tên RCW gọi giữa ứng dụng .NET và đối tượng COM. RCW giữ số tham chiếu trên đối tượng COM. Do đó, nếu tất cả tham chiếu chưa được phát hành trên RCW, đối tượng COM sẽ không thoát.
Giải pháp
Để đảm bảo rằng ứng dụng Office thoát, hãy xác định xem mã tự động hóa của bạn có đáp ứng các tiêu chí sau đây hay không:
-
Khai báo mỗi đối tượng là một biến số mới. Ví dụ, thay đổi dòng mã sau đây:
oBook = oExcel.Workbooks.Add()
Thay đổi điều này thành như sau:
dim oBooks as Excel.Workbooks oBooks = oExcel.Workbooks oBook = oBooks.Add()
-
Sử dụng System.Runtime.InteropServices.Marshal.ReleaseComObject trong vòng lặp cho đến khi trả về 0 khi bạn sử dụng xong đối tượng. System.Runtime.InteropServices.Marshal.ReleaseComObject decrements số lượng tham chiếu của RCW và vòng lặp đảm bảo rằng cấu phần COM cơ sở được phát hành bất kể đã nhập lại bao nhiêu lần CLR.
-
Để phát hành tham chiếu đến biến số, hãy đặt biến số bằng Không có gì hoặc Null.
-
Sử dụng phương pháp Thoát của đối Office application để yêu cầu máy chủ tắt máy chủ.
Trạng thái
Hành vi này là có chủ động.
Thông tin Bổ sung
Các bước để tái tạo hành vi
-
Bắt Visual Studio .NET.
-
Trên menu Tệp, bấm vào Mới, rồi bấm vào Tệp Project. Dưới Visual Basic dự án, chọn Windows Dụng, rồi bấm OK.
Lưu ý Form1 được tạo theo mặc định. -
Thêm tham chiếu vào Thư viện Microsoft Excel tượng của bạn. Để thực hiện điều này, hãy làm theo các bước sau:
-
Trên menu Project, bấm Thêm Tham chiếu.
-
Trên tab COM, hãy định vị Thư viện Đối tượng Excel thư viện, rồi bấm Chọn.
Ví dụ Microsoft Excel 2002: Thư viện Đối tượng Microsoft Excel 10.0
Nếu bạn chưa thực hiện việc này, chúng tôi khuyên bạn nên tải xuống và cài đặt Tập hợp Liên hợp Chính (PIAs) Microsoft Office XP Chính.
Để biết thêm thông tin về Office XP, hãy đi đến bài viết sau trong Cơ sở Tri thức Microsoft:328912 Microsoft Office hợp liên hợp chính (PIAs) XP chính sẵn có để tải xuống
Ví Microsoft Office Excel 2003: Thư viện Microsoft Excel 11.0 -
Bấm OK trong hộp thoại Thêm Tham chiếu để chấp nhận lựa chọn của bạn.
-
-
Trên menu Dạng xem, bấm vào Hộp công cụ, rồi kéo điều khiển Nút vào Form1.
-
Bấm đúp vào Nút1.
Lưu ý Cửa sổ mã của biểu mẫu xuất hiện. -
Thêm mã sau đây vào đầu Form1.vb:
Imports Microsoft.Office.Interop
-
Thay thế mã sau đây trong cửa sổ mã:
Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click End Sub
Thay thế mã sau:
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
-
Nhấn F5 để chạy ứng dụng.
-
Mở Trình Windows tác vụ. Trong Visual Studio, hiển thị cửa sổ Đầu ra để xem thông báo gỡ lỗi. Bấm vào nút lệnh. Lưu ý rằng một phiên bản của Excel.exe xuất hiện trong danh sách Quy trình.
-
Phiên bản của Excel vẫn chạy trong danh sách tác vụ ngay cả khi ứng dụng đã ngủ xong. Đóng hộp thoại và lưu ý rằng Excel sẽ không còn xuất hiện trong danh sách Quy trình.
-
Khi bạn thực hiện các bước trong mục "Độ phân giải", ứng dụng Office thoát sau khi ứng dụng phát hành biến cuối cùng. Thay thế hàm trong Bước 5 bằng cách sử dụng mã sau đây:
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
Nếu bạn đang sử dụng Visual C# .NET, hãy tham khảo mã cho hàm NAR():
private void NAR(object o)
{
try
{
while (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0) ;
}
catch {}
finally
{
o = null;
}
}
Lưu ý Bắt đầu từ .NET Framework 2.0, bạn có thể sử dụng System.Runtime.InteropServices.Marsobices.FinalReleaseComObject thay vì trong lúc gọi theo vòng lặp System.Runtime.InteropServices.Marshal.ReleaseComObject để đạt được kết quả tương tự.
Gỡ rối
Chú ý Nếu bạn làm theo các bước được mô tả trong phần "Các bước để Tái tạo Hành vi" và máy chủ vẫn không tắt, bạn có thể sử dụng GC. Collect() và GC. Phương pháp WaitForPendingFinalizers() sau khi bạn thả đối tượng cuối cùng. Vì thời gian chạy thực hiện thu thập rác trên RCW, nên GC. Phương pháp Collect() buộc bộ thu thập rác chạy và có thể giải phóng bất kỳ tham chiếu nào mà RCW vẫn có. The GC. Collect() method tries to reclaim the maximum memory that is available. Lưu ý rằng điều này không đảm bảo rằng tất cả bộ nhớ sẽ được thu hồi.
Áp dụng cho
Bài viết này cũng áp dụng cho:
-
Microsoft Visual Basic .NET (tất cả các phiên bản)
-
Microsoft Visual C# .NET (tất cả phiên bản)
-
Microsoft Office 2016 (tất cả phiên bản)
-
Microsoft Office 2013 (tất cả phiên bản)