อาการ
เมื่อคุณอัตโนมัติแอปพลิเคชัน Microsoft Office จาก Microsoft Visual Basic .NET หรือ Microsoft Visual C# .NET แอปพลิเคชัน Office จะไม่ออกเมื่อคุณเรียกใช้เมธอด Quit
สาเหตุ
When Visual Studio .NET calls a COM object from managed code, it automatically creates a Runtime Callable Wrapper (RCW). MARShals RCW จะโทรระหว่างแอปพลิเคชัน .NET และวัตถุ COM RCW จะนับการอ้างอิงบนวัตถุ COM ดังนั้น ถ้าการอ้างอิงทั้งหมดยังไม่ได้เผยแพร่บน RCW วัตถุ COM จะไม่ออก
การแก้ไข
เมื่อต้องการตรวจสอบให้แน่ใจว่าแอปพลิเคชัน Officeออก ให้ระบุว่าโค้ดอัตโนมัติของคุณตรงตามเกณฑ์ต่อไปนี้หรือไม่:
-
ประกาศแต่ละวัตถุเป็นตัวแปรใหม่ ตัวอย่างเช่น เปลี่ยนบรรทัดของโค้ดต่อไปนี้:
oBook = oExcel.Workbooks.Add()
เปลี่ยนเป็นดังต่อไปนี้:
dim oBooks as Excel.Workbooks oBooks = oExcel.Workbooks oBook = oBooks.Add()
-
ใช้ System.Runtime.InteropServices.Marshal.ReleaseComObject ในการวนรอบจนกว่าจะส่งกลับค่า 0 เมื่อคุณเสร็จสิ้นการใช้วัตถุ System.Runtime.InteropServices.Marshal.ReleaseComObject จะนับการอ้างอิงของ RCW และการวนรอบจะทําให้แน่ใจว่าคอมโพเนนต์ COM ที่ขีดเส้นใต้จะถูกเผยแพร่โดยไม่เกี่ยวกับระยะเวลาที่ใส่ CLR อีกครั้ง
-
เมื่อต้องการปล่อยการอ้างอิงไปยังตัวแปร ให้ตั้งค่าตัวแปรเท่ากับ ไม่มี หรือ Null
-
ใช้เมธอด Quit ของวัตถุOfficeแอปพลิเคชันหลักเพื่อบอกให้เซิร์ฟเวอร์ปิดระบบ
สถานะ
พฤติกรรมเช่นนี้เกิดจากการออกแบบ
ข้อมูลเพิ่มเติม
ขั้นตอนในการสร้างลักษณะการเกิดขึ้น
-
เริ่ม Visual Studio .NET
-
บนเมนู ไฟล์ ให้คลิก ใหม่ แล้วคลิก Projectใหม่ ภายใต้ Visual Basicโครงการ Windows แอปพลิเคชันของคุณ แล้วคลิก ตกลงหมายเหตุ Form1 จะถูกสร้างขึ้นตามค่าเริ่มต้น
-
เพิ่มการอ้างอิงไปยังMicrosoft Excelวัตถุของคุณ เมื่อต้องการให้ปฏิบัติตามขั้นตอนเหล่านี้:
-
บนเมนู Project ให้คลิก เพิ่มการอ้างอิง
-
บนแท็บ COM ให้ค้นหาไลบรารีวัตถุExcelไลบรารีวัตถุ แล้วคลิก เลือกFor Microsoft Excel 2002: Microsoft Excel 10.0 Object LibraryNote ถ้าคุณยังไม่ได้เสร็จสิ้น, เราขอแนะให้ คุณดาวน์โหลด และติดตั้ง Microsoft Office XP Primary Interop Assemblies (PIAs)For more information about Office XP PIAs, go to the following Microsoft Knowledge Base article:
328912 Microsoft Officeประกอบหลัก (PIAs) ของ XP มีให้ดาวน์โหลด For Microsoft Office Excel 2003: Microsoft Excel 11.0 Object Library
-
คลิก ตกลง ในกล่องโต้ตอบ เพิ่มการอ้างอิง เพื่อยอมรับการเลือกของคุณ
-
-
บนเมนู มุมมอง ให้คลิก กล่องเครื่องมือ แล้วลากตัวควบคุม ปุ่ม ไปยัง Form1
-
ดับเบิลคลิก ปุ่ม1หมายเหตุ หน้าต่างโค้ดของฟอร์มจะปรากฏขึ้น
-
เพิ่มโค้ดต่อไปนี้ที่ด้านบนของ Form1.vb:
Imports Microsoft.Office.Interop
-
แทนที่โค้ดต่อไปนี้ในหน้าต่างโค้ด:
Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click 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 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 -
กด F5 เพื่อเรียกใช้แอปพลิเคชัน
-
เปิด Windowsจัดการงาน In Visual Studio, display the Output window to see the debug messages. คลิกปุ่มสั่ง โปรดสังเกตว่า อินสแตนซ์Excel.exeจะปรากฏในรายการ กระบวนการ
-
อินสแตนซ์ของExcelยังคงเรียกใช้ในรายการงานแม้ว่าหลังจากแอปพลิเคชันได้นอนเสร็จแล้ว ปิดกล่องโต้ตอบและExcelไม่ปรากฏขึ้นในรายการ กระบวนการ อีกต่อไป
-
เมื่อคุณปฏิบัติตามขั้นตอนในส่วน "การแก้ปัญหา" แอปพลิเคชัน Officeออกจากแอปพลิเคชันหลังจากเผยแพร่ตัวแปรสุดท้าย แทนที่ฟังก์ชันในขั้นตอนที่ 5 โดยใช้รหัสต่อไปนี้:
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
ถ้าคุณใช้ฟังก์ชัน Visual C# .NET ให้อ้างอิงโค้ดของฟังก์ชัน NAR()
private void NAR(object o)
{
try
{
while (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0) ;
}
catch {}
finally
{
o = null;
}
}
หมายเหตุ เริ่มต้นใน .NET Framework 2.0 คุณสามารถใช้ System.Runtime.InteropServices.Marshal.FinalReleaseComObject แทนการโทรวนรอบ System.Runtime.InteropServices.Marshal.ReleaseComObject เพื่อให้ได้ผลลัพธ์เดียวกัน
การแก้ไขปัญหา
หมายเหตุ ถ้าคุณปฏิบัติตามขั้นตอนที่อธิบายไว้ในส่วน "ขั้นตอนที่จะเกิดพฤติกรรม" และเซิร์ฟเวอร์ยังคงไม่ปิดตัว คุณสามารถใช้ GC วิธีการเก็บรวบรวม() และ GC เมธอด WaitForPendingFinalizers() หลังจากที่คุณปล่อยวัตถุสุดท้าย เนื่องจากรันไทม์จะเก็บถังขยะบน RCW ดังนั้น GC วิธีการรวบรวม() บังคับให้ถังขยะถูกทิ้งให้ใช้งานและอาจเผยแพร่การอ้างอิงใดๆ ที่ RCW ยังคงมีอยู่ GC วิธีเก็บรวบรวม() พยายามเรียกคืนหน่วยความจําสูงสุดที่พร้อมใช้งาน โปรดสังเกตว่าวิธีนี้ไม่ได้รับประกันว่าหน่วยความจําทั้งหมดจะถูกเรียกคืน
นำไปใช้กับ
บทความนี้ยังใช้ได้กับ:
-
Microsoft Visual Basic .NET (ทุกรุ่น)
-
Microsoft Visual C# .NET (ทุกรุ่น)
-
Microsoft Office 2016 (ทุกรุ่น)
-
Microsoft Office 2013 (ทุกรุ่น)