如何从Excel 2007 VBA模块中调用System.Runtime.InteropServices.Marshal.ReleaseComObject [英] How can I call System.Runtime.InteropServices.Marshal.ReleaseComObject from within an Excel 2007 VBA module

查看:1186
本文介绍了如何从Excel 2007 VBA模块中调用System.Runtime.InteropServices.Marshal.ReleaseComObject的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在我的VBA代码中实例化的一些第三方COM对象上调用System.Runtime.InteropServices.Marshal.ReleaseComObject(obj),从我的工作簿关闭事件,如下:

I want to call System.Runtime.InteropServices.Marshal.ReleaseComObject(obj) on some 3rd party COM objects that I've instantiated in my VBA code, from my workbook close event, something like the following:

    Public Sub disconnect(obj As Variant)
        Dim refs As Long
        refs = 0

        If Not obj Is Nothing Then
            Do
                refs = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
            Loop While (refs > 0)
        End If
    End Sub

但是,我得到一个编译错误:invalid qualifier ,用上面的代码突出显示 System 。搜索似乎没有返回任何VBA代码从VBA宏调用System.Runtime方法 - 我只能找到VB.Net自动化Excel。我不确定是否可能。

However, I get a compile error: invalid qualifier with the System highlighted with the above code. Search doesn't seem to return any VBA code that calls System.Runtime methods from a VBA macro - I can only find VB.Net automating Excel. I'm not sure it's even possible.

我尝试解决此问题: Excel 2007 Zombie Process not COM automation but w / references to 3rd party com objects by确保这些第三方COM对象在Excel退出之前被正确处理。

I'm trying to resolve this issue: Excel 2007 Zombie Process not COM automation but w/ references to 3rd party com objects by ensuring these 3rd party COM objects are properly disposed of before Excel exits.

推荐答案

我无法使用推荐的VBA唯一方法解决僵尸问题,即使仔细检查和删除循环引用。

I was unable to resolve the zombie problem using the recommended VBA only method, even after careful checking for and removal of circular references.

其他搜索方法可以调用 ReleaseCom 方法使用包装的代码System.Runtime.InteropServices.Marshal .FinalReleaseComObject 创建可以从VBA调用的COM可见dll

Additional searching turned up a way to call the ReleaseCom method using code that wraps System.Runtime.InteropServices.Marshal.FinalReleaseComObject to create a COM visible dll that can be called from VBA

使用教程如何使用vs 2008创建一个com对象,并从vb6.0客户端使用它和一个新安装的VS2010 Express副本,我能够创建一个COM可见dll从VBA可调用。

Using the tutorial "how to create a com object using vs 2008 and consume it from vb6.0 client" and a newly installed copy of VS2010 Express, I was able to create a COM visible dll callable from VBA.

下面是稍微修改的包装器以及如何构建dll:

Here's the slightly modified wrapper and how to build the dll:

    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using System.EnterpriseServices;


    namespace ComDisposerLib
    {
        [ClassInterface(ClassInterfaceType.None)]
        [ComponentAccessControl(false)]
        public class ComDisposer : System.EnterpriseServices.ServicedComponent, IDisposable, ComDisposerLib.IComDispose
        {
            private List<Object> _comObjs;

            public ComDisposer()
            {
                _comObjs = new List<Object>();
            }

            ~ComDisposer()
            {
                Dispose(false);
            }

            public Object Add(Object o)
            {
                if (o != null && o.GetType().IsCOMObject)
                    _comObjs.Add(o);
                return o;
            }

            public void Clear()
            {
                Dispose(true);
            }

            protected override void Dispose(bool disposing)
            {
                if (disposing)
                {
                    for (int i = _comObjs.Count - 1; i >= 0; --i)
                        Marshal.FinalReleaseComObject(_comObjs[i]);
                    _comObjs.Clear();
                }
            }

            void IDisposable.Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
        }
    }

p>

and the interface:

    using System;

    namespace ComDisposerLib
    {
        public interface IComDispose
        {
            Object Add(Object o);
            void Clear();
            void Dispose();
        }
    }

要创建一个新的类库项目,对 System.Runtime.InteropServices System.EnterpriseServices 的引用,启用签署程序集 / properties / signing)并选择或创建密钥文件。添加类和接口代码文件。在AssemblyInfo.cs文件(位于属性下)中,使用System.Runtime.InteropServices添加

To build, create a new class library project, add references to System.Runtime.InteropServices and System.EnterpriseServices, enable 'Sign the assembly' (in the menu under project / properties / signing ) and select or create a key file. Add the class and interface code files. In the AssemblyInfo.cs file (located under properties) add

using System.Runtime.InteropServices;
using System.EnterpriseServices;

[assembly: ComVisible(true)]
[assembly: ApplicationName("ComDisposer")]
[assembly: ApplicationActivation(ActivationOption.Library)]

并构建。如果一切顺利,您可以如下注册您的dll:

and build. If all goes well, you can register you dll as follows:

regsvcs "C:\Documents and Settings\username\My Documents\Visual Studio 2010\Projects\ComDispose\ComDispose\obj\Release\ComDisposer.dll"

在VBA中,在添加对你的新COM库的引用之后,使用它如下:

In VBA, after adding a reference to your new COM library, use it as follows:

Sub disposeGlobalComObjects()
' global scope objects used only to simplify example 

    Dim cd As ComDisposer
    Set cd = New ComDisposer

    If Not SomeGlobalComObject Is Nothing Then
        cd.Add SomeGlobalComObject
        Set SomeGlobalComObject = Nothing
    End If
    If Not AnotherGlobalComObject Is Nothing Then
        cd.Add AnotherGlobalComObject
        Set AnotherGlobalComObject = Nothing
    End If
    cd.Dispose
End Sub

表示它正在工作,即Excel完全关闭,不再创建僵尸进程。

Early testing indicates that it's working, i.e. Excel closes cleanly and no longer creates zombie processes.

有趣的是,我只是遇到了从VBA使用您的dll的方法,无需先注册,如果您无法访问客户端计算机上的注册表,这将是非常有用的。

Interestingly, I just ran across this method for using your dll from VBA without having to register it first which could be useful if you didn't have access to the registry on your client machine.

这篇关于如何从Excel 2007 VBA模块中调用System.Runtime.InteropServices.Marshal.ReleaseComObject的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆