Windows 7上的StartServiceCtrlDispatcher访问被拒绝

时间:2012-07-25 12:41:39

标签: windows service access-denied

我在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

6 个答案:

答案 0 :(得分:5)

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

这不可能。您必须使用visual studio编译服务,然后使用sc命令(或按照here描述的程序)在命令提示符上注册它。所有正确的方法都在this问题的接受答案中描述。

如果要调试服务代码,则必须直接发出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)

时,同样的问题也会出现

答案 1 :(得分:2)

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

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

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

答案 2 :(得分:1)

StartServiceCtrlDispatcher access denied on windows 7

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

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

#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);

答案 3 :(得分:0)

这是错误的:

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

你遗漏了NUL的终止。使用

wchar_t str[] = L"sesm";

答案 4 :(得分:0)

你是如何开始服务的?

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

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

答案 5 :(得分:0)

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

转到“运行”并键入services.msc 找到服务sesm,运行它,检查你在ServiceMain中做了什么。