我在c ++服务上写,但有错误,不能修复它。
我的服务主要功能
int main (int argc, TCHAR *argv[])
{DWORD f;
for(int i=0;i<113;i++)
f = GetLastError();
servicePath = LPTSTR(argv[0]);
OutputDebugString(_T("My Sample Service: Main: Entry"));
//InstallService();
SERVICE_TABLE_ENTRY ServiceTable[] =
{
{SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
{NULL, NULL}
};
// StartService();
if(!StartServiceCtrlDispatcher(ServiceTable)) {
f = GetLastError();
//addLogMessage("Error: StartServiceCtrlDispatcher");
} else if( memcmp(argv[argc-1],"install",7)) {
InstallService();
} else if( memcmp(argv[argc-1],"remove",6)) {
RemoveService();
} else if( memcmp(argv[argc-1],"start",5)) {
StartService();
} else if( memcmp(argv[argc-1],"stop",4)) {
// StopService();
}
// StopService();
OutputDebugString(_TEXT("My Sample Service: Main: Exit"));
return 0;
}
每次在StartServiceCtrlDispatcher上使用命令行参数(service_path和action)调试我的程序时,每次返回1063错误。 Visual Studio我在Administrator下运行。我写错了代码,请帮忙。
更新
VOID WINAPI ServiceMain (DWORD argc, LPTSTR *argv)
{
DWORD Status = E_FAIL;
OutputDebugString(_T("My Sample Service: ServiceMain: Entry"));
g_StatusHandle = RegisterServiceCtrlHandler (SERVICE_NAME, ServiceCtrlHandler);
if (g_StatusHandle == NULL)
{
OutputDebugString(_T("My Sample Service: ServiceMain: RegisterServiceCtrlHandler returned error"));
goto EXIT;
}
// Tell the service controller we are starting
ZeroMemory (&g_ServiceStatus, sizeof (g_ServiceStatus));
g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwServiceSpecificExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE)
{
OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
/*
* Perform tasks neccesary to start the service here
*/
OutputDebugString(_T("My Sample Service: ServiceMain: Performing Service Start Operations"));
// Create stop event to wait on later.
g_ServiceStopEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
if (g_ServiceStopEvent == NULL)
{
OutputDebugString(_T("My Sample Service: ServiceMain: CreateEvent(g_ServiceStopEvent) returned error"));
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwWin32ExitCode = GetLastError();
g_ServiceStatus.dwCheckPoint = 1;
if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE)
{
OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
goto EXIT;
}
// Tell the service controller we are started
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE)
{
OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
// Start the thread that will perform the main task of the service
HANDLE hThread = CreateThread (NULL, 0, ServiceWorkerThread, NULL, 0, NULL);
OutputDebugString(_T("My Sample Service: ServiceMain: Waiting for Worker Thread to complete"));
// Wait until our worker thread exits effectively signaling that the service needs to stop
WaitForSingleObject (hThread, INFINITE);
OutputDebugString(_T("My Sample Service: ServiceMain: Worker Thread Stop Event signaled"));
/*
* Perform any cleanup tasks
*/
OutputDebugString(_T("My Sample Service: ServiceMain: Performing Cleanup Operations"));
CloseHandle (g_ServiceStopEvent);
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 3;
if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE)
{
OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
EXIT:
OutputDebugString(_T("My Sample Service: ServiceMain: Exit"));
return;
}
VOID WINAPI ServiceCtrlHandler (DWORD CtrlCode)
{
OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: Entry"));
switch (CtrlCode)
{
case SERVICE_CONTROL_STOP :
OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: SERVICE_CONTROL_STOP Request"));
if (g_ServiceStatus.dwCurrentState != SERVICE_RUNNING)
break;
/*
* Perform tasks neccesary to stop the service here
*/
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 4;
if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE)
{
OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: SetServiceStatus returned error"));
}
// This will signal the worker thread to start shutting down
SetEvent (g_ServiceStopEvent);
break;
default:
break;
}
OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: Exit"));
}
DWORD WINAPI ServiceWorkerThread (LPVOID lpParam)
{
OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Entry"));
main2();
OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Exit"));
return ERROR_SUCCESS;
}
答案 0 :(得分:3)
您只能在服务控制管理器启动进程时调用StartServiceCtrlDispatcher
,即实际作为服务运行时。从任何其他上下文调用时,您将获得ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
(1063)。
从代码的外观来看,如果没有传递命令行参数,你应该只调用StartServiceControlDispatcher
,例如
if (argc < 2)
{
if (!StartServiceCtrlDispatcher(ServiceTable))
{
f = GetLastError();
}
}
else if (strcmp(argv[1], "install")
{
InstallService();
}
等等。
main()函数还存在一些其他问题,最值得注意的是:
错误的签名; argv []是char,而不是TCHAR
将argv [0]转换为TCHAR
无理由调用GetLastError的循环,114次
使用memcmp代替strcmp
我没看过ServiceMain()。
答案 1 :(得分:3)
当服务安装在Windows 8或更高版本的64位上时,会调用 StartServiceCtrlDispatcher 方法,该方法将调用Main入口点。但是 StartServiceCtrlDispatcher 方法适用于8位指针。
因此,解决方案是使用函数 StartServiceCtrlDispatcherW ,该函数使用16位指针,例如:
之前:它使用指向 LPTSTR (8位)的指针,这是需要 SERVICE_TABLE_ENTRY 和 StartServiceCtrlDispatcher 的数据类型:< / p>
SERVICE_TABLE_ENTRY DispatchTable[] = {
{ (LPTSTR)srvName.str().c_str(), (LPSERVICE_MAIN_FUNCTION)ServiceMain },
{ NULL,NULL }
};
StartServiceCtrlDispatcher(DispatchTable);
之后:它使用指向 LPWSTR (16位)的指针,这是需要 SERVICE_TABLE_ENTRYW 和 StartServiceCtrlDispatcherW 的数据类型:< / p>
SERVICE_TABLE_ENTRYW DispatchTable[] = {
{ (LPWSTR)srvName.str().c_str(), (LPSERVICE_MAIN_FUNCTION)ServiceMain },
{ NULL,NULL }
};
StartServiceCtrlDispatcherW(DispatchTable);
结论:
使用宽字符串(每个字符16位)和StartServiceCtrlDispatcherW和SERVICE_TABLE_ENTRYW Type的函数,而不是StartServiceCtrlDispatcher和SERVICE_TABLE_ENTRY。