Tag: com interop

如何将暴露给COM-interop的.NET对象标记为单线程?

在C ++中定义COM可见类时,我可以在头文件中定义支持的线程模型( threading(single) ): [ coclass, default(IComInterface), threading(single), vi_progid(“Example.ComClass”), progid(“Example.ComClass.1”), version(1.0), uuid(“72861DF5-4C77-43ec-A4DC-ED04396F0CCD”) ] 是否有类似的方法在.NET中设置线程模型(例如属性)? 我目前正在定义我的COM类: [Guid(“67155A91-2948-43f5-B07F-5C55CDD240E5”)] [ComVisible(true)] [InterfaceType(ComInterfaceType.InterfaceIsDual)] public interface IComInterface { … } [Guid(“DC5E6955-BB29-44c8-9FC0-6AADEEB2AFFB”)] [ClassInterface(ClassInterfaceType.None)] [ProgId(“Example.ComClass”)] public class ComClass : IComInterface { … } – 编辑: 对标记答案的评论非常重要。 似乎告诉RegAsm设置不同的ThreadingModel的唯一方法是编写一个标有[ComRegisterFunction]属性的自定义注册方法。

如何通过COM公开可空类型

我一直在努力解决这个问题一天半,希望有人可以帮助我。 假设我在C#中有这样的结构: public struct Part { public double? x; // or System.Nullable x, doesn’t really matter } (这些结构表示数据库表,从Linq转换为SQLMetal创建的SQL代码) 我需要能够将包含可空类型的这些结构公开给COM,以便它们可以在另一个应用程序(C ++)中使用。 但我无法弄清楚,对于我的生活,如何做到这一点。 我以为我可以创建类来封装可空类型: public class NullableDouble { private double _Value; // class methods… } public struct Part { public NullableDouble x; } 这种工作,但在C ++方面,我最终得到一个指向类的指针,但没有类定义(只是一个接口): interface DECLSPEC_UUID(“{E8EE4597-825D-3F4C-B20B-FD6E9026A51C}”) _NullableDouble; struct Part { MyDll_tlb::_NullableDouble* x; } 因此,我无法取消引用没有类定义的指针,从中可以访问C ++端的数据成员/方法。 如果我能弄清楚如何在C […]

如何在C#,2012版中正确清理Excel互操作对象

我正在用C#编写一个应用程序,它将通过互操作打开一个Excel电子表格(2007年,现在),做一些魔术,然后关闭。 “魔术”部分非常重要,因此该应用程序将包含对Excel生成的许多COM对象的许多引用。 我以前写过这种应用程序(事实上已经太多次了)但是我从来没有找到一种舒适的,“好闻”的方法来与COM对象进行交互。 问题部分在于,尽管进行了大量研究,我仍然不能完全理解COM,部分是因为互操作包装器隐藏了很多可能不应该隐藏的内容。 事实上,来自社区的这么多不同的,相互冲突的建议只会让事情变得更糟。 如果您无法从标题中分辨出来,我已经完成了我的研究。 标题暗示了这篇文章: 如何正确清理Excel互操作对象? 在2008年首次询问时,这个建议在当时非常有用且非常可靠(特别是“从不使用带有com对象的2个点”位),但现在看来已经过时了。 2010年3月,Visual Studio团队发布了一篇博客文章,警告其他程序员Marshal.ReleaseComObject [is] Considered Dangerous 。 文章提到了两篇文章, cbrumme的WebLog> ReleaseComObject以及接口指针和运行时可调用包装器(RCW)之间的映射 ,表明人们一直错误地使用ReleaseComInterop(cbrumme:“如果你是一个使用适度数量的客户端应用程序在托管代码中自由传递的COM对象,不应使用ReleaseComObject“)。 有没有人有一个中等复杂的应用程序的例子,最好使用多个线程,能够成功地在内存泄漏之间导航(Excel在应用程序关闭后继续在后台运行)和InvalidComObjectExceptions? 我正在寻找能够在创建它的上下文之外使用COM对象的东西,但是一旦应用程序完成它仍然可以清理它:内存管理策略的混合,可以有效地跨越托管/非管理鸿沟。 对于讨论这个问题的正确方法的文章或教程的引用将是一个非常受欢迎的替代方案。 我最好的Google-fu努力已经返回了显然不正确的ReleaseComInterop方法。 更新: (这不是答案) 发布后不久我发现了这篇文章: Jake Ginnivan的VSTO和COM Interop 我已经能够通过扩展方法实现他在“AutoCleanup”类中包装COM对象的策略,我对结果非常满意。 虽然它没有提供允许COM对象跨越创建它们的上下文边界的解决方案,并且仍然使用ReleaseComObject函数 ,但它至少提供了一个简洁易读的解决方案。 这是我的实现: class AutoCleanup : IDisposable { public T Resource { get; private set; } public AutoCleanup( T resource ) { this.Resource = resource; […]

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); common.dll只包含以下两件事: public enum ControllerRunResult{FatalError, Finished, NonFatalError, NotRun} public interface IController { ControllerRunResult Run(); } controller.dll包含这个类(也调用COM互操作的东西): public class Controller: IController, MarshalByRefObject 首次运行应用程序时,Assembly.GetAssemblies()看起来像预期的那样,在两个AppDomain中都加载了common.dll,并且只将controller.dll加载到控制器域中。 在调用c.Run()之后,我看到与COM互操作相关的程序集已加载到默认的AppDomain中,而不是在发生COM互操作的AppDomain中。 为什么会发生这种情况? 如果你有兴趣,这里有一些背景知识: 最初这是一个1 AppDomain应用程序。 它与之接口的COM东西是一个服务器API,在长时间使用时不稳定。 […]

为COM Interop公开dll

我以为我知道怎么做,但显然不是这样,我会感激一些帮助! 我无法让我的dll注册,所以我可以在VBS或其他地方实例化它。 我编写了以下示例类,选中“Make assembly COM Visible”,选中“Register for COM Interop”,然后构建它。 当我尝试从VBS实例化它时,我得到“Activex组件无法创建对象”错误。 这是类代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Smurf { public class Pants { public string Explode(bool Loud) { string result; if (Loud) result = “BANG”; else result = “pop”; return result; } } } ……这是VBS: Dim a Set a = CreateObject(“Smurf.Pants”) msgbox(“ok”) […]

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

我在.NET(C#)中使用了广泛的现有COM API(可能是Outlook,但它不是)。 我已经通过在Visual Studio中添加“COM Reference”来完成此操作,因此所有“魔法”都是在幕后完成的(即,我不必手动运行tlbimp )。 虽然现在可以从.NET“轻松”使用COM API,但它不是非常友好的.NET。 例如,没有generics,事件很奇怪,像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(); } […]

无注册在64位COM dll和C#/ .Net应用程序之间互操作

我试图在64位COM DLL和C#应用程序之间获得免注册COM互操作。 在我之前的一个问题的答案中 ,我得到了帮助,这使我能够在C#的64位COM dll上成功调用HelloWorld方法。 但是,这只能通过使用regsrv32.exe全局注册COM dll来实现。 基于对相关问题的这个答案 ,我认为我需要将COM dll的引用上的Isolated标志设置为true。 但是,这会导致以下构建错误: Problem isolating COM reference ‘ComLibInteropLib’: No registered classes were detected for this component. 关于MSDN社交问题的答案似乎表明,如果可以编译32位版本的dll,就可以解决这个问题。 但是,我的COM互操作库需要链接到一个“普通”的C ++ dll,我没有源代码,只能用于x64。 所以我的问题是:如何在64位COM dll和C#应用程序之间启用Isolated标志(或以其他方式并行工作)? 我很高兴在我的机器或其他开发人员的机器上使用regsrv32.exe,但我们无法在最终应用程序必须运行的生产机器上注册任何COM dll。

.NET是否定义了常见的HRESULT值?

我在C#中创建一个COM类,它将从非托管C ++中调用。 我想使用ThrowExceptionForHR,但我不想硬编码HRESULT数值。 我原以为在.Net某处会有一些常见的HRESULT值? 换句话说,在哪里可以找到映射到HRESULT值的命名符号以传递给ThrowExceptionForHR ? 更新: MS在此页面中讨论它: 管理代码中的HRESULT信息 。 它们引用了VSConstants类Microsoft.VisualStudio.VSConstants但是当我尝试使用它时,它声称命名空间不存在。

TLB在部署时没有Regsrv32来管理.NET程序集

我有一个TLB作为第三方API的一部分提供。 我使用TLBIMP.exe生成DLL程序集包装器。 但是,在开发时,似乎程序集需要使用regsvr32进行注册。 然而,这在开发时不是问题; 我在生产中使用托管实例,并且在部署时手动注册DLL将是一个痛苦,如果不是不可能的话。 有没有办法在部署期间不需要注册步骤的方式使用托管DLL程序集? 我一直在互联网上阅读,并使用app.manifest找到了一些关于免注册COM的文献。 这可行吗?

在WPF中禁用WebBrowser上的上下文菜单

我有一个WPF应用程序,它将在带有触摸屏的PC上的自助服务终端上运行。 应用程序以全屏模式运行,以隐藏操作系统。 在我的一个页面上,我有一个WebBrowser控件,允许用户查看一些网页(导航仅限于某些页面)。 由于计算机将被放置在公共场所,我不能让用户访问操作系统。 问题是,触摸屏允许右键单击Web浏览器,最终导致任务栏出现……不好……! 我一直试图在过去几天禁用该上下文菜单而没有太大的成功。 基本上我现在在的地方是: 添加了对SHDocVw.dll的COM引用以获取IWebBrowser2接口(需要禁用新窗口的启动。 [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid(“6d5140c1-7436-11ce-8034-00aa006009fa”)] internal interface IServiceProvider { [return: MarshalAs(UnmanagedType.IUnknown)] object QueryService(ref Guid guidService, ref Guid riid); } static readonly Guid SID_SWebBrowserApp = new Guid(“0002DF05-0000-0000-C000-000000000046”); 获取IWEbBrowser2接口 IServiceProvider _serviceProvider = null; if (_browser.Document != null) { _serviceProvider = (IServiceProvider)_browser.Document; Guid _serviceGuid = SID_SWebBrowserApp; Guid _iid = typeof(SHDocVw.IWebBrowser2).GUID; SHDocVw.IWebBrowser2 _webBrowser […]