标签: com-interop

COM互操作是否尊重.NET AppDomain边界以进行程序集加载?

这是核心问题:我有一个在单独的AppDomain中使用COM互操作的.NET应用程序.COM的东西似乎是将程序集加载回默认域,而不是从中调用COM内容的AppDomain.

我想知道的是:这是预期的行为,还是我做错了导致这些COM相关程序集被加载到错误的AppDomain中?请参阅以下情况的更详细说明......

该应用程序由3个程序集组成: - 主EXE,应用程序的入口点. - common.dll,只包含一个接口IController(采用IPlugin风格) - controller.dll,包含一个实现IController和MarshalByRefObject的Controller类.此类完成所有工作并使用COM interop与另一个应用程序进行交互.

主要EXE的相关部分如下所示:

AppDomain controller_domain = AppDomain.CreateDomain("Controller Domain");
IController c = (IController)controller_domain.CreateInstanceFromAndUnwrap("controller.dll", "MyNamespace.Controller");
result = c.Run();
AppDomain.Unload(controller_domain);
Run Code Online (Sandbox Code Playgroud)

common.dll只包含以下两件事:

public enum ControllerRunResult{FatalError, Finished, NonFatalError, NotRun}
public interface IController
{
    ControllerRunResult Run();
}
Run Code Online (Sandbox Code Playgroud)

controller.dll包含这个类(也调用COM互操作的东西):

public class Controller: IController, MarshalByRefObject
Run Code Online (Sandbox Code Playgroud)

首次运行应用程序时,Assembly.GetAssemblies()看起来像预期的那样,在两个AppDomain中都加载了common.dll,并且只将controller.dll加载到控制器域中.在调用c.Run()之后,我看到与COM互操作内容相关的程序集已加载到默认的AppDomain中,而不是在发生COM互操作的AppDomain中.

为什么会发生这种情况?

如果你有兴趣,这里有一些背景知识:

最初这是一个AppDomain应用程序.它与之接口的COM东西是一个服务器API,它在长时间使用时不稳定.当COM东西发生COMException(没有关于其原因的有用诊断信息)时,整个应用程序必须重新启动才能再次使用COM连接.只需重新连接到COM应用服务器,就会再次导致COM异常.为了解决这个问题,我试图将COM互操作内容移动到一个单独的AppDomain中,这样当神秘的COMExceptions出现时,我可以卸载发生它的AppDomain,创建一个新的并再次启动,所有这些都无需手动重启应用程序.无论如何,这就是理论......

c# com interop com-interop appdomain

8
推荐指数
1
解决办法
3397
查看次数

即使找到接口,CoCreateInstance也会返回E_NOINTERFACE

我有一个COM类在一个应用程序中CMyCOMServer实现IMyInterface,两个都具有正确的GUID.CMyCOMServer::QueryInterface如果请求IUnknown或IMyInterface,则返回S_OK(并将其自身转换为正确的类型),否则返回E_NOINTERFACE.

在同一台PC上的另一个应用程序中,我打电话给:

HRESULT hr = ::CoCreateInstance(__uuidof(CMyCOMServer), 0, CLSCTX_SERVER,
 __uuidof(IMyInterface ),(void **)&pInterface);
Run Code Online (Sandbox Code Playgroud)

它返回E_NOINTERFACE.所以我认为我做错了什么并添加了一个断点CMyCOMServer::QueryInterface.我发现在CoCreateInstance调用时,QueryInterface会针对不同的接口多次触发:

  • 首先,要求IUnknown - 没问题
  • 然后,请求几个接口,如IMarshall等...这些不受支持,因此返回E_NOINTERFACE
  • 最后,请求IMyInterface.我验证QueryInterface返回S_OK并按(IMyInterface *)this预期设置为接口指针

所以我的困惑是为什么调用CoCreateInstance给我留下一个NULL指针并返回E_NOINTERFACE代码,当COM服务器应用程序显然返回我要求的接口?

编辑:我的客户端应用程序在启动时调用CoInitialize(NULL),这没有任何区别.

c++ windows com com-interop visual-c++

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

COM程序如何找到为COM Interop注册的.NET DLL?

一个客户想要从VB6使用我们的.NET DLL.它们旨在支持反向互操作,所有工作都很好......除了:在两个不同的目录中有两个单独的VB6程序.似乎有必要做一个:

  1. 将.NET DLL复制到两个目录中,或
  2. 在GAC中安装.NET DLL

这是客户的观察,也得到了RegAsm文档的支持:

使用Regasm.exe注册程序集后,可以将其安装在全局程序集缓存中,以便可以从任何COM客户端激活它.如果程序集仅由单个应用程序激活,则可以将其放在该应用程序的目录中.

我对这一点感到困惑.

第一点困惑:

据我所知,COM运行时使用Prog ID/Class ID定位DLL.当我在类ID条目的注册表中查看时,我在CodeBase键中看到了.NET DLL的完整路径.为什么使用Prog ID/Class ID的COM程序无法使用CodeBase找到.NET DLL?

第二点困惑:

GAC特定于.NET.它如何参与解析COM引用?

gac com-interop regasm

8
推荐指数
1
解决办法
966
查看次数

语言中立的插件架构

我期待通过使用插件架构扩展现有的应用程序.应用程序ID是用Delphi编写的,但我希望能够以最好的工作方式实现各种语言的各种插件.目前我们拥有Delphi,C#和Java技能,并且希望能够以所需的任何语言实现插件.

有谁知道可以用来实现这个的示例系统?

我假设我可以在特定的COM接口上进行标准化,并且实现该接口的任何东西都可以是插件.

有没有人有任何指针?

谢谢

c# java delphi plugins com-interop

8
推荐指数
1
解决办法
409
查看次数

我应该在.NET中使用哪个集合接口进行COM-interop?

这是我之前的问题的后续内容,但您不需要阅读它来理解那个问题.

我正在设计.NET中的接口,它将从COM应用程序(主要是VB6,但Visual C++ 6也是一种可能性)中使用,我想使用Collection类型作为接口中方法的参数和返回类型.

问题:

  1. 当VB6内置集合类型(数组,集合,字典)通过互操作时会发生什么?我目前的猜测是:

    • 数组 - > System.Array
    • 收藏 - > Microsoft.VisualBasic.Collection
    • 词典 - > System.Collections.Hashtable

    那是对的吗?

  2. 我应该使用哪些接口作为返回类型?IEnumerable,ICollection,IList,IDictionary?我是否能够在VB6中执行For Each迭代这些接口?我应该使用接口的通用或非通用变体吗?

.net vb6 com-interop

8
推荐指数
1
解决办法
3822
查看次数

从C#创建COM索引属性?

我试图用一个新的.net来模仿一个旧的vb6 dll.模仿必须是完美的,以便呼叫者不知道他们正在使用新的.dll.

我有一种好奇心.在VB6中,它在对象库中具有以下内容:

Property BankList(Index As Long) As String
Run Code Online (Sandbox Code Playgroud)

但AFAIK属性这不能在.net中完成吗?

我能得到的最接近的是创建一个展示该行为的函数,然后COM类型从Property转到Method.

任何人都可以建议我如何使用属性创建该签名?

.net c# vb6 com-interop

8
推荐指数
2
解决办法
443
查看次数

在.net 4.0 dll中访问.net2.0 dll

我想在我的.Net4.0 dll中加载一个.NET 2.0 dll.我确实搜索了解决方案并找到了'useLegacyV2RuntimeActivationPolicy'属性,我可以将其添加到我的app.config中,如此URL:混合模式程序集是针对版本'v1.1.4322'构建的

但问题是,在我的情况下,我试图在我的4.0 DLL中使用.net2.0 dll,而不是在4.0 exe中.原因是这个4.0 dll然后在Excel中用作自动化插件.

目前,当我从Excel处理我的.NET 4.0 API(为一个功能加载2.0 dll)时,我得到'混合模式2.0 dll无法在4.0运行时加载',这是可以理解的,因为COM加载了4.0 CLR,因此无法加载2.0 dll.

不知何故,我需要使我的4.0 DLL加载2.0运行时.我尝试将app.config添加到4.0 dll但我猜只有.exe默认读取app.config才能加载clr.这是我在4.0 dll项目中的app.config中所拥有的,但没有用.

    <?xml version="1.0"?>
<configuration>
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
  <runtime>
    <NetFx40_LegacySecurityPolicy enabled="true"/>
  </runtime>
</configuration>
Run Code Online (Sandbox Code Playgroud)

如何解决此问题以使我的.NET 4.0 DLL能够使用.NET 2.0 DLL?

谢谢,玛尼

.net c# com clr com-interop

8
推荐指数
1
解决办法
5349
查看次数

在.NET中为Interop公开属性作为变体

我正在.NET中创建一个包装类(VB.NET,因为它发生但与C#同样相关),它暴露给COM,我试图包装的一个属性是Variant.我以为我只能使用一个Object,但是我收到一个错误:

Public Property FieldValue([vFieldID As Object = -1]) As Object不能作为属性'让'暴露给COM.您将无法使用"Let"语句从Visual Basic 6.0为此属性分配非对象值(如数字或字符串).*

我的财产声明如下:

Public Property FieldValue(Optional ByVal vFieldID As Object = -1) As Object
    Get
        Return _objVAccess.FieldValue(vFieldID)
    End Get
    Set(ByVal value As Object)
        _objVAccess.FieldValue = value
    End Set
End Property
Run Code Online (Sandbox Code Playgroud)

我的属性实际上从数据库返回一个值,可以是整数,字符串,日期等,因此它不是 COM方面的对象.是否有任何解决方法允许属性让?

c# vb.net com properties com-interop

8
推荐指数
1
解决办法
7051
查看次数

MethodImplAttribute(InternalCall,Runtime)对COM Interop接口的方法做了什么?

Windows API Code Pack for .NET Framework中,COM Interop接口的许多方法都使用MethodImplAttribute例如:

internal interface IShellItem
{
    [PreserveSig]
    [MethodImpl(
        MethodImplOptions.InternalCall,
        MethodCodeType = MethodCodeType.Runtime)]
    HResult BindToHandler(
        [In] IntPtr pbc, [In] ref Guid bhid, [In] ref Guid riid,
        [Out, MarshalAs(UnmanagedType.Interface)] out IShellFolder ppv);
Run Code Online (Sandbox Code Playgroud)

MethodImplOptions.InternalCall价值文件说:

调用是内部的,也就是说,它调用在公共语言运行库中实现的方法.

文档MethodCodeType.Runtime说:

指定方法实现由运行时提供.

但是,如果我理解正确,这两种说法都是正确的.据MSDN称,它IShellItem是在shell32.dll中实现的.shell32.dll不是CLR的一部分.有趣的是,并非所有方法都有MethodImplAttribute.IShellFolder是,IShellLinkW不,IShellLibrary做,IPersistStream不等.

为什么MethodImplAttribute应用于某些COM Interop接口?在这种情况下它意味着什么?它如何修改互操作的行为?

.net c# com com-interop

8
推荐指数
1
解决办法
2632
查看次数

使用提升的权限进行调试时,Marshal.GetActiveObject("Outlook.Application")会抛出MK_E_UNAVAILABLE

当Visual Studio未作为管理员启动时,此代码在版本r调试中运行没有问题.

Marshal.GetActiveObject("Outlook.Application");
Run Code Online (Sandbox Code Playgroud)

但是,当我以管理员身份启动Vs并在调试中运行相同的行时,我收到以下错误:

System.Runtime.InteropServices.COMException
Operation unavailable (Exception from HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))
Run Code Online (Sandbox Code Playgroud)

我怎样才能解决这个问题.

.net c# com-interop elevated-privileges visual-studio-2013

8
推荐指数
1
解决办法
4594
查看次数