อาการ
เมื่อคุณอัตโนมัติแอปพลิเคชัน 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 (ทุกรุ่น)