• 调用office COM出现不会退出的问题


    症状

    在使用.net调用 Microsoft Office 应用程序时,Office 应用程序在调用Quit方法时不会退出。

    原因

    Visual Studio.NET 从托管代码调用 COM 对象时,它会自动创建运行时可调用包装 (RCW)。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。
    • 若要解除对变量的引用,设置为空值空值的变量等。
    • 使用 Office 应用程序对象的Quit方法告诉服务器关闭。

    示例

    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
    
    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
    

     如果您使用的 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来代替 while 循环调用System.Runtime.InteropServices.Marshal.ReleaseComObject来实现相同的结果。

    故障排除

    请注意,如果您按照中所述的步骤"步骤重现行为"一节,并在服务器仍然没有关闭向下,您可以使用GC。Collect()方法和GC。WaitForPendingFinalizers()后释放的最后一个对象的方法。因为运行库对GC,RCW 执行垃圾回收。Collect()方法强制垃圾回收器在运行,并可能释放任何仍有 RCW 的引用。GC。Collect()方法尝试回收可用的最大内存。请注意,这不能保证所有内存都被都回收。

  • 相关阅读:
    layui动态修改select的选中项
    layui 鼠标悬停单元格显示全部
    使用LayUI操作数据表格
    layer.msg 弹出不同的效果的样式
    layer父页面刷新
    layui 获取radio单选框选中的值
    使用Dapper.Contrib
    微信公众号的文章爬取有三种方式
    centos的 各种安装包下载位置
    git pull一直弹出vim编辑器
  • 原文地址:https://www.cnblogs.com/ac1985482/p/3396684.html
Copyright © 2020-2023  润新知