5

我在 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 线程”(0x129c) 已退出,代码为 0 (0x0)。程序“[2492] SessionMonitor.exe: Native”已退出,代码为 0 (0x0)。

在调试时,j 是 1063 - ERROR_FAILED_SERVICE_CONTROLLER_CONNECT

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

谢谢你,里龙

4

6 回答 6

5

问题在于您在 Visual Studio 中启动服务。

这是无法做到的。您只需使用 Visual Studio 编译服务,然后使用 sc 命令(或按此处所述以编程方式)在命令提示符下注册它。这个问题的公认答案中描述了所有正确的方法。

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

于 2014-10-03T13:10:45.000 回答
2

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

SetConsoleCtrlHandler(myConsoleHandler, TRUE); 服务启动(argc,argv,真);

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

于 2014-01-24T17:51:26.497 回答
1

在 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);
于 2017-05-29T08:01:06.857 回答
0

你是如何开始服务的?

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

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

于 2012-08-24T12:37:17.727 回答
0

这是错误的:

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

您已经省略了终止的 NUL。利用

wchar_t str[] = L"sesm";
于 2012-07-25T20:46:50.330 回答
0

完成代码后,不要调试。构建它。Build 成功后,会在 Debug 中创建 SessionMonitor.exe 文件。转到命令提示符并安装服务。sc create "sesm" binPath="你的 SessionMonitor.exe\SessionMonitor.exe 的位置"

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

于 2015-02-18T10:14:45.077 回答