Tag: com interop

如何在c#中调用visual basic 6.0方法?

我想用c#(visual studio 2008)编写一个用visual basic 6.0编写的方法。 可能吗? 我该怎么办?

如何优雅地防止Web服务代理暴露给COM?

我有一个C#程序集,我用作非托管C ++应用程序使用的进程内COM服务器。 程序集使用一个永远不会改变的Web服务,因此不需要更新Web服务代理类。 这就是为什么代理类被创建一次而Reference.cs文件被简单地放入存储库并且只从那里编译。 问题是默认情况下,webservice代理类是公共的,因此暴露给COM。 这会使typelib和污染注册表膨胀。 将可见性更改为内部会破坏程序集,因此这些实体需要保持公开,但不需要向COM公开。 愚蠢的方法是接近Reference.cs文件中的每个公共接口/类并标记它 [System.Runtime.InteropServices.ComVisible(false)] 之后,它不再暴露给COM。 有没有更好的办法?

托管托管代码和垃圾回收

我有一个C ++进程外COM服务器,它承载了很多C#代码,以支持C ++ COM对象公开的API。 由于各种原因,我正在考虑取消我的解决方案的C ++部分。 但是,由于我无法控制的限制,我必须保留进程外的COM服务器。 微软确实在这里有一个典型的例子。 看看这个例子,我有些不明白。 在消息循环开始之前,会创建一个计时器,每隔5秒调用GC.Collect。 我能找到的唯一提到的就是确保在合理的时间范围内释放COM对象。 我对此有点困惑…我的C ++主机当前是否自动调用GC.Collect? 我当然不是这样做的。 然而,我正在创建托管对象(COMVisible(true)作为C ++代码中的COM对象。这是否意味着我现在应该每5秒调用一次GC.Collect?如果没有,为什么我需要在这个新的C#中调用它是否可以弥补在普通C ++应用程序中清理未引用的COM对象的自动进程?(我假设在消息循环期间的某个时间发生了这种情况)。 每5秒调用一次GC.Collect似乎可能是一个坏主意。 我担心吗? 是否有其他方法可以达到相同的效果? 我使用的是.NET 4.5和Visual Studio 2012。

WebBrowserSite:如何在派生类中调用私有COM接口方法?

这是挑战。 我是从Framework的WebBrowserSite类派生出来的。 我的派生类ImprovedWebBrowserSite一个实例是通过WebBrowser.CreateWebBrowserSiteBase返回的,我在WebBrowser类的派生版本中覆盖了它 – 专门用于提供自定义站点对象。 Framework的WebBrowser实现进一步将其传递给底层的非托管WebBrowser ActiveX控件。 到目前为止,我已经设法在我的ImprovedWebBrowserSite实现中覆盖IDocHostUIHandler (像这样 )。 我现在正在寻找更多的核心COM接口,比如IOleClientSite ,我想将它传递给WebBrowserSite 。 所有这些都通过ComImport暴露给COM,但是通过Framework的WebBrowserSite / UnsafeNativeMethods实现声明为private或internal 。 因此,我无法在派生类中明确地重新实现它们。 我必须定义自己的版本,就像我使用IDocHostUIHandler 。 所以,问题是,如何从我的派生类中调用WebBrowserSite定义的私有或内部COM接口的方法? 例如,我想调用IOleClientSite.GetContainer 。 我可以使用reflection(像这样 ),但这将是最后的手段,其次是从头开始重新实现WebBrowser 。 我的想法是,因为Framework的私有UnsafeNativeMethods.IOleClientSite和我自己的ImprovedWebBrowserSite.IOleClientSite都是COM接口,使用ComImport属性声明,相同的GUID和相同的方法签名。 .NET 4.0+中有COM类型等价 ,因此必须有一种方法可以在没有reflection的情况下完成。 [更新]现在我已经有了解决方案 ,我相信它为自定义WebBrowser控件的WinForms版本打开了一些新的和有趣的可能性。 这个版本的问题是在我最初尝试以更抽象的forms提出问题之后创建的,被评论员称为误导。 评论已被删除,但我决定保留这两个版本。 为什么我不想用reflection来解决这个问题? 原因如下: 依赖于内部或私有方法的实际符号名称,由WebBrowserSite的实现者给出,与COM接口不同,后者是关于二进制v表合同。 庞大的reflection代码。 例如,考虑通过Type.InvokeMember调用base的私有TranslateAccelerator ,我有大约20个这样的方法来调用。 虽然不太重要,但效率:通过reflection的后期绑定调用总是比通过v-table直接调用COM接口方法效率低。

COMException(0x800A13E9) – Word互操作服务

我得到这个堆栈跟踪: System.Runtime.InteropServices.COMException (0x800A13E9): Word ðú÷ì ááòéä. at Microsoft.Office.Interop.Word.Documents.Add(Object& Template, Object& NewTemplate, Object& DocumentType, Object& Visible) at Crm.DocumentGeneration.Printing.DocumentsPrinter.MergeDocuments(ApplicationClass& wordApp, IEnumerable`1 printDataItems, String tempDirectory, String template) in C:\Work\Danel.Nursing\Crm.DocumentGeneration.Printing\DocumentsPrinter.cs:line 249 谷歌搜索后似乎COMException(0x800A13E9)内存不足exception,但服务器上有足够的内存来启动太空船 8192太空飞船。 这是函数调用: Document document = wordApp.Documents.Add(ref defaultTemplate, ref missing, ref missing, ref missing); 我检查过defaultTemplate没有null或无效。

为什么我的.NET组件上的索引器不能始终从VBScript访问?

我有一个.NET程序集,我通过COM互操作从VBScript(经典ASP)访问。 一个类有一个索引器(也就是默认属性),我通过向索引器添加以下属性从VBScript开始工作: [DispId(0)] 。 它适用于大多数情况,但不能作为另一个对象的成员访问该类。 如何使用以下语法使其工作: Parent.Member(“key”)其中Member具有索引器(类似于访问内置Request.QueryString的默认属性: Request.QueryString(“key”) ) ? 在我的例子中,有一个带有QueryString属性的父类TestRequest ,它返回一个IRequestDictionary ,它有默认的索引器。 VBScript示例: Dim testRequest, testQueryString Set testRequest = Server.CreateObject(“AspObjects.TestRequest”) Set testQueryString = testRequest.QueryString testQueryString(“key”) = “value” 以下行导致错误而不是打印“值”。 这是我想要工作的语法: Response.Write(testRequest.QueryString(“key”)) Microsoft VBScript运行时(0x800A01C2) 参数数量错误或属性赋值无效:’QueryString’ 但是,以下行无错误地工作并输出预期的“值”(请注意,第一行访问临时变量上的默认索引器): Response.Write(testQueryString(“key”)) Response.Write(testRequest.QueryString.Item(“key”)) 下面是C#2.0中的简化接口和类。 它们已通过RegAsm.exe /path/to/AspObjects.dll /codebase /tlb : [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] public interface IRequest { IRequestDictionary QueryString { get; } } [ClassInterface(ClassInterfaceType.None)] […]

使用com-interop将数组从vba传递给c#

使用com-interop将用户定义的类数组从vba传递到.net(特别是c#)的正确方法是什么? 这是我的c#代码。 如果我从vba调用Method1,它会因“期望的数组或用户定义类型”或“函数使用visual basic中不支持的自动化类型”而失败。 public class MyClass { public Method1(UserDefinedClass[] Parameters) { … } public Method2(Object Parameters) { … } } 我已经阅读了一些关于MarshallAsAttribute类的内容。 这可能是c#代码中缺少的部分吗? 这是我正在使用的vba代码: Dim udt As New UserDefinedClass Dim myArray() myArray(1) = udt myClass.Method1(myArray) myClass.Method2(myArray)

我是否需要在每个’foreach’迭代中释放COM对象?

这是(潜在的)问题: 我创建一个COM对象,然后使用’foreach’迭代它返回的集合中的每个元素。 我是否需要释放我在集合中迭代的每个元素? (参见下面的代码。)如果是这样,我想不出有效地从’finally’语句中释放它的方法,以防万一在项目被操作时出现错误。 有什么建议? private static void doStuff() { ComObjectClass manager = null; try { manager = new ComObjectClass(); foreach (ComObject item in manager.GetCollectionOfItems()) { Log.Debug(item.Name); releaseComObject(item); // <– Do I need this line? // It isn't in a 'finally' block… // …Possible memory leak? } } catch (Exception) { } finally { releaseComObject(manager); […]

在构建服务器上注册COM引用的DLL

我们正在开发一个引用几个COM库的C#应用​​程序(例如AutoIT)。 我在源控件下包含所有引用的组件,在第三方“Libs”文件夹中。 问题是COM dll在.csproj文件中没有HintPath属性,我认为必须使用regsvr32(或使用某种脚本)手动注册这些属性。 我目前正在研究创建一个将在每次构建之前运行的MSBuild脚本,但是我无法弄清楚我应该手动调用regsvr32.exe还是使用一些预定义的MSBuild任务? 目前,这是我作为测试所支持的: 这会生成我在给定文件夹中放置的DLL不是有效DLL的错误。 什么是这个问题的好方法? 编辑: 引用COM dll的项目在.csproj文件中有类似的内容: {F8937E53-D444-4E71-9275-35B64210CC3B} 1 0 0 tlbimp False 这不包括任何提示路径作为其他托管程序集,因此在构建服务器上,找不到引用的COM dll。 使用REGSVR32在构建服务器上注册COM dll时,构建成功。

如何调用基类中定义的私有COM接口的方法?

如何从派生类调用基类中定义的私有COM接口的方法? 例如,这是COM接口, IComInterface (IDL): [ uuid(9AD16CCE-7588-486C-BC56-F3161FF92EF2), oleautomation ] interface IComInterface: IUnknown { HRESULT ComMethod([in] IUnknown* arg); } 这是来自OldLibrary程序集的C#类BaseClass ,它实现了这样的IComInterface (注意接口被声明为private): // Assembly “OldLibrary” public static class OldLibrary { [ComImport(), Guid(“9AD16CCE-7588-486C-BC56-F3161FF92EF2”)] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IComInterface { void ComMethod([In, MarshalAs(UnmanagedType.Interface)] object arg); } [ComVisible(true)] [ClassInterface(ClassInterfaceType.None)] public class BaseClass : IComInterface { void IComInterface.ComMethod(object arg) { Console.WriteLine(“BaseClass.IComInterface.ComMethod”); } […]