office的每个对象引用必须要显示释放,才能将所有内存释放,自动关闭office进程。
类似于下面的代码:
Chart.Title.Text=”test”;
Title对象是无法释放的,我们必须写成:
Chart chart=GetChartObj(Name);
Title title=Chart.Title;
Title.Text=”test”;
Marshal.FinalReleaseComObject(title);
Marshal.FinalReleaseComObject(chart);
也就是对每个对象的访问,必须经过ReleaseComObject()才可以关闭office进程。
下边的就解决这个问题。
/// <summary> /// Com封装对象,用于com对象的释放 /// </summary> /// <typeparam name="T"></typeparam> /// <author> /// tang jing bo /// </author> /// <remarks> /// tangj15 2011-11-4 /// </remarks> public class ComWrap<T> : Releasable where T : class { private T _needReleaseObj; private bool disposed; /// <summary> /// Initializes a new instance of the <see cref="ComWrap<T>"/> class. /// </summary> /// <param name="needReleaseObj">The need release obj.</param> public ComWrap(T needReleaseObj) { _needReleaseObj = needReleaseObj; } /// <summary> /// 获取Com对象引用 /// </summary> public T Target { get { return _needReleaseObj; } } /// <summary> /// Performs an explicit conversion from <see cref="T"/> to <see cref="System.ComWrap<T>"/>. /// </summary> /// <param name="comObject">The COM object.</param> /// <returns> /// The result of the conversion. /// </returns> public static explicit operator ComWrap<T>(T comObject) { return new ComWrap<T>(comObject); } /// <summary> /// Performs an implicit conversion from <see cref="System.ComWrap<T>"/> to <see cref="T"/>. /// </summary> /// <param name="wrap">The wrap.</param> /// <returns> /// The result of the conversion. /// </returns> public static implicit operator T(ComWrap<T> wrap) { return wrap.Target; } /// <summary> /// Wraps the specified COM object. /// </summary> /// <param name="comObject">The COM object.</param> /// <returns></returns> public static ComWrap<T> Wrap(T comObject) { return new ComWrap<T>(comObject); } /// <summary> /// Releases unmanaged and - optionally - managed resources /// </summary> /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { if (!disposed) { try { if (disposing) { } if (_needReleaseObj != null) { Marshal.FinalReleaseComObject(_needReleaseObj); _needReleaseObj = null; } disposed = true; } finally { // Call Dispose on your base class. base.Dispose(disposing); } } }
再写一个扩展类方便com对象的封装调用
/// <summary> /// Com释放扩展 /// </summary> /// <author> /// Tang Jing bo /// </author> /// <remarks> /// tangj15 2011-11-4 /// </remarks> public static class ComObjectDisposeExtension { /// <summary> /// 返回将Com组件包装后对象,需要显示的调用Dispose()方法 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="comObject">The COM object.</param> /// <returns></returns> public static ComWrap<T> Wrap<T>(this T comObject) where T : class { return new ComWrap<T>(comObject); } /// <summary> /// 返回将Com组件包装后对象,需要显示的调用Dispose()方法 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="comObject">The COM object.</param> /// <returns></returns> public static ComWrap<T> Wrap<T>(this object comObject) where T : class { return new ComWrap<T>((T)comObject); } /// <summary> /// 将Com组件包装后,执行action的代码,并且执行完后自动释放 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="comObject">The COM object.</param> /// <param name="action">The action.</param> public static void WrapRun<T>(this T comObject, Action<ComWrap<T>> action) where T : class { using (var o = new ComWrap<T>(comObject)) action(o); } /// <summary> /// 将Com组件包装后,执行action的代码,并且执行完后自动释放 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="comObject">The COM object.</param> /// <param name="action">The action.</param> public static void WrapRun<T>(this object comObject, Action<ComWrap<T>> action) where T : class { WrapRun((T)comObject, action); } /// <summary> /// 将Com组件包装后,执行并返回func的值,返回前自动释放com对象 /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="TRet">The type of the ret.</typeparam> /// <param name="comObject">The COM object.</param> /// <param name="func">The func.</param> /// <returns></returns> public static TRet WrapGet<T, TRet>(this T comObject, Func<ComWrap<T>, TRet> func) where T : class { using (var o = new ComWrap<T>(comObject)) return func(o); } /// <summary> /// 将Com组件包装后,执行并返回func的值,返回前自动释放com对象 /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="TRet">The type of the ret.</typeparam> /// <param name="comObject">The COM object.</param> /// <param name="func">The func.</param> /// <returns></returns> public static TRet WrapGet<T, TRet>(this object comObject, Func<ComWrap<T>, TRet> func) where T : class { return WrapGet((T)comObject,func); } }
我们可以这样调用:
using (ComWrap<Slides> slides = Presentation.Target.Slides.Wrap())
{
//….
}
也可以使用扩展方法:
Presentation.Target.Slides.WrapRun(slide=>{..do});