玩转Windows服务系列——无COM接口Windows服务启动失败原因及解决方案

原文:玩转Windows服务系列——无COM接口Windows服务启动失败原因及解决方案

将VS创建的Windows服务项目编译生成的程序,通过命令行 “服务.exe -Service”注册为Windows服务后,就可以通过服务管理器进行管理了。

问题

通过服务管理器进行启动的时候,发现服务无法启动,提示错误

由于程序代码是由VS的项目模板生成的,生成后直接编译为Debug版,然后通过命令行进行注册,期间并没有修改过任何代码。

难道是只有Release版本才能通过服务管理器启动吗。于是将Release版注册为服务,通过服务管理器启动,仍然会报同样的错误。

由于服务比较特殊,应该会在Windows的事件管理器中留下日志,经查看,日志为

可以看到系统日志中并无异常。

问题还不只如此,当Debug版本通过 RegServer 注册后,程序也是启动后立即停止。

既然如此,那就开始使用神器——单步调试。

启动失败原因

Window服务程序启动后,会在WinMain方法中调用一个Run方法

HRESULT Run(_In_ int nShowCmd = SW_HIDE) throw()
{
    HRESULT hr = S_OK;

    T* pT = static_cast<T*>(this);
    hr = pT->PreMessageLoop(nShowCmd);

    // Call RunMessageLoop only if PreMessageLoop returns S_OK.
    if (hr == S_OK)
    {
        pT->RunMessageLoop();
    }

    // Call PostMessageLoop if PreMessageLoop returns success.
    if (SUCCEEDED(hr))
    {
        hr = pT->PostMessageLoop();
    }

    ATLASSERT(SUCCEEDED(hr));
    return hr;
}

而Run方法中会调用pT->RunMessageLoop()方法,来进行一个While循环,从而阻止WinMain方法返回,造成程序结束。

经过调试,发现执行时,pT->PreMessageLoop 方法返回了S_FALSE,由于RunMessageLoop方法前有一个判断,所以此方法没有执行,从而造成程序启动便立即停止。

而真正造成PreMessageLoop方法返回S_FALSE的原因是

hr = pT->RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED);

调用RegisterClassObjects方法,返回了S_FALSE,而RegisterClassObjects方法又调用了AtlComModuleRegisterClassObjects方法,实际上是在注册Com相关的东西,而由于程序是由VS创建的默认代码编译的,并未添加任何Com接口,所以就会返回S_FALSE,即注册失败。

解决方案

找到了问题的原因了,那么也就相对好解决了。

既然程序中,并没有使用到Com相关的东西,那么就干脆跳过RegisterClassObjects方法的调用。

由于PreMessageLoop方法中通过宏_ATL_NO_COM_SUPPORT,可以决定是否跳过RegisterClassObjects的调用,所以只需要在预处理器中或者代码中定义这个宏即可。

代码如下

#define _ATL_NO_COM_SUPPORT

或者通过预处理器来定义

系列链接

玩转Windows服务系列——创建Windows服务

玩转Windows服务系列——Debug、Release版本的注册和卸载,及其原理

玩转Windows服务系列——无COM接口Windows服务启动失败原因及解决方案

玩转Windows服务系列——服务运行、停止流程浅析

玩转Windows服务系列——Windows服务小技巧

玩转Windows服务系列——命令行管理Windows服务

 

时间: 2024-12-23 05:36:16

玩转Windows服务系列——无COM接口Windows服务启动失败原因及解决方案的相关文章

无COM接口Windows服务启动失败的原因及解决方案

将VS创建的Windows服务项目编译生成的程序,通过命令行 "服务.exe -Service"注册为Windows服务后,就可以通过服务管理器进行管理了. 问题 通过服务管理器进行启动的时候,发现服务无法启动,提示错误 由于程序代码是由VS的项目模板生成的,生成后直接编译为Debug版,然后通过命令行进行注册,期间并没有修改过任何代码. 难道是只有Release版本才能通过服务管理器启动吗.于是将Release版注册为服务,通过服务管理器启动,仍然会报同样的错误. 由于服务比较特殊,

玩转Windows服务系列&amp;mdash;&amp;mdash;Windows服务小技巧

原文:玩转Windows服务系列--Windows服务小技巧 伴随着研究Windows服务,逐渐掌握了一些小技巧,现在与大家分享一下. 将Windows服务转变为控制台程序 由于默认的Windows服务程序,编译后为Win32的窗口程序.我们在程序启动或运行过程中,如果想看到一些调试信息,那么就只能通过DebugView或者输出到日志的方式了.因为如果我们通过printf或者std::cout输出调试信息的话,Win32窗口程序是无法显示的. 此时,我们是多么怀念我们的经典的控制台程序啊,它可以

玩转Windows服务系列&amp;mdash;&amp;mdash;命令行管理Windows服务

原文:玩转Windows服务系列--命令行管理Windows服务 说到Windows服务的管理就不得不说通过命令行的方式管理Windows服务,因为无论是系统管理员,还是通过编程的方式调用cmd命令,命令行都是非常方便以及强大的工具. 接下来就看一下如何通过cmd命令管理Windows服务. 管理Windows服务的主要cmd命令 管理Windows服务的命令应该有很多,但是我所了解到的命令主要有两个:sc.net. 说是两个cmd命令,实际就是windows的system32目录下的两个执行程

玩转Windows服务系列&amp;mdash;&amp;mdash;Debug、Release版本的注册和卸载,及其原理

原文:玩转Windows服务系列--Debug.Release版本的注册和卸载,及其原理 Windows服务Debug版本 注册 Services.exe -regserver 卸载 Services.exe -unregserver Windows服务Release版本 注册 Services.exe -service 卸载 Services.exe -unregserver 原理 Windows服务的Debug.Release版本的注册和卸载方式均已明确.但是为什么要这么做呢. 最初我在第一

玩转Windows服务系列&amp;mdash;&amp;mdash;服务运行、停止流程浅析

原文:玩转Windows服务系列--服务运行.停止流程浅析 通过研究Windows服务注册卸载的原理,感觉它并没有什么特别复杂的东西,Windows服务正在一步步退去它那神秘的面纱,至于是不是美女,大家可要睁大眼睛看清楚了. 接下来研究一下Windows服务的启动和停止的流程. 启动流程 启动时自然是从程序的入口点开始 extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/

Windows各系列启动速度差异的奥秘

Windows各系列启动速度差异的奥秘 作者:计算机基础教程网    来源:www.itwen.com    更新时间:2006-02-09 [ 收藏此页到: 天天 | 和讯 | 博采 | ViVi | 狐摘 | 我摘 ]   不知道大家有没有留意,最近两年Windows的版本,启动进入图形界面的所需时间有加长的趋势,这纯粹是系统没优化好吗?其实Windows从诞生的那天开始,其核心和任务的侧重点经历了三次变化,加上它们对储存设备利用的不同,导致了Windows各个系列启动速度的差异.我们就来看

Windows各系列启动速度差异

  一.针对不同的Windows进行优化加快启动速度 1.基于DOS架构的Windows9X的优化: 前文已经探讨了Windows9X的启动关键,就是对基本内存的合理配置运用.这要求加载HIMEM.SYS和SMARTDRV.EXE,在 CONFIG.SYS里对DOS的缓冲区BUFFERS和高端内存都进行优化设置.这些技巧在以前的很多经验文章里都介绍过,所以不再重复了.要注意的是,Windows9X图形界面下,可以不加载声卡.光驱的MS-DOS的驱动程序,以免兼容模式导致系统性能降低.今天大概没多

手把手玩转win8开发系列课程(8)

这节,我们继续上节的一个议程. ①添加一个主页 现在我已经定义了一个ViewModel,我就开始整合项目.第一步就是添加主页到添加到项目中去.我明白项目为何吧页面创建为空白页面,但这个空白的页面起名字叫空白一点儿意义都没有吧,我这里需要给新页面起一个更有意义的页面.原先的空白页面,我已经吧他干掉了. 鄙人是个贱体,我更喜欢添加一些新的文件夹,使其更加的有层次.因此,我加了一个新的文件夹加做pages.在此文件夹下,我右击我添加了一个叫做list的xaml的文件. 特别提醒,如果你是xaml的一个

手把手玩转win8开发系列课程(5)

  前面第三节,我们对ui层大一统的技术--xaml技术有了一个概览.   这节中的我们正式以一个项目--食品管理程序从头到尾的开发的过程,来真真正正手把手进行win8开发.别看这是简简单单的项目,麻雀虽小,能够学win8的开发的方方面面--数据的绑定,各种各样的控件和xaml样式的引用等等.   在下图1,你会看到这个项目最终运行的效果(在模拟器中运行的). 项目的开篇介绍. 针对项目,首先,可以肯定告诉大家我写的这个项目的内容是针对程序猿们而不是对于这些设计妹妹,而且这个食品管理器不是一个完