假设我有一个COM对象,用户可以通过以下呼叫访问:
Set s = CreateObject("Server")
Run Code Online (Sandbox Code Playgroud)
我希望能够做的是允许用户为对象指定事件处理程序,如下所示:
Function ServerEvent
MsgBox "Event handled"
End Function
s.OnDoSomething = ServerEvent
Run Code Online (Sandbox Code Playgroud)
这是可能的,如果是这样,我如何在我的C++类型库(特别是BCB 2007)中公开它?
我正在开发一个C#程序集,它将通过COM从Delphi 7(iow,原生win32,而不是.net)应用程序调用.
到目前为止,它似乎工作.我已经导出了一个TLB文件,将其导入到我的Delphi项目中,我可以创建我的C#对象并调用它的函数.
这很好,但很快我就真的想在运行时使用Visual Studio来调试C#代码.设置断点,逐步执行代码,所有这些.
在创建COM对象后,我尝试打破Delphi代码,然后寻找VS附加到的进程,但我找不到.
有没有办法设置VS2008这样做?我更愿意只能点击f5并让VS启动Delphi可执行文件,等待调用C#代码,然后将其自身附加到它上面.但我认为我可以手动附加到进程.
请不要告诉我,我必须使用MessageBox.Show等.
我需要将CString实例转换为正确分配的实例并将其BSTR传递BSTR给COM方法.要拥有为ANSI和Unicode编译和工作的代码我CString::AllocSysString()用来将任何格式转换CString为Unicode BSTR.
由于没有人拥有返回的BSTR,我需要处理它并在以尽可能最安全的方式完成调用之后以尽可能少的代码完成调用.
目前我ATL::CComBSTR用于终身管理:
ATL::CComBSTR converted;
converted.Attach( sourceString.AllocSysString() ); //simply attaches to BSTR, doesn't reallocate it
interface->CallMethod( converted );
Run Code Online (Sandbox Code Playgroud)
我不喜欢的是我需要两个单独的语句来构造ATL::CComBSTR转换结果的绑定.
有没有更好的方法来完成相同的任务?
我用C#昨天创建了一个COM对象,导致我的VS 2010项目的bin/release目录中有三个文件(comclass.dll,comclass.pdb和comclass.tlb).现在,当我在项目中构建解决方案时,VS会在开发PC上自动为我注册该类,我可以从Powershell访问COM对象及其方法.但是,当我将这三个文件复制到另一台机器并尝试使用regsvr32注册dll时,它告诉我
模块"comclass.dll"已加载但未找到入口点DllRegisterServer.
确保"comclass.dll"是有效的DLL或OCX文件,然后重试.
使用.tlb文件中regasm的/tlb参数给我一个类似的消息.所以我有点难过.有谁知道我应该怎么从这里开始?
我正在通过开发现有应用程序的扩展 COM.
要扩展的应用程序的当前接口允许创建自定义属性窗口并在该应用程序内使用它们.
现在,我正在使用.NET这个目的,并有一些奇怪的问题:
extensionForm = new Form();
extensionForm.SetBounds(0, 0, 100, 100);
extensionForm.Controls.Add(new Button());
ExApplAPI.AddCustomPropertyWindow(extensionForm.Handle.ToInt32(), "Ololo");
Run Code Online (Sandbox Code Playgroud)
正如你在下面看到的那样,属性表实际上已经扩展,但在那之后,一些奇怪的事情开始发生.

基本上,如果我切换到Ololo选项卡,然后返回到任何其他3个选项卡(Attributes,Drawing或Services),应用程序将冻结.我也知道冻结发生在一些非托管代码块中.
另一个有趣的事实是,如果我不写extensionForm.Controls.Add(new Button()) (有或没有暂停/恢复布局调用),一切正常.因此,如果最近构建的表单上没有控件(按钮或任何其他),则它不会冻结.
这是冻结之前窗口Spy++上的日志Ololo(最后一条消息是WM_CTLCOLORBTN,在应用程序冻结之后):

Ololo到其他选项卡然后Ololo再次切换到选项卡时才会发生冻结.那么 - 在这种情况下帮助我的任何想法/类似问题解决/等?
我想开发一个兼容Windows XP SP2(32位)和Windows 7 64位的shell扩展(上下文菜单处理程序).
是否可以在64位Windows中运行32位shell扩展,或者是否必须将shell扩展移植/重建为64位才能在Windows 7 64位中使用?
在64位操作系统中使用32位shell扩展是否存在任何缺点/已知问题?
32位应用程序运行在64位Windows就好了,但我不知道外壳扩展,因为如果我的理解是正确的,外壳扩展是在进程内加载到浏览器进程内COM服务器,这应该是一个64 64位Windows中的位进程...还是为在64位操作系统中运行的32位shell扩展提供的"32位仿真"形式?
当建立COM DLL文件,为什么要像出口DllGetClassObject,DllCanUnloadNow,DllRegisterServer,DllUnregisterServer,等标注PRIVATE在EXPORTS相关的部分.DEF文件?
我在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)将一个asyn回调(新线程)发送到c ++层,该层使用ObjectBinder对象向CLI发送回调用.现在我们在ObjectBinder对象的CLI层中.但是App域已被更改(在WCF或NUNIT或任何其他创建它自己的App域的服务的情况下,在编译时不知道).现在我想访问存储在gcroot中的托管Receiver对象,以便将回调发送回C#,但它给出了APP DOMAIN错误.
我也尝试过IntPtr和IUnknown*而不是gcroot与Marshal :: GetIUnknownForObject和Marshal :: GetObjectForIUnknown但是得到相同的错误.
我有一对使用相同COM接口的库.在一个库中,我有一个实现该接口的类.另一个库需要一个实现接口的对象.
但是两个库都有自己的接口定义.两者略有不同,但基本上是相同的界面.
所以我尝试将它们放在如下:
Library2.Interface intf = (Library2.Interface)impl;
Run Code Online (Sandbox Code Playgroud)
但这引起了例外.如果我执行以下操作:
Library1.Interface intf = (Library1.Interface)impl;
Run Code Online (Sandbox Code Playgroud)
然后它没有问题,但我不能再将类传递给Library2.
我天真地假设两个具有相同GUID的接口都可以防止这是一个问题,但我似乎错了.有谁知道如何在两个库之间进行转换?也许是通过某种元帅?
我正在尝试在一个线程中使用COM接口.从我所读到的,我必须CoInitialize/CoUninitialize在每个线程中调用.
虽然这很好用:
procedure TThreadedJob.Execute;
begin
CoInitialize(nil);
// some COM stuff
CoUninitialize;
end;
Run Code Online (Sandbox Code Playgroud)
当我将调用移动到构造函数和析构函数时:
TThreadedJob = class(TThread)
...
protected
procedure Execute; override;
public
constructor Create;
destructor Destroy; override;
...
constructor TThreadedJob.Create;
begin
inherited Create(True);
CoInitialize(nil);
end;
destructor TThreadedJob.Destroy;
begin
CoUninitialize;
inherited;
end;
procedure TThreadedJob.Execute;
begin
// some COM stuff
end;
Run Code Online (Sandbox Code Playgroud)
我得到EOleException:CoInitialize没有被称为异常,我不知道为什么.