繁体   English   中英

Windows 7上的StartServiceCtrlDispatcher访问被拒绝

[英]StartServiceCtrlDispatcher access denied on windows 7

我在Windows 7上的visual studio 2008中有一个c ++项目,我尝试启动一项新服务。 我以管理员身份运行visual studio。 我无法启动服务(甚至没有调用serviceMain)。

这是我的主要功能:

wchar_t str[] = {'s','e','s','m'};

int _tmain(int argc, _TCHAR* argv[])
{
    SERVICE_TABLE_ENTRY dispTable[] =
    {
        {(wchar_t*)str, ServiceWork::ServiceMain}, 
        {NULL, NULL}
    };

    int i = StartServiceCtrlDispatcher(dispTable);
    int j = GetLastError();
    return 0; 
}

输出是:

'SessionMonitor.exe':已加载'C:\\ Windows \\ SysWOW64 \\ cryptbase.dll'

'SessionMonitor.exe':已加载'C:\\ Windows \\ SysWOW64 \\ imm32.dll'

'SessionMonitor.exe':已加载'C:\\ Windows \\ SysWOW64 \\ msctf.dll'

SessionMonitor.exe中0x7638b9bc的第一次机会异常:0x00000005:访问被拒绝。 线程'Win32 Thread'(0x129c)已退出,代码为0(0x0)。 程序'[2492] SessionMonitor.exe:Native'已退出,代码为0(0x0)。

在调试时,j是1063 - ERROR_FAILED_SERVICE_CONTROLLER_CONNECT

以前有人遇到过这个问题吗? 任何解决方案

谢谢你,Liron

问题在于您在visual studio中启动服务。

这是不可能做到的。 您必须使用visual studio编译服务,然后使用sc命令(或此处描述的programmarically)在命令提示符上注册它。 所有正确的方法都在这个问题的公认答案中描述。

如果要调试服务代码,则必须直接发出ServiceMain,例如:

int _tmain(int argc, _TCHAR* argv[])
{
#ifdef AS_SERVICE
    SERVICE_TABLE_ENTRY dispTable[] =
    {
        {(wchar_t*)str, ServiceWork::ServiceMain}, 
        {NULL, NULL}
    };

    int i = StartServiceCtrlDispatcher(dispTable);
    int j = GetLastError();
    return 0;
#else
    ServiceMain(argc, argv);
#endif
}

StartServiceCtrlDispatcher失败并且GetLastError返回ERROR_FAILED_SERVICE_CONTROLLER_CONNECT (1063)时,同样的问题也会出现

如果您尝试从Microsoft Visual Studio等IDE或命令行启动Windows服务,则需要设置ConsoleHandler并以manaully调用ServiceStart,例如

SetConsoleCtrlHandler(myConsoleHandler,TRUE); ServiceStart(argc,argv,TRUE);

在我们的应用程序中,我们传递一个-debug标志,告诉应用程序作为控制台程序而不是Windows服务运行。

Windows 7上的StartServiceCtrlDispatcher访问被拒绝

我相信这是Windows中的一个错误。 根据MSDN,StartServiceCtrlDispatcher应该在失败时返回零,但是微软的某个人认为在API边界之间抛出自定义(非C ++)异常是一个好主意。

您可以使用AddVectoredExceptionHandler来捕获并忽略此特殊类型的异常,以解决此问题:

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

LONG WINAPI handle_exception(EXCEPTION_POINTERS* exception_data)
{
  switch (exception_data->ExceptionRecord->ExceptionCode)
  {
  case 0x00000005:  // thrown by StartServiceCtrlDispatcher for fun.
    // Ignore these specific type of exceptions and continue execution.
    // Note: There are several more interesting exceptions to catch here,
    // which are out of scope of this question.
    return EXCEPTION_CONTINUE_SEARCH;

  case 0xE06D7363:  // C++ exception code.
  default:
    // Pass all other type of exceptions to their regular exception handlers.
    return EXCEPTION_EXECUTE_HANDLER;
  }
}

auto handle = AddVectoredExceptionHandler(1, &handle_exception);
// Your code here. Now you can check for the return value of
// StartServiceCtrlDispatcher to see whether the application
// was started as a service or not without crashing.
RemoveVectoredExceptionHandler(handle);

这是错的:

wchar_t str[] = {'s','e','s','m'};

你遗漏了NUL的终止。 使用

wchar_t str[] = L"sesm";

你是如何开始服务的?

即使您的用户位于Administrators组中,在您通过UAC之前,程序也不会完全升级,或者它们是从已经提升的上下文启动的。 如果您尝试通过Visual Studio进行调试,则可能需要右键单击Visual Studio并以管理员身份运行它以使其正常工作。

如果您希望能够从资源管理器启动服务,则需要在清单中将requestedExecutionLevel设置为“level = requireAdministrator”。 从命令提示符启动将需要相同,除非您使用'net start yourservice',当需要提升命令提示符时。 从系统服务插件启动不需要特别准备,并且在Windows 7(而不是Vista)下对MS签名应用程序具有隐藏的提升。

完成代码后,请不要调试。 建立它。 当Build成功时,将在Debug内部创建SessionMonitor.exe文件。 转到命令提示符并安装该服务。 sc创建“sesm”binPath =“SessionMonitor.exe \\ SessionMonitor.exe的位置”

转到运行并键入services.msc找到服务sesm,运行它,检查您在ServiceMain中所做的工作是否正常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM