我在COM服务器中编写了几个Excel UDF.我想获得按fx时获得的标准帮助(" 插入函数"对话框).是的,我可以看到我的COM服务器列在类别下拉列表中,但是
这是我得到的跛足:
插入函数对话框http://www.iwebthereforeiam.com/files/Insert%20function%20dialog.gif
Excel函数参数对话框http://www.iwebthereforeiam.com/files/Function%20Arguments%20dialog.gif
是否有.NET属性我可以把方法传递给Excel?
(我发现在ExcelDNA中看起来很容易,但我不会那样做.模仿govert的代码[自定义属性,某种类型的加载器等]看起来很难.)
如果您以前没有使用Excel + COM服务器,这里有一些有用的资源可以加快速度:
以前的StackOverflow问题:
如何在VB.NET中安装并在Automation Servers列表中注册的用于Excel的COM Server for Excel?
如何将COM暴露的.NET项目添加到VB6(或VBA)引用对话框?
其他资源:
在.NET中为Excel编写用户定义的函数
构建和部署.NET COM程序集
在C#中编写自定义Excel工作表函数
编辑2009-10-20 14:10
我试着打电话Application.MacroOptions
给Sub New()
.
Cannot register assembly "...\Foo.dll". Exception has been thrown by the target of an invocation.
我怀疑这对于MacroOptions和Charles推荐的更复杂的路线都是一个问题.
编辑2009-10-20 14:55
从好的方面来说,Mike建议创建一个实现的接口确实可以消除暴露的烦人的额外方法.
编辑2009-10-20 15:00
我正在通过将Windows消息直接发送到HWND并调用自动化应用程序公开的COM服务器来实现一些自动化.
如果有多个实例正在运行,我需要能够确定COM服务器的进程ID,这样我可以使用COM调用命中相同的实例作为我发送Windows消息的实例.
我可以使用正在运行的对象表枚举所有正在运行的COM服务器,并为所有这些服务器返回monikers,但COM对象本身不会公开任何可用于获取窗口句柄,线程ID,进程ID或任何类型的方法.
有没有办法弄清楚,基于名字对象或名字对象的实际绑定COM对象,COM服务器的进程ID是什么?
谢谢!
我有一个模块,可以创建一个包含ActiveX控件的无模式对话框。该模块是MFC EXE应用程序的一部分,并且对话框的创建工作正常。最近,我将模块移到ATL / COM服务器中,并将对话框资源从EXE复制到COM服务器中。尝试使用CDialog::Create()
错误创建无模式对话框时发生。
我调试到CDialog::Create
并注意到它的失败,::CreateDialogIndirect()
返回NULL
和GetLastError
回报0
。我在对话框资源属性中将“ No Fail Create”标志设置为True,并获得了更多有关错误的详细信息。问题发生在该对话框的DoDataExchange()
的中DDX_Control
宏。这会CDataExchange::PrepareCtrl()
使用控件的资源ID 调用,如下所示:
HWND CDataExchange::PrepareCtrl(int nIDC)
{
ASSERT(nIDC != 0);
ASSERT(nIDC != -1); // not allowed
HWND hWndCtrl;
COleControlSite* pSite = NULL;
m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl);
if (hWndCtrl == NULL)
{
// Could be a windowless OCX
pSite = m_pDlgWnd->GetOleControlSite(nIDC);
if (pSite == NULL)
{
TRACE(traceAppMsg, 0, "Error: no data exchange control with ID 0x%04X.\n", nIDC);
ASSERT(FALSE);
AfxThrowNotSupportedException(); …
Run Code Online (Sandbox Code Playgroud) 我是制作COM服务器和使用Python的COM的新手,所以我想澄清一些我找不到明确答案的东西:
正确为COM服务器创建GUID
我生成:
手动创建我的COM服务器的GUID,从那时起复制它并将#用于服务器?因此,当我分发应用程序时,其他用户将使用我在开发期间创建的相同GUID.
每次初始化应用程序或COM服务器对象时都有新的GUID?
基于每台计算机的新GUID,在初始设置期间只有一次然后让应用程序保存GUID#,并且在将来加载时它会从用户设置文件中提取#?
示例场景1:
i) print(pythoncom.CreateGuid()) #in interpreter
ii) _reg_clsid_ = copy above GUID into your app
Run Code Online (Sandbox Code Playgroud)
示例场景2:
i)_reg_clsid_ = pythoncom.CreateGuid()
Run Code Online (Sandbox Code Playgroud)
示例场景3:
if self.isfile = os.path.isfile(url):
load_previous_generated_GUID(url)
else:
#first time running application or setup file is missing
GUID = pythoncom.CreateGuid()
save_GUID_to_setup_file(GUID)
Run Code Online (Sandbox Code Playgroud)
我可以使用GUID来跟踪程序/ COM服务器版本吗?
如果上面的场景#1是正确的那么:当我进行升级时,我可以测试旧的GUID,以便我可以正确地与它进行交互?
TODO:如何从Python和/或VBA获取COM服务器的GUID?
在我的IContextMenu
COM服务器实现中,QueryContextMenu
调用了gets(可以通过日志记录查看),但InvokeCommand
没有.这是QueryContextMenu
:
HRESULT ContexMenuImp::QueryContextMenu(HMENU hmenu,UINT indexMenu,UINT idCmdFirst,
UINT idCmdLast,UINT uFlags)
{
if (uFlags & CMF_DEFAULTONLY) {
// shouldn't handle this situation:
LOG("IContextMenu::QueryContextMenu: (...,CMF_DEFAULTONLY)");
return MAKE_HRESULT(SEVERITY_SUCCESS,FACILITY_NULL,0);
}else if (InsertMenuItem(hmenu,indexMenu,TRUE,&globals.menuItemInfo) == FALSE){
// error occurred:
LOG("IContextMenu::QueryContextMenu: Error: %d",GetLastError());
return MAKE_HRESULT(SEVERITY_SUCCESS,FACILITY_NULL,0);
} else{
// the desired situation: add item to the menu:
LOG("IContextMenu::QueryContextMenu(hMenu,indexMenu:%u,idCmdFirst:%u,idCmdLast:%u,0x%x): All set...",
indexMenu,idCmdFirst,idCmdLast,uFlags);
return MAKE_HRESULT(SEVERITY_SUCCESS,FACILITY_NULL,1/*handle only a single item*/);
}
}
Run Code Online (Sandbox Code Playgroud)
知道为什么吗?
我有一个进程外com服务器,指定CLSCTX_LOCAL_SERVER作为上下文,并指定REGCLS_MULTIPLEUSE作为连接类型.这导致单个服务器进程被来自多个客户端的多个调用重用.
我现在想要对服务器进行一些更改,遗憾的是,这些更改无法与客户端共享的单个进程一起工作(有这样的原因,但是它们已经很长时间了).我知道您可以将服务器设置为使用REGCLS_SINGLEUSE作为连接类型,这将为每次调用的OOP服务器创建一个新进程.这解决了我的问题,但在流程使用方面是不起作用的; 短时间内的多次呼叫会导致许多进程,并且这种特定的服务器可能会经常受到惊吓.
有没有人碰巧知道混合这两种连接类型的机制?基本上我想要的是每个调用进程一个服务器进程.(即,客户端1创建一个进程,该进程被重用于该客户端的后续调用.客户端2尝试调用服务器,并创建一个新进程).我怀疑我可以通过强制REGCLS_SINGLEUSE服务器在客户端永久保持打开来实现它,但这既不优雅也不可能(因为我无法更改其中一个客户端).
思考?
更新 正如预期的那样,似乎没有办法做到这一点.如果时间和资源允许,我很可能将其转换为In-Proc解决方案.但就目前而言,我不得不采用任何调用客户端所使用的新行为.幸运的是,这种变化的影响非常小,并且客户可以接受.我稍后会研究更激烈和适当的变化.
注意 我已经将Hans的回复标记为答案,因为事实上它确实解决了维护OOP解决方案的问题.我只是没有能力实现它.
CAL