Tag: com interop

Activator.CreateInstance()在VSIDE内部工作,但不在外部工作

我有一堆COM对象,它们都实现了相同的接口,并且需要在运行时从选项列表中创建其中一个。 由于我知道每个实现COM服务器的CLSID,因此这应该很容易。 但是,对于某个COM库的子集,如果我在VS2010 IDE中运行,我只能使这个工作。 这是我用来测试的整个程序: using System; namespace ComTest { class Program { static void Main(string[] args) { var clsid = “{E8978DA6-047F-4E3D-9C78-CDBE46041603}”; var type = Type.GetTypeFromCLSID(new Guid(clsid)); var obj = Activator.CreateInstance(type, true); Console.WriteLine(“Obj is {0}”, obj); } } } 只要我通过VS2010运行,我就可以为迄今为止尝试过的每个COM CLSID做这项工作。 无论是否附加调试器,无论是否附加了托管进程,我都会从CreateInstance获取System.__ComObject 。 当我从控制台窗口编译并运行此代码时,对于某些CLSID值,我得到: Unhandled Exception: System.Runtime.InteropServices.COMException: Creating an instance of the COM component with […]

使用C#中的复杂用户定义类型(UDT)调用VB6 DLL函数

我正在编写一个C#应用程序来调用第三方VB6 DLL。 我在References-> COM选项卡中添加了对VB6 DLL的引用。 DLL中的特定方法采用VB6 UDT(用户定义类型)作为参数。 此UDT在COM的自动生成的.NET包装器中显示为结构。 该结构具有许多子UDT /结构以及VBA.Collection类型的成员(如.NET元数据所示)。 它还有常规数据类型,如string,short,double,int等。 我在我的C#代码中初始化这个结构为: udtEmployee udtEmpData = default(udtEmployee); 我也试过了 udtEmpData = new udtEmployee(); 如果我没有使用default或new初始化它,我无法编译我的C#代码,因为编译器抱怨使用未分配的变量。 我需要传递这个结构作为参考。 我是这样做的: clsEmployee.SetData(ref udtEmpData); 在调用VB6 DLL的这个方法时,我收到错误: 错误:尝试读取或写入受保护的内存。 这通常表明其他内存已损坏。 原因是什么,解决方案是什么? 注意,我无法更改VB6 DLL,因为我没有其源代码。 我正在使用VS 2005。 编辑1: 这是一个完整的背景: 有一个本地开发的ERP产品,它支持使用VB6进行附加开发。 它有一个配置文件,它指定要加载的附加DLL的名称。 然后,这些插件将显示在ERP应用程序的菜单中。 在菜单上单击,ERP调用名为StartAddOn()的函数,该函数应存在于VB6 DLL中。 我想在C#中开发附加组件,因此我开发了一个带有StartAddOn方法的简单VB6插件,该方法又将控制权传递给我的.NET DLL。 .NET DLL使用ERP公开的业务类,并来回传递数据对象。 在.NET DLL中,我添加了对ERP供应商发布的DLL的COM引用。 所以架构是这样的:ERP-> VB6 AddOn和StartAddOn方法 – > .NET DLL->使用ERP供应商发布的COM […]

无法在COM客户端中添加引用COM?

创建一个COM服务器,然后我注册了它。 当我尝试在COM客户端中添加该COM服务器时,我无法添加,并且出现以下错误。 “无法添加对’COMTest’的引用 ActiveX类型库’c \ user \〜\ Debug \ COMTest.tlb’是从.NET程序集导出的,无法添加为引用。 添加对.NET的引用“ 任何人都可以告诉我这是什么错误。 我以两种方式注册COM,也来自VS,也尝试使用命令提示符。

无法通过AppDomains传递GCHandle:没有代表的解决方案?

我在c ++中有基础库,客户端应用程序在C#中。 有c ++ / cli接口可以从C#访问c ++ api。 一切都运行良好,直到多个应用程序域没有像NUnit或WCF托管一样发挥,即有一个应用程序域。 我已经在cli中的gcroot中存储了托管对象以进行回调。 我已经读过这是应用程序域问题的根本原因(“无法通过AppDomains传递GCHandle”),因为它们没有应用程序域信息( http://lambert.geek.nz/2007/05/29/unmanaged -appdomain-callback / )。 有人建议使用委托,但我的底层c ++层期望对象不是函数指针( http://www.lenholgate.com/blog/2009/07/error-cannot-pass-a-gchandle-across-appdomains.html )。 我也尝试过IntPtr,但在这种情况下,我无法在回调期间将其强制转换为我的托管对象。 UPDATE 让我再详细说明一下我的问题。 我在C#中有“Receiver”类 ,它作为输入参数传递给api之一。 此接收器对象用于回调。 在C ++ / CLI中,我创建了一个Native / unmanaged类“ObjectBinder” ,它与托管的Receiver类具有相同的副本(具有相同的方法)。 它保存了gcroot中托管接收者对象的引用 。 当我们从C#调用api时,它来到CLI层, app域是“client exe” 。 我们在gcroot的ObjectBinder中存储参数“managed receiver object”,并将本机ObjectBinder对象的引用传递给C ++。 现在后端代码(c ++和c)向c ++层发送一个asyn回调 ( 新线程 ),该层使用ObjectBinder对象向CLI发送回调用。 现在我们在ObjectBinder对象的CLI层中。 但是App域已被更改(在WCF或NUNIT或任何其他创建它自己的App域的服务的情况下,在编译时不知道) 。 现在我想访问存储在gcroot中的托管Receiver对象,以便将回调发送回C#,但它给出了APP DOMAIN错误。 我也试过IntPtr和IUnknown *而不是gcroot与Marshal […]

在C#中使用相同的COM接口在2个不同的库之间进行转换

我有一对使用相同COM接口的库。 在一个库中,我有一个实现该接口的类。 另一个库需要一个实现接口的对象。 但是两个库都有自己的接口定义。 两者略有不同,但基本上是相同的界面。 所以我试着将它们放在如下: Library2.Interface intf = (Library2.Interface)impl; 但这引起了例外。 如果我执行以下操作: Library1.Interface intf = (Library1.Interface)impl; 然后它没有问题,但我不能再将类传递给Library2。 我天真地假设两个具有相同GUID的接口都可以防止这是一个问题,但我似乎错了。 有谁知道如何在两个库之间进行转换? 也许是通过某种元帅?

MTA控制台应用程序从多个线程调用STA COM对象

虽然有很多关于COM和STA / MTA的问题(例如这里 ),但大多数人都在讨论具有UI的应用程序。 但是,我有以下设置: 控制台应用程序,默认为Multi-Threaded Apartment(Main()显式具有[MTAThread]属性)。 主线程产生一些工作线程。 主线程实例化单线程COM对象。 主线程调用Console.ReadLine()直到用户点击’q’,然后应用程序终止。 几个问题: 许多地方都提到需要为COM对象提供消息泵 。 我是否需要为主线程手动创建消息泵,或者CLR是否会在新的STA线程上为我创建消息泵,正如这个问题所示? 只是为了确保 – 假设CLR自动创建必要的管道,然后我可以使用来自任何工作线程的COM对象而无需显式同步吗? 在性能方面,以下哪项更好: 让CLR负责处理来自COM对象的编组。 在单独的STA线程上显式实例化对象,并让其他线程通过例如ConcurrentQueue与之通信。

Marshal.GetActiveObject()在C#中抛出MK_E_UNAVAILABLEexception

以下vbscript代码完美地工作: Dim App Set App = GetObject(“”,”QuickTest.Application”) App.Quit 但是,当我将其翻译成C#代码时,如下所示: class Program { [STAThread] static void Main(string[] args) { object qtApp = Marshal.GetActiveObject(“QuickTest.Application”); (qtApp as QuickTest.Application).Quit(); } } 我得到了例外: mscorlib.dll中发生未处理的“System.Runtime.InteropServices.COMException”类型exception 附加信息:(来自HRESULT的exception:0x800401E3(MK_E_UNAVAILABLE)) 我不认为问题与ROT有关,因为vbscript代码有效。 那么C#代码有什么问题?

是否可以从.NET测试COM暴露的程序集?

我有一个.NET程序集,我通过tlb文件向COM公开,以及一个注册tlb的安装程序。 我已手动检查安装程序是否正常工作,并且COM客户端可以访问该库。 到现在为止还挺好… 但是,我正在尝试组合一些自动化系统测试,以检查安装程序是否正常工作。 作为其中的一部分,我已经在VM上自动安装,我现在想要对已安装的COM库进行一些调用以validation它是否正常工作。 我最初想过在VB6中编写一些测试,但我已经有了一大堆用C#编写的测试,它引用了.NET程序集。 我希望我可以更改这些以引用.tlb,但是当我在VS2008中尝试这个时出现错误: ActiveX类型库’blah.tlb’是从.NET程序集导出的,无法添加为引用。 有什么方法可以欺骗VS2008允许我添加这个引用,也许是通过编辑tlb文件? 谷歌搜索没有提出任何解决方案。 我发现的只是一篇Microsoft Connect文章,声明这是“按设计”: http : //connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx ?FeedbackID = 120882

何时有必要/适当使用InAttribute和OutAttribute进行COM Interop

我正在努力解决我们分散在各个项目中的COM互操作定义的混乱,并将它们收集到一个已知良好的位置,整个开发团队可以从中受益。 这项工作的一部分涉及清理多年来积累的定义。 其中一些是从其他源代码借来的,有些是从pinvoke.net逐字复制的,有些看起来是直接从SDK头文件中翻译过来的。 我注意到的一件事是关于何时使用各种编组属性没有一致性(即使在pinvoke.net示例中,这也非常棒)。 问题的一部分是,我不认为这里的任何人(包括我自己)完全理解何时需要各种属性,或者他们实际做了什么。 到目前为止,在COMExceptions停止发生之前,获得这些权利似乎是猜测和随机变化的组合,但我更倾向于翻译是正确的,因为有人实际上看了他们并宣布了这些。 所以,我从[In]和[Out] 。 我知道这两个属性在概念上是什么:它们告诉编组人员数据必须走向哪个方向。 例如,我假设 marshaller不会打扰将[In]数据复制回调用者,或者知道可能需要在被调用者端释放[Out]数据,等等。我不知道的事情是: 什么时候需要使用这些属性? 也就是说,什么时候默认的编组行为是错误的,这样属性才能使其正确? 什么时候使用这些属性是安全的 ? 也就是说,指定应该已经存在的默认行为会改变编组程序的工作方式吗? 什么时候使用这些属性是危险的 ? 我假设显式标记输出参数[In]是坏的,但是标记输入参数[In, Out]实际上会破坏什么? 因此,假设一个假设的COM接口方法,其IDL如下所示: HRESULT Foo( [in] ULONG a, [out] ULONG * b [in, out] ULONG * c); 我可能会看到这翻译为以下任何一种: void Foo( uint cb, out uint b, ref uint c); void Foo( uint cb, [Out] out uint b, [In, […]

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

[EDITED] 这似乎是 Framework的Application.DoEvents实现中的一个错误 ,我在这里报告过 。 在UI线程上恢复错误的同步上下文可能会严重影响像我这样的组件开发人员。 赏金的目标是更多地关注这个问题并奖励@MattSmith,他的答案帮助追踪它。 我负责通过COM互操作将基于.NET WinForms UserControl的组件作为ActiveX暴露给传统的非托管应用程序 。 运行时要求是.NET 4.0 + Microsoft.Bcl.Async。 该组件被实例化并在应用程序的主要STA UI线程上使用。 它的实现使用async/await ,因此它期望在当前线程(即WindowsFormsSynchronizationContext )上安装序列化同步上下文的实例。 通常, WindowsFormsSynchronizationContext由Application.Run设置,这是托管应用程序的消息循环运行的地方。 当然, 这不是非托管主机应用程序的情况 ,我无法控制它。 当然,主机应用程序仍然有自己的经典Windows消息循环,因此序列化await延续回调应该不是问题。 然而,到目前为止我提出的解决方案都不是完美的,甚至都不能正常工作。 这是一个人为的例子,主机app调用Test方法: 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 != […]