📄 service.c
字号:
// 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 + -