Tag: com

System.Runtime.InteropServices.ComTypes.IStream到System.IO.Stream

在.NET 3.0项目中,我需要通过P / Invoke进行一些调用(特别是对于PrintTicket Provider函数,如PTConvertPrintTicketToDevMode())。 该框架具有COM IStream接口的托管定义: System.Runtime.InteropServices.ComTypes.IStream 我需要它作为System.IO.Stream,以便我可以轻松地使用.NET类(如XmlDocument)和这些导入函数的输出。 但是,除了一次读取和写入一个字节块之外,我无法看到一种不那么痛苦的方法将此来回转换为System.IO.Stream 。 对于看似非常普遍的任务来说,这似乎太过愚蠢了。 或者我是以错误的方式去做的? 我将PTConvertPrintTicketToDevMode ()导入为: [DllImport(“prntvpt.dll”)] public static extern int PTConvertPrintTicketToDevMode(IntPtr hProvider, IStream pPrintTicket, EDefaultDevmodeType baseDevmodeType, EPrintTicketScope scope, IntPtr pcbDevmode, out IntPtr ppDevmode, [MarshalAs(UnmanagedType.BStr)]out String pbstrErrorMessage);

使用C#中的参数打包IDispatch调用(使用DISPPARAMS)

我正在使用Invoke对支持IDispatch的旧COM对象进行后期绑定。 这似乎是必要的,因为.NET的Type.GetMethod Type.InvokeMember似乎不适用于这些对象。 以下代码适用于从对象获取属性,调用者将属性名称作为字符串传递,以获取具有后期绑定的属性值。 该类在其构造函数中获取一个对象,并将this.idisp(和this.lcid)设置为该对象的接口指针(Critiques welcome!) public object InvokeGet(string propertyName) { int id = GetDispID(propertyName); IntPtr[] pArgErr = default(IntPtr[]); object pVarResult; System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams = default(System.Runtime.InteropServices.ComTypes.DISPPARAMS); System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo = default(System.Runtime.InteropServices.ComTypes.EXCEPINFO); Guid guid = new Guid(); int result = this.idisp.Invoke(id, ref guid, (uint)this.lcid, (ushort)System.Runtime.InteropServices.ComTypes.INVOKEKIND.INVOKE_PROPERTYGET, ref pDispParams, out pVarResult, ref pExcepInfo, pArgErr); if (result != 0) { throw […]

成功注册了COM DLL,但不能使用类方法

我使用regasm.exe注册了一个COM DLL,现在我正在尝试编写一个使用DLL中的类的VBA脚本。 该DLL是ExcelDataReaderLibrary.dll 。 在C#源代码中,该类描述如下(包括来自此库的代码): using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.Data; using Excel; namespace ExcelDataReaderLibrary { public class ExcelDataReader { public void readSheet(string filePath,string sheetName,string outPath) { // code for method here } } } 我的assembly.cs文件包括以下内容: [assembly: ComVisible(true)] [assembly: Guid(“b1e78f8f-9ab0-46d8-beac-b843656aacdb”)] 当我打开VBA编辑器并转到引用时,我看到ExcelDataReaderLibrary的引用。 请注意,与此引用关联的文件是ExcelDataReaderLibrary.tlb ,而不是ExcelDataReaderLibrary.dll 。 检查此引用后,我想在VBA中创建和使用ExcelDataReader对象,如下所示: Sub x() […]

使用.NET互操作编译VB6应用程序,仅在我的机器上编译时运行

我最近在.NET(Visual Studio 2008,项目目标是.NET 2.0)中开发了一个用于VB6应用程序的互操作用户控件。 该程序集公开了1个控件,1个类,以及一些枚举和结构。 我使用此处的Interop Forms Toolkit 2.0项目模板的C#转换开发了它。 程序集具有强名称,并安装在GAC中,并使用以下脚本在regasm中注册: @”C:\gacutil.exe” /i “C:\Program Files\AppName\Control.dll” /f @”C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\regasm.exe” “C:\Program Files\AppName\Control.dll” /tlb:”C:\Program Files\AppName\Control.tlb” 问题:当我在我的机器上编译VB6应用程序时,它将在任何其他机器上运行(当然,安装了控件)。 但是,当应用程序在不同的计算机上编译时,它将在该计算机上运行,​​但不会在任何其他计算机上运行。 当我说它没有运行时,我的意思是你试图运行它,绝对没有任何反应。 我使用OleView来检查我的机器和其他机器上的控件,并且所有GUID在类型信息中都是相同的。 唯一的区别是一个有行importlib(“stdole2.tlb”)而另一个有importlib(“STDOLE2.TLB”)。 我的机器有:Visual Studio 6.0 sp6,VB6互操作用户控件模板,Windows SDK 6.0和6.0A,Visual Studio 2008 sp1。 这台机器是有效的。 同事机:Visual Studio 6.0 sp6,Visual Studio 2005 另一台机器:Visual Studio 6.0 sp6,Visual Studio 2008. 2008今天早上安装了这个并没有解决问题。 我如何让这些其他机器正确编译VB6应用程序,以便它运行在编译它的机器以外的机器上? (在评论中提出更多信息请求,我将对其进行编辑以提供答案。) 编辑: 关于注册控件的权限提出了建议。 我想澄清控制似乎运作良好。 我在工作的机器和不工作的机器上以完全相同的方式注册它。 当引用控件的VB6应用程序在我自己的机器上编译时,问题就会出现。 […]

C#COM Cross Thread

我们正在开发一种控制科学测量设备的软件。 它提供了一个COM接口定义了几个函数来设置测量参数,并在测量数据时触发事件。 为了测试我们的软件,我正在实现该设备的模拟。 com-object运行一个循环,定期触发事件。 客户端应用程序中的另一个循环现在应该使用给定的函数设置com-simulator。 我创建了一个用于测量参数的类,在设置新测量时将对其进行实例化。 // COM-Object public class MeasurementParams { public double Param1; public double Param2; } public class COM_Sim : ICOMDevice { public MeasurementParams newMeasurement; IClient client; public int NewMeasurement() { newMeasurment = new MeasurementParam(); } public int SetParam1(double val) { // why is newMeasurement null when method is called from client […]

System.Windows.Forms.Timer没有触发

我想使用System.Windows.Forms.Timer来确保在我正在创建的excel插件的UI线程上触发事件。 我按如下方式构建计时器: private System.Windows.Forms.Timer _timer; private void ThisAddIn_Startup(object sender, System.EventArgs e) { Debug.WriteLine(“ThisAddIn_Startup:” + Thread.CurrentThread.ManagedThreadId); _timer = new System.Windows.Forms.Timer(); _timer.Tick += new EventHandler(TimerEventHandler); _timer.Interval = 500; } 计时器由我正在使用的库中的COM事件触发: private void OnEvent() { _timer.Start(); } 然后我希望_timer在_timer时调用以下方法: public void TimerEventHandler(object sender, EventArgs args) { _timer.Stop(); Debug.WriteLine(“Tick: ” + Thread.CurrentThread.ManagedThreadId); } 据我所知,当我在Addin线程中创建计时器时,即使它是从另一个线程启动的(在这种情况下是COM事件),它应该触发它创建的线程,即插件线程。 但是,这不会发生。 我已经在我过去编写的RTDServer实现了这个确切的机制( 如Kenny Kerr所述 ),并且它按预期工作,但此场景中的_timer永远不会_timer 。 […]

从C#开始,打开一个任意应用程序

相关问题[stackoverflow] 在这里 。 我正在努力做到这一点,但我想更进一步。 我想使用文件类型的默认编辑器打开任意文件。 从那时起,我希望允许我的用户像往常一样与文件进行交互,或者继续在我的应用程序中工作。 扩展名是用户完成编辑后发生的事情。 有没有办法可以从外部应用程序捕获一个close(并且理想的保存)事件,并将其用作触发器来执行其他操作? 就我的目的而言,跟踪外部应用程序的关闭就行了。 我可以在具体情况下这样做。 例如,我可以从我的应用程序中打开Word实例并跟踪我的应用程序感兴趣的事件。 但是,我想将我的应用程序与Word分离。我希望允许我的用户使用他们选择的任何文档编辑器,然后在后台管理正在编辑的文件的存储。

用.NET实现替换C ++ ActiveX组件?

我有现有的托管和非托管软件,使用第三方提供的ActiveX组件来执行某些通信,但现在要求通过我的应用程序路由此通信。 理想情况下,我将能够安装一个.NET组件,它将公开完全相同的接口,并可用作替代品。 但是,我遇到了对COM的理解,这无疑是最小的。 如何最好地确保我的接口实现与现有对象100%二进制兼容? 如何确保应用程序使用我的接口实现而不是遗留实现? 这只是注册我的实现和取消注册遗留实现的问题吗? 我如何确保它是“插入式”替代品,并且不需要更改现有软件? 如何确保非托管代码可以毫无问题地使用它? 注意:我可以要求使用.NET 4.0,如果这样可以使事情变得更简单。 编辑: Bounty将被移动到此处如何调试使用我的.NET ActiveX控件的VB6应用程序为什么不注册事件? 2天后。

C#在线程之间编组COM对象

我对C#marshal在线程之间是否有COM对象感到非常困惑。 为此,我有一个应用程序,它以任务并行方式加载一组文件。 我正在使用StaTaskScehduler使用COM对象加载文件。 加载COM对象后,我将对象存储在中央列表中。 然后,我再次使用STATaskScheduler尝试对此数据执行一些处理。 但是在这一点上我遇到了一个问题。 我收到如下例外情况: An unhandled exception of type ‘System.Runtime.InteropServices.InvalidComObjectException’ occurred in MadCat.exe Additional information: COM object that has been separated from its underlying RCW cannot be used 现在我的理解是我收到此错误,因为该对象尚未编组到新线程中。 我以为这是C#为你做的事情? 如何在一个线程中创建一个公寓线程COM对象,然后从另一个线程使用它? 我在这里吠叫错了吗? 我甚至不能使用Sta公寓作为我的主题吗? 我可以保证对象永远不会同时从多个线程访问。 任何想法都非常感激。 编辑 :COM对象定义如下: [ coclass, threading( apartment ), vi_progid( [Namespace.Class] ), progid( [Namespace.Class].6 ), version( 6.0 ), uuid( […]

在C#中动态加载和使用COM对象

我有一个C#项目,如果它安装在客户端的机器上,我想访问MS outlook。 “访问前景”部分是通过引用Outlook COM对象并从那里开始完成的。 我的问题现在是“如果已安装”部分。 目前,我的项目没有在没有安装outlook的机器上编译,所以我假设我不得不引用outlook组件,而是在检测到outlook存在后动态加载和使用它,但我还没有找到了一种方法来做到这一点。 我是否正确,是否有人对如何做到这一点有任何暗示? 谢谢。 编辑:已解决。 根据Hans Passant在关于使用办公室PIA的一条评论中给出的建议,certificate是阻力最小的路径。 在我的办公室机器上获得PIA时遇到了一些困难,但是使用这个问题的接受答案就克服了这个问题。