我有一个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退出,CoCreateInstance调用超时。
MyService.exe未作为服务安装,但通过/ RegServer注册
MyServiceTest.exe调用CoCreateInstance,并调用MyService WinMain。 MyService.exe在登录的用户帐户(不是LOCALSYSTEM)下实例化。可执行文件成功运行,但不是作为服务运行,这不是所需的行为。尽管没有作为服务运行,CoCreateInstance()调用成功,我得到一个有效的接口指针,通过它我可以调用MyService COM函数。
MyService.exe未作为服务安装,通过/ RegServer注册,并且已在运行(例如在方案2中成功启动后)
MyServiceTest.exe调用CoCreateInstance,并在登录的用户帐户下再次实例化MyService.exe的新实例。对CoCreateInstance的每次后续调用都会继续此行为。
我希望的行为是我可以将MyService.exe安装为服务,CoCreateInstance将启动服务器,或者如果服务已在运行,则连接到当前的MyService.exe实例。据我所知,上面的代码应该是这样的。我错过了什么?
似乎服务在LOCALSYSTEM下运行,而简单的RegServer替代方案在本地用户下运行可能是相关的,但我不确定这是否是问题。
CoInitializeSecurity的服务端调用是:
HRESULT hr = CoInitializeSecurity(0,
-1,
0,
0,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
0,
EOAC_NONE,
0);
我做错了什么?
P.S。一旦启动,MyService.exe就不应该退出,因为它在Run()函数中包含WaitForSingleObject(),它等待外部信号(也在OnStop()中设置,因此SCM可以暂停服务)。这就是MyServiceTest.exe完成后MyService.exe仍然存在的原因。这是期望的行为(对于服务,它应该运行它)。
答案 0 :(得分:1)
如果您已经涵盖了这一点,请原谅我:
运行DCOMCNFG.EXE。
深入了解组件服务\计算机\我的电脑\ DCOM配置。
找到您的组件,右键单击并激活“属性”。
在“标识”选项卡中,确保将COM组件配置为在运行该服务的同一标识下运行。
答案 1 :(得分:1)
事实证明,罪魁祸首是服务的注册方式。为了让类将控制应用程序作为服务启动,控制应用程序需要将条目添加到注册表中,以便将其识别为本地服务器,即:
(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 value
LocalServer32 overload in CoClass CLSID
Specifying AppID for CLSID