标签: com-interop

使用IDisposable清理Excel Interop对象

在我的公司中,发布Excel Interop Objects的常用方法是使用IDisposable,方法如下:

Public Sub Dispose() Implements IDisposable.Dispose
    If Not bolDisposed Then
        Finalize()
        System.GC.SuppressFinalize(Me)
    End If
End Sub

Protected Overrides Sub Finalize()
    _xlApp = Nothing
    bolDisposed = True
    MyBase.Finalize()
End Sub
Run Code Online (Sandbox Code Playgroud)

IDisposable构造函数中以下列方式创建的位置:

Try
    _xlApp = CType(GetObject(, "Excel.Application"), Excel.Application)
Catch e As Exception
    _xlApp = CType(CreateObject("Excel.Application"), Excel.Application) 
End Try
Run Code Online (Sandbox Code Playgroud)

并且客户端使用_xlApp执行有关excel互操作对象的代码.

我们完全避免使用双点规则.现在我开始研究如何重新发布(Excel)互操作对象以及我发现的几乎所有关于它的讨论如何正确清理excel互操作对象释放Excel对象主要使用Marshal.ReleaseComObject(),它们都没有使用IDisposable接口.

我的问题是:使用IDisposable Interace释放excel互操作对象有什么缺点吗?如果是这样,这些不利因素是什么.

.net vb.net excel interop com-interop

25
推荐指数
1
解决办法
7778
查看次数

无法将'microsoft.Office.Interop.Excel.ApplicationClass'类型的COM对象强制转换为'microsoft.Office.Interop.Excel.Application'"

这是我第一次尝试从一个C#控制台应用程序中的excel中捕获一些数据.

我收到错误"无法将类型为'microsoft.Office.Interop.Excel.ApplicationClass'的COM对象转换为'microsoft.Office.Interop.Excel.Application'".

此代码使用"Microsoft Excel 12.0对象库",我提供了对Microsoft.Office.Interop.Excel的引用.

不过,我无法克服这个错误 - 我相信它有自己的快速解决方案.

我挖了一点这个网站并遇到了这个解决方案: Interop类型无法嵌入

但是,我无法理解所以无法实现建议的解决方案.

我的.Net版本是4.5.

很感谢任何形式的帮助.

提前致谢.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;

using Excel = Microsoft.Office.Interop.Excel;

namespace deneme
{
class Program
{
    static void Main(string[] args)
    {

        Excel.Application xlApp = new Excel.Application();
        xlApp.Visible = true; // <-- excel application
        xlApp.DisplayAlerts = false;

        // Open the workbook.
        Excel.Workbook wBook = xlApp.Workbooks.Open("C:\\FNN\\XLA\\fnnComTemplate.xlsx",
            Type.Missing, Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, Type.Missing); …
Run Code Online (Sandbox Code Playgroud)

c# excel com-interop

20
推荐指数
3
解决办法
6万
查看次数

通过COM4J从.NET方法返回接口数组

如何通过COM4J从C#方法返回一个对象数组(实现COM接口)到Java方法?

示例C#生成数组的类:

using System;
using System.Runtime.InteropServices;

namespace Example
{

    [ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IAnimal
    {
        string Speak();
    }

    [ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IFarm
    {
        [return:MarshalAs(UnmanagedType.SafeArray,
        SafeArraySubType=VarEnum.VT_UNKNOWN)]
        IAnimal[] GetAnimals();
    }

    [ComVisible(true), ClassInterface(ClassInterfaceType.None)]
    public class Farm : IFarm
    {
        public IAnimal[] GetAnimals()
        {
            return new IAnimal[] { new Cow(), new Pig() };
        }
    }

    internal class Cow: IAnimal
    {
        public string Speak()
        {
            return "Moo";
        }
    }

    internal class Pig: IAnimal
    {
        public string Speak()
        {
            return "Oink";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

生成的.tlb中的接口声明如下所示: …

c# java com com-interop com4j

19
推荐指数
1
解决办法
1364
查看次数

COM Interop没有regasm

我是一个有限的用户,我需要编写一个Outlook宏来展示Outlook 2003和2007中的C#库.

我根本没有任何管理员权限,即使在安装时也没有,所以我无法运行RegAsm,我不能(我假设)编写一个托管加载项.

在这种情况下,有没有办法从VBA调用.Net代码,还是有其他解决方案?

这仅供个人使用,所以丑陋的黑客是完全可以接受的(只要它有效)

.net outlook vba com-interop limited-user

18
推荐指数
3
解决办法
8302
查看次数

如何通过COM互操作在.NET对象上调用静态方法?

是否可以通过COM互操作在.NET对象上调用静态方法?

我知道我可以写一个包装类.如果我不想那样做怎么办?

.net com interop com-interop

18
推荐指数
1
解决办法
2086
查看次数

是否可以拦截(或意识到)COM引用计数暴露给COM的CLR对象

我已经改写了这个问题.

当.net对象通过COM iterop公开给COM客户端时,会创建一个CCW(COM Callable Wrapper),它位于COM客户端和Managed .net对象之间.

在COM世界中,对象保留其他对象对其的引用数量的计数.当引用计数变为零时,将删除/释放/收集对象.这意味着COM对象终止是确定性的(我们在.net中使用Using/IDispose用于确定性终止,对象终结器是非确定性的).

每个CCW都是一个COM对象,它的引用计数与任何其他COM对象一样.当CCW死亡(引用计数变为零)时,GC将无法找到CCW包装的CLR对象,并且CLR对象有资格进行收集.快乐的日子,一切都与世隔绝.

我想要做的是在CCW死时(即当它的引用计数变为零时)捕获,并以某种方式将此信号通知给CLR对象(例如,通过在被管理对象上调用Dispose方法).

那么,是否可以知道CLR类的COM可调用包装器的引用计数何时变为零?
和/或
是否可以在.net中为CCW提供AddRef和ReleaseRef的实现?

如果不是替代方法是在ATL中实现这些DLL(我不需要任何ATL帮助,谢谢).它不是火箭科学,但我不愿意这样做,因为我是内部唯一的开发人员,任何现实世界的C++或任何ATL.

背景
我在.net中重写了一些旧的VB6 ActiveX DLL(确切地说是C#,但这更像是.net/COM互操作问题,而不是C#问题).一些旧的VB6对象依赖于引用计数来在对象终止时执行操作(参见上面引用计数的解释).这些DLL不包含重要的业务逻辑,它们是我们为使用VBScript与我们集成的客户提供的实用程序和帮助程序函数.

我不想做什么

  • 引用计数.net对象而不是使用垃圾收集器.我对GC很满意,我的问题不在于GC.
  • 使用对象终结器.终结器是非确定性的,在这种情况下我需要确定性终止(如.net中的Using/IDispose惯用法)
  • 在非托管C++中实现IUnknown
    如果我要使用C++路由,我将使用ATL,谢谢.
  • 使用Vb6解决此问题,或重新使用VB6对象.本练习的重点是消除我们对Vb6的构建依赖.

谢谢
BW

接受的答案
分毫不差一千感谢史蒂夫·施泰纳,谁,唯一的(可能是可行的)想出了基于.NET的答案,埃里克,谁用一个非常简单的解决方案ATL上来.

然而,接受的答案是Bigtoe,他建议将.net对象包装在VbScript对象中(我认为不诚实),有效地为VbScript问题提供了一个简单的VbScript解决方案.

谢谢大家.

.net c# reference-counting com-interop

17
推荐指数
2
解决办法
5130
查看次数

以编程方式注册C#/ VB.NET COM DLL

问题:我有一个.NET dll,我在C++程序中使用它.现在我必须在部署计算机上以编程方式注册dll.

我该怎么做(以编程方式!不使用regasm)?我记得,当我曾经用C++ dll调用VB6 dll时,我不得不使用DllRegisterServer和DllUnregisterServer.

使用.NET dll还是这样吗?
看来我必须以某种方式将dllregisterserver函数添加到.NET dll中.

c# vb.net com dll com-interop

17
推荐指数
1
解决办法
1万
查看次数

由非托管应用程序托管的托管组件中的Await和SynchronizationContext

[EDITED] 这似乎是 Framework的Application.DoEvents实现中的一个错误,我在这里报告.在UI线程上恢复错误的同步上下文可能会严重影响像我这样的组件开发人员.赏金的目标是更多地关注这个问题,并奖励@MattSmith,他的答案帮助追踪它.

我负责通过COM互操作UserControl将基于.NET WinForms 的组件作为ActiveX暴露给传统的非托管应用程序.运行时要求是.NET 4.0 + Microsoft.Bcl.Async.

该组件被实例化并在应用程序的主要STA UI线程上使用.它的实现使用async/await,因此它期望在当前线程(即,WindowsFormsSynchronizationContext)上安装序列化同步上下文的实例.

通常,WindowsFormsSynchronizationContext设置为Application.Run,托管应用程序的消息循环运行的位置.当然,这不是非托管主机应用程序的情况,我无法控制它.当然,主机应用程序仍然有自己的经典Windows消息循环,因此序列化await延续回调应该不是问题.

但是,到目前为止我提出的解决方案都不是完美的,甚至都不能正常工作.这是一个人为的例子,其中Test方法由主机app调用:

Task testTask;

public void Test()
{
    this.testTask = TestAsync();
}

async Task TestAsync()
{
    Debug.Print("thread before await: {0}", Thread.CurrentThread.ManagedThreadId);

    var ctx1 = SynchronizationContext.Current;
    Debug.Print("ctx1: {0}", ctx1 != null? ctx1.GetType().Name: null);

    if (!(ctx1 is WindowsFormsSynchronizationContext))
        SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());

    var ctx2 = SynchronizationContext.Current;
    Debug.Print("ctx2: …
Run Code Online (Sandbox Code Playgroud)

.net c# asynchronous com-interop async-await

17
推荐指数
2
解决办法
2291
查看次数

如何在本机.NET类中包装COM对象?

我在.NET(C#)中使用了广泛的现有COM API(可能是Outlook,但它不是).我通过在Visual Studio中添加"COM引用"来完成此操作,因此所有"魔法"都是在幕后完成的(即,我不必手动运行tlbimp).

虽然现在可以从.NET"轻松"使用COM API,但它不是非常友好的.NET.例如,没有泛型,事件很奇怪,奇怪,如IPicture等.所以,我想创建一个使用现有COM API实现的本机.NET API.

一个简单的第一次传球可能是

namespace Company.Product {
   class ComObject {
       public readonly global::Product.ComObject Handle; // the "native" COM object
       public ComObject(global::Product.ComObject handle) {
          if (handle == null) throw new ArgumentNullException("handle");
          Handle = handle;
       }

       // EDIT: suggestions from nobugz
       public override int GetHashCode() {
          return Handle.GetHashCode();
       }
       public override bool Equals(object obj) {
          return Handle.Equals(obj);
       }
   }
}
Run Code Online (Sandbox Code Playgroud)

这种方法的一个直接问题是,您可以轻松地为同一个底层"本机COM"对象结束多个ComObject实例.例如,在进行枚举时:

IEnumerable<Company.Product.Item> Items {
   get {
      foreach (global::Item item in Handle.Items)
         yield …
Run Code Online (Sandbox Code Playgroud)

.net c# com interop com-interop

16
推荐指数
2
解决办法
3125
查看次数

在C#中的类上面出现的Guid属性是什么?

我最近选择了一些C#代码,其中一个类上面有一个Guid属性.我不明白这是什么或它用于什么.

有人可以给我一个简要的概述,或者只是指向一些提供更多信息的文章的方向?

谢谢!

c# com-interop

16
推荐指数
3
解决办法
8760
查看次数