⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 service.c

📁 This is Win32 Service wrapper for SVN. Source is included, and its in the public domain.
💻 C
📖 第 1 页 / 共 2 页
字号:
//  PURPOSE: Installs the service
//
//  PARAMETERS:
//    none
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:
//
void CmdInstallService(int argc, char **argv)
{
    SC_HANDLE   schService;
    SC_HANDLE   schSCManager;

    TCHAR szPath[512];

	HKEY log_key;
	LONG err;

    if ( GetModuleFileName( NULL, szPath, 512 ) == 0 )
    {
        _tprintf(TEXT("Unable to install %s - %s\n"), TEXT(SZSERVICEDISPLAYNAME), GetLastErrorText(szErr, 256));
        return;
    }

    schSCManager = OpenSCManager(
                        NULL,                   // machine (NULL == local)
                        NULL,                   // database (NULL == default)
                        SC_MANAGER_ALL_ACCESS   // access required
                        );
    if ( schSCManager )
    {
        schService = CreateService(
            schSCManager,               // SCManager database
            TEXT(SZSERVICENAME),        // name of service
            TEXT(SZSERVICEDISPLAYNAME), // name to display
            SERVICE_ALL_ACCESS,         // desired access
            SERVICE_WIN32_OWN_PROCESS,  // service type
            SERVICE_DEMAND_START,       // start type
			// Could also be SERVICE_AUTO_START for automatic startup.
            SERVICE_ERROR_NORMAL,       // error control type
            szPath,                     // service's binary
            NULL,                       // no load ordering group
            NULL,                       // no tag identifier
            TEXT(SZDEPENDENCIES),       // dependencies
            NULL,                       // LocalSystem account
            NULL);                      // no password

        if ( schService )
        {
            _tprintf(TEXT("%s installed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
			// To automatically start service ::StartService(schService, 0, NULL);
            CloseServiceHandle(schService);
        }
        else
        {
            _tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText(szErr, 256));
        }

        CloseServiceHandle(schSCManager);
    }
    else
        _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));


	// Try to register the log message file:

	err = RegCreateKeyEx(
		HKEY_LOCAL_MACHINE,
		TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\SVNService"),
		0,
		NULL,
		REG_OPTION_NON_VOLATILE,
		KEY_ALL_ACCESS,
		NULL,
		&log_key,
		NULL);
	if (err != ERROR_SUCCESS) printf("Could register log message file.");

	err = RegSetValueEx(
		log_key,
		TEXT("EventMessageFile"),
		0,
		REG_SZ,
		(LPBYTE) szPath,
		(wcslen(szPath)+1)*sizeof(TCHAR));
	if (err != ERROR_SUCCESS) printf("Could not set message file.");

	err = RegCloseKey(log_key);
	if (err != ERROR_SUCCESS) printf("Could not close reg key.");

	CmdSetupService(argc, argv);
}

void CmdSetupService(int argc, char **argv)
{
	CHAR cmdLine[512];
	int i;
	HKEY key;
	LONG err;

	if (argc > 0)
	{
		cmdLine[0] = 0;
		for (i=0; i<argc; i++)
		{
			if (i == 0)
				strcat(cmdLine, "\"");
			else
				strcat(cmdLine, " \"");
			strcat(cmdLine, argv[i]);
			strcat(cmdLine, "\"");
		}

		err = RegCreateKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Clansoft\\SVNService", &key);
		if (err == ERROR_SUCCESS)
		{
			RegSetValueExA(key, "CommandLine", 0, REG_SZ, cmdLine, strlen(cmdLine)+1);
			RegCloseKey(key);
		}

		printf("Commandline set: %s\r\n", cmdLine);
	}
	else
	{
		printf("No parameters specified!\r\n");
	}
}


//
//  FUNCTION: CmdRemoveService()
//
//  PURPOSE: Stops and removes the service
//
//  PARAMETERS:
//    none
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:
//
void CmdRemoveService()
{
    SC_HANDLE   schService;
    SC_HANDLE   schSCManager;

    schSCManager = OpenSCManager(
                        NULL,                   // machine (NULL == local)
                        NULL,                   // database (NULL == default)
                        SC_MANAGER_ALL_ACCESS   // access required
                        );
    if ( schSCManager )
    {
        schService = OpenService(schSCManager, TEXT(SZSERVICENAME), SERVICE_ALL_ACCESS);

        if (schService)
        {
            // try to stop the service
            if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )
            {
                _tprintf(TEXT("Stopping %s."), TEXT(SZSERVICEDISPLAYNAME));
                Sleep( 1000 );

                while( QueryServiceStatus( schService, &ssStatus ) )
                {
                    if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )
                    {
                        _tprintf(TEXT("."));
                        Sleep( 1000 );
                    }
                    else
                        break;
                }

                if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
                    _tprintf(TEXT("\n%s stopped.\n"), TEXT(SZSERVICEDISPLAYNAME) );
                else
                    _tprintf(TEXT("\n%s failed to stop.\n"), TEXT(SZSERVICEDISPLAYNAME) );

            }

            // now remove the service
            if( DeleteService(schService) )
                _tprintf(TEXT("%s removed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
            else
                _tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText(szErr,256));


            CloseServiceHandle(schService);
        }
        else
            _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText(szErr,256));

        CloseServiceHandle(schSCManager);
    }
    else
        _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
}




///////////////////////////////////////////////////////////////////
//
//  The following code is for running the service as a console app
//


//
//  FUNCTION: CmdDebugService(int argc, char ** argv)
//
//  PURPOSE: Runs the service as a console application
//
//  PARAMETERS:
//    argc - number of command line arguments
//    argv - array of command line arguments
//
//  RETURN VALUE:
//    none
//
//  COMMENTS:
//
void CmdDebugService(int argc, char ** argv)
{
    DWORD dwArgc;
    LPTSTR *lpszArgv;

#ifdef UNICODE
    lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc) );
#else
    dwArgc   = (DWORD) argc;
    lpszArgv = argv;
#endif

    _tprintf(TEXT("Debugging %s.\n"), TEXT(SZSERVICEDISPLAYNAME));

    SetConsoleCtrlHandler( ControlHandler, TRUE );

    ServiceStart( dwArgc, lpszArgv );
}


//
//  FUNCTION: ControlHandler ( DWORD dwCtrlType )
//
//  PURPOSE: Handled console control events
//
//  PARAMETERS:
//    dwCtrlType - type of control event
//
//  RETURN VALUE:
//    True - handled
//    False - unhandled
//
//  COMMENTS:
//
BOOL WINAPI ControlHandler ( DWORD dwCtrlType )
{
    switch( dwCtrlType )
    {
        case CTRL_BREAK_EVENT:  // use Ctrl+C or Ctrl+Break to simulate
        case CTRL_C_EVENT:      // SERVICE_CONTROL_STOP in debug mode
            _tprintf(TEXT("Stopping %s.\n"), TEXT(SZSERVICEDISPLAYNAME));
            ServiceStop();
            return TRUE;
            break;

    }
    return FALSE;
}

//
//  FUNCTION: GetLastErrorText
//
//  PURPOSE: copies error message text to string
//
//  PARAMETERS:
//    lpszBuf - destination buffer
//    dwSize - size of buffer
//
//  RETURN VALUE:
//    destination buffer
//
//  COMMENTS:
//
LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize )
{
    DWORD dwRet;
    LPTSTR lpszTemp = NULL;

    dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
                           NULL,
                           GetLastError(),
                           LANG_NEUTRAL,
                           (LPTSTR)&lpszTemp,
                           0,
                           NULL );

    // supplied buffer is not long enough
    if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )
        lpszBuf[0] = TEXT('\0');
    else
    {
        lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0');  //remove cr and newline character
        _stprintf( lpszBuf, TEXT("%s (0x%x)"), lpszTemp, GetLastError() );
    }

    if ( lpszTemp )
        LocalFree((HLOCAL) lpszTemp );

    return lpszBuf;
}

volatile BOOL stop_service = FALSE;

VOID ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv)
{
	TCHAR szDllName[_MAX_PATH];
	TCHAR szApp[_MAX_PATH*2];
	TCHAR szCommand[_MAX_PATH*2];
	int i, len;
	STARTUPINFO startupInfo;
	PROCESS_INFORMATION processInfo;
	BOOL result;
	DWORD exitcode;
	LONG lResult;
	HKEY key;
	DWORD type, size;
	LPTSTR pos;

	ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 5000);
	stop_service = FALSE;

	GetModuleFileName(0, szDllName, _MAX_PATH);
	len = wcslen(szDllName);

	wcscpy(szApp, szDllName);
	for (i=len-1; i>0; i--)
	{
		if (szApp[i] == '\\')
		{
			szApp[i+1] = 0;
			break;
		}
	}
	_tprintf(TEXT("Setting working directory: %s\n"), szApp);
	SetCurrentDirectory(szApp);
	wcscat(szApp, L"svnserve.exe");

	wcscpy(szCommand, L"\"");
	wcscat(szCommand, szApp);
	wcscat(szCommand, L"\" ");

	lResult = RegOpenKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Clansoft\\SVNService", &key);
	if (lResult == ERROR_SUCCESS)
	{
		pos = szCommand+wcslen(szCommand);
		size = (_MAX_PATH*2-wcslen(szCommand))*sizeof(TCHAR);
		type = REG_SZ;
		lResult = RegQueryValueEx(key, L"CommandLine", 0, &type, (LPBYTE) pos, &size);
		if (lResult != ERROR_SUCCESS || type != REG_SZ)
			wcscpy(pos, L"-d");
		else
			_tprintf(TEXT("RegQueryValueEx failed with error %d, type %d\n"), lResult, type);
		RegCloseKey(key);
	}
	else
	{
		_tprintf(TEXT("RegOpenKey failed with %d\n"), lResult);
		wcscat(szCommand, L"-d");
	}

	_tprintf(TEXT("Running command: %s\n"), szCommand);

	memset(&startupInfo, 0, sizeof(STARTUPINFO));
	startupInfo.cb = sizeof(STARTUPINFO);

	memset(&processInfo, 0, sizeof(PROCESS_INFORMATION));

	result = CreateProcess(
		szApp,
		szCommand,
		0,
		0,
		FALSE,
		CREATE_NEW_PROCESS_GROUP,
		0,
		0,
		&startupInfo,
		&processInfo);

	if (result == FALSE)
	{
		AddToMessageLog(Event_FailCreateProcess, szCommand, EVENTLOG_ERROR_TYPE);
		ReportStatusToSCMgr(SERVICE_STOPPED, GetLastError(), 1000);
		return;
	}

	if (processInfo.hThread)
		CloseHandle(processInfo.hThread);

	ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 1000);

	while (!stop_service)
	{
		if (WaitForSingleObject(processInfo.hProcess, 1000) != WAIT_TIMEOUT)
		{
			AddToMessageLog(Event_ProcessEnded, szCommand, EVENTLOG_ERROR_TYPE);
			break;
		}
	}

	if (processInfo.hProcess)
	{
		GenerateConsoleCtrlEvent(CTRL_C_EVENT, processInfo.dwProcessId);
		GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, processInfo.dwProcessId);
		ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 30000);
		if (WaitForSingleObject(processInfo.hProcess, 28000) == WAIT_TIMEOUT)
		{
			AddToMessageLog(Event_ProcessTimeout, szCommand, EVENTLOG_ERROR_TYPE);
			TerminateProcess(processInfo.hProcess, 255);
		}

		exitcode = STATUS_WAIT_0;
		GetExitCodeProcess(processInfo.hProcess, &exitcode);

		/* Unusual exit code?*/
/*		if (exitcode != STATUS_WAIT_0)
		{
			AddToMessageLog(Event_ExitCode, exitcode, EVENTLOG_WARNING_TYPE);
		}*/
		CloseHandle(processInfo.hProcess);
	}

	ReportStatusToSCMgr(SERVICE_STOPPED, NO_ERROR, 1000);
}

VOID ServiceStop()
{
	ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 2000);
	stop_service = TRUE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -