[英]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.