CoCreateInstance没有启动或连接atlcom服务
CoCreateInstance does not start or connect to ATL COM service
我有一个ATL COM服务exe (MyService.exe),它编译和运行良好。如果我安装这个服务(通过MyService.exe/service),它就成功地安装到SCM中了。我可以通过SCM启动服务,它在LOCALSYSTEM帐户下运行良好。
当我尝试创建由服务定义的COM类的实例时,问题出现了。我的测试工具应用程序(MyServiceTest.exe)调用以下内容:
::CoInitialize(NULL);
::CoInitializeSecurity(NULL,
NULL,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE,
NULL);
ATL::CComPtr<IMyServiceInterface> pInterface;
HRESULT hr = CoCreateInstance(CLSID_MyServiceInterface, NULL, CLSCTX_LOCAL_SERVER, IID_IMyServiceInterface, reinterpret_cast<void**>(&pInterface));
在调用CoCreateInstance时,根据MyService.exe的安装方式,会发生一些不同的事情:
- MyService.exe使用/Service命令行安装:
MyServiceTest.exe调用CoCreateInstance, MyService WinMain被调用。然后调用CAtlServiceModuleT::Start,它确定可执行文件已通过命令行选项"-Embedding"启动。它确定它作为服务安装,并以此调用::StartServiceCtrlDispatcher()。此调用失败,错误码为1063 (ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)。根据MS:
"如果程序作为控制台应用程序而不是作为服务运行,则返回此错误。如果程序将作为控制台应用程序运行以进行调试,则对其进行结构调整,以便在返回此错误时不调用特定于服务的代码。"
调用失败,MyService.exe退出,CoCreateInstance调用超时。
MyService.exe不是作为服务安装的,而是通过/RegServer
注册的MyServiceTest.exe调用CoCreateInstance, MyService WinMain被调用。MyService.exe在登录的用户帐户(不是LOCALSYSTEM)下实例化。可执行文件成功运行,但不是作为服务运行,这不是期望的行为。尽管没有作为服务运行,CoCreateInstance()调用成功,我得到一个有效的接口指针,通过它我可以调用MyService COM函数。MyService.exe不是作为服务安装的,是通过/RegServer注册的,并且已经在运行(例如在场景2中成功启动后)
MyServiceTest.exe调用CoCreateInstance, MyServiceTest.exe的一个新实例被实例化,再次在登录的用户帐户下。
我想要的行为是,我可以安装MyService.exe作为一个服务,CoCreateInstance将启动服务器,或连接到当前的MyService.exe实例,如果服务已经运行。据我所知,上面的代码应该是这样的。我错过了什么?
服务在LOCALSYSTEM下运行,而简单的RegServer在本地用户下运行的事实似乎是相关的,但我不确定这是否是问题所在。
服务端对coinitializessecurity的调用是:
HRESULT hr = CoInitializeSecurity(0,
-1,
0,
0,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
0,
EOAC_NONE,
0);
我做错了什么?
注:MyService.exe一旦启动就不应该退出,因为它在Run()函数中包含WaitForSingleObject(),该函数正在等待外部信号(也在OnStop()中设置,因此SCM可以停止服务)。这就是为什么MyServiceTest.exe完成后MyService.exe仍然存在的原因。这是期望的行为(对于服务来说,它应该是这样运行的)。
如果你已经讲过了,请原谅我:
DCOMCNFG.EXE运行。
钻取组件服务 Computers My Computer DCOM Config.
找到你的组件,右键单击并激活"属性"。
在Identity选项卡中,确保将COM组件配置为在服务运行的同一身份下运行。
事实证明,罪魁祸首是服务的注册方式。为了使一个类作为服务启动它的控制应用程序,控制应用程序需要在注册表中添加条目,以便将其识别为本地服务器,即:
(MyService.rgs)HKCR
{
NoRemove AppID
{
ForceRemove {6E5B1E7E-3340-4553-A356-76F1C3543452} = s 'MyService'
{
val LocalService = s 'MyService'
val ServiceParameters = s '-Service'
}
'MyService.EXE'
{
val AppID = s {6E5B1E7E-3340-4553-A356-76F1C3543452}
}
}
}
AppID在MyService.rgs中指定。
这会导致注册表中的以下布局:
HKCR
AppID
{6E5B1E7E-3340-4553-A356-76F1C3543452} (Contains LocalService, ServiceParameters REG_SZ's)
MyService.EXE (Contains AppID REG_SZ)
CLSID
{MyServiceInterface GUID} (Contains MyService.EXE AppID)
相关链接:
LocalService价值
在CoClass CLSID中重载LocalServer32
为CLSID指定AppID
- 当套接字连接断开时检测C/C++Unix
- 无法在windows上使用mingw将sqlite3与c连接
- 到连接组件算法的问题(递归)
- QTcpSocket在不阻塞GUI的情况下重新连接到服务器
- 无法在C++中建立与MySQL数据库的连接
- PC中的程序和PHONE中的本机描述应用程序之间的数据连接
- 在Qt Creator中,如何在连接到正在运行的进程后查看控制台输出
- 连接 dockerized 模型和 dockerized 数据库时出现"无法 SQLConnect"错误
- 使用 bfs 解决连接组件问题时得到错误的答案
- 在C++的两个字符串中连接以逗号分隔的唯一值
- 如何修复valgrind启动时的致命错误(与libc6-dbg和libc6-dbg:i386连接)
- C++应用程序 MySQL odbc 数据库连接错误:在引发"otl_tmpl_exception<>"实例后终止调用
- OSX蓝牙打开RFCOMMChannelAsync声称已连接,但未建立连接,并且从未调用过委托
- 在 libcurl 连接池中预创建连接
- 套接字连接"Operation not permitted"错误,甚至使用升压/平发器根.cpp
- libcurl 和 DNS ttl 中的内部连接管理
- 如何应用 libcurl 的持久连接选项
- 提升 ASIO - io_service 不要等待连接到线程
- WinSock2:connect() 提供"连接被拒绝"
- CoCreateInstance没有启动或连接atlcom服务