Tag: com interop

无法从VBA实例化用C#编写的COM对象(VB6确定)

使用VS 2008,这是我的COM对象 using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Windows.Forms; namespace TestCom { [Guid(“9E5E5FB2-219D-4ee7-AB27-E4DBED8E123E”)] [ClassInterface(ClassInterfaceType.AutoDual)] [ProgId(“Test9.COMINT”)] public class TestComClass { public void Init(string userid, string password) { MessageBox.Show(string.Format(“{0}/{1}”, userid, password)); } } } 如果我构建它并在生产机器上注册如下 REGASM /CODEBASE TESTCOM.DLL 从一个简单的VB6应用程序,这工作正常 Private Sub Form_Load() Dim o As Object Set o = CreateObject(“Test9.COMINT”) o.Init “A”, “B” End […]

在非托管C ++项目中使用C#COM – > 0x7697C41F的第一次机会exception(KernelBase.dll)

我试图在非托管的Visual C ++解决方案中调用C#COM项目中的方法,但我不断收到下一个错误 First-chance exception at 0x7697C41F (KernelBase.dll) in Program.exe: 0x04242420 (parameters: 0x31415927, 0x6F310000, 0x00BBDAE8). 在下一段代码中 SalesForceNew::IMyObjectClassPtr p; p.CreateInstance(__uuidof(SalesForceNew::TestObject)); // error SalesForceNew::MyObject mo = p->getObject(1, “a”); 然而, mo的值如预期的那样(5,“aa”)。 我用这行代码导入tlb文件: #import “C:\Users\Bob\Desktop\ComTest\SalesForceNew\bin\x86\Debug\SalesForceNew.tlb” named_guids C#项目如下: 界面: using System.Runtime.InteropServices; namespace SalesForceNew { [ComVisible(true)] [Guid(“22901ACD-CA30-4D3E-B84B-73B707026AE5”)] public interface IMyObjectClass { MyObject getObject(int i, string s); } [ComVisible(true)] [StructLayout(LayoutKind.Sequential)] public struct […]

是否可以拦截(或意识到)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的答案,以及Earwicker ,他提出了一个非常简单的ATL解决方案。 然而,接受的答案是Bigtoe ,他建议将.net对象包装在VbScript对象中(我认为不诚实),有效地为VbScript问题提供了一个简单的VbScript解决方案。 谢谢大家。

通过SWIG为C#编译Quantlib

任何人都有使用SWIG的经验吗? 我目前正在研究QuantLib并发现可以使用SWIG生成C#代码。 我们正在探索使用QuantLib和专有的闭源库(可能以.Net dlls的forms提供)来创建财务function组合库的选项。 我们的想法是将这两者结合起来创建一个统一的超级库。 我已经看到了QuantLib的.Net端口 ,但它似乎没有被主动维护(并且不完全确定实际移植了多少),所以我避免使用它。 这一步的第一步是评估生成可以在任何地方使用的库的难度,即MS office应用程序(通过VBA),控制台应用程序以及服务器端(例如Web应用程序)。 我认为这涉及COM Interop,但我不知道从哪里开始,或者我是否在正确的轨道上。 我没有使用C ++的经验; 和COM是我(我现在的流行语)的一些东西,我已经釉面了。 我知道与此主题相关的相关MSDN文章。 我正在寻找以下几行的帮助: 有没有在C#中使用QuantLib的替代方案? 关于我的开发环境,我需要什么? 有没有人知道通过SWIG编译的即用型QuantLib C#库? (一等奖=对我来说工作少) 任何帮助表示赞赏 编辑:除非提供更好的答案,否则我已接受我的答案作为正确答案。

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

问题:我有一个.NET dll,我在C ++程序中使用它。 现在我必须在部署计算机上以编程方式注册dll。 我该怎么做(以编程方式!不使用regasm)? 我记得,当我曾经用C ++ dll调用VB6 dll时,我不得不使用DllRegisterServer和DllUnregisterServer。 .NET dll仍然如此吗? 看来我必须以某种方式将dllregisterserver函数添加到.NET dll中。

处理来自托管STA应用程序中的进程外COM服务器的事件

显然,来自非托管进程外COM服务器的事件的托管处理程序在随机池线程上调用,而不是在主STA线程上调用(正如我所期望的那样)。 我在回答有关Internet Explorer自动化的问题时发现了这一点。 在下面的代码中, DocumentComplete在非UI线程上触发(因此”Event thread”与调试输出中的”Main thread” )。 因此,我必须使用this.Invoke来显示一个消息框。 据我所知,此行为与非托管COM客户端不同,其中从STA线程订阅的事件会自动编组回同一个线程。 这种背离传统COM行为背后的原因是什么? 到目前为止,我还没有找到任何证实这一点的参考文献。 using System; using System.Diagnostics; using System.Threading; using System.Windows.Forms; namespace WinformsIE { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs ev) { var ie = (SHDocVw.InternetExplorer)Activator.CreateInstance(Type.GetTypeFromProgID(“InternetExplorer.Application”)); ie.Visible = true; Debug.Print(“Main thread: {0}”, Thread.CurrentThread.ManagedThreadId); ie.DocumentComplete += […]

释放临时COM对象

使用COM对象考虑以下C#代码。 MyComObject o = new MyComObject; try { var baz = o.Foo.Bar.Baz; try { // do something with baz } finally { Marshal.ReleaseComObject(baz); } } finally { Marshal.ReleaseComObject(o); } 这将释放COM对象o和baz ,但不释放由o.Foo和o.Foo.Bar的临时对象。 当这些对象拥有大量非托管内存或其他资源时,这可能会导致问题。 一个明显但丑陋的解决方案是,使用try-finally和Marshal.ReleaseComObject使代码更加混乱。 请参阅C#+ COM Interop,确定性版本 作为一种解决方法,我创建了一个帮助类 class TemporaryComObjects: IDisposable { public C T(C comObject) { m_objects.Add(comObject); return comObject; } public void Dispose() { foreach […]

如何使.NET COM对象成为单元线程?

默认情况下,.NET对象是自由线程的。 如果通过COM封送到另一个线程,它们总是被封送到自己,无论创建者线程是否是STA,并且无论其ThreadingModel注册表值如何。 我怀疑,他们聚合了Free Threaded Marshaler (有关COM线程的更多细节可以在这里找到)。 我想让我的.NET COM对象在封送到另一个线程时使用标准的COM marshaller代理。 问题: using System; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using System.Windows.Threading; namespace ConsoleApplication { class Program { static void Main(string[] args) { var apt1 = new WpfApartment(); var apt2 = new WpfApartment(); apt1.Invoke(() => { var comObj = new ComObject(); comObj.Test(); IntPtr pStm; NativeMethods.CoMarshalInterThreadInterfaceInStream(NativeMethods.IID_IUnknown, comObj, out […]

与C#和VBA并排的COM Interop

我不是在谈论从C#调用VBA COM ……反过来说! 我想要做的是在MS Access中使用VBA调用C#库而无需注册DLL。 我一直在玩并排互操作一段时间没有成功,最后我发现mdb.manifest可能不是exe.manifest的可接受的替代品(可能很明显,我知道,但我我试图保持乐观。 我的问题:是否有可能让VBA加载并排的COM组件? 或者,是否有另一种方法在Access中使用未注册的C#库? (在您提出问题之前,我的理由是:我绝对无法访问我的客户端的Windows注册表 – 这就是为什么它首先在Access中编写。而且,我需要在一个实现相同的function。 C#应用程序很快,而不是两次)。

Interop中将属性公开为.NET中的变体

我正在.NET中创建一个包装类(VB.NET,因为它发生但与C#同样相关),它暴露给COM,我试图包装的其中一个属性是Variant。 我以为我只能使用一个Object,但是我收到一个错误: Public Property FieldValue([vFieldID As Object = -1]) As Object不能作为属性’Let’向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 我的属性实际上从数据库返回一个值,该值可以是整数,字符串,日期等,因此它不是 COM方面的对象。 是否有任何解决方法允许属性让?