16,472
社区成员
发帖
与我相关
我的任务
分享
void WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv);
DWORD WINAPI ServiceCtrlHandler(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext); // Service Control
BOOL Create(LPCTSTR lpszCmdLine); // Create Service
BOOL Delete(void); // Delete Service
void Dispatch(void); // Dispatch Service
void Run(LPCTSTR lpszExecute, LPCTSTR lpszCmdLine);
// Global Variables
SERVICE_STATUS_HANDLE ServiceStatusHandle = NULL;
SERVICE_STATUS ServiceStatus = { 0 };
HANDLE StopEventHandle = NULL;
// The one and only application object
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[])
{
do
{
if (!AfxWinInit(GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
break;
}
if (2 == argc)
{
LPCTSTR lpszCmdLine = NULL;
if (NULL != (lpszCmdLine = _tcsstr(argv[1], DEFAULT_BATTERYMONITORSERVICES_COMMANDLINE_CREATE))) { Create(lpszCmdLine + _tcslen(DEFAULT_BATTERYMONITORSERVICES_COMMANDLINE_CREATE)); }
else if (NULL != (lpszCmdLine = _tcsstr(argv[1], DEFAULT_BATTERYMONITORSERVICES_COMMANDLINE_DELETE))) { Delete(); }
else { Usage(); }
break;
}
CCommon::INITIALIZE(); // Initialize
// Dispatch Service
Dispatch();
CCommon::PRINT(CCommon::INF, TEXT("-------------------------------------------------------------"));
CCommon::UNINITIALIZE(); // Uninitialize
// Completed
} while (FALSE);
return 0;
}
BOOL Create(LPCTSTR lpszCmdLine)
{
BOOL bRet = FALSE;
SC_HANDLE hSCManager = NULL;
SC_HANDLE hService = NULL;
do
{
// Open Service Control Manager
if (NULL == (hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) { break; }
// Get Service Execute Path
TCHAR szPath[MAX_PATH] = { 0 };
TCHAR szExecute[MAX_PATH] = { 0 };
GetModuleFileName(NULL, szPath, _countof(szPath));
StringCchPrintf(szExecute, _countof(szExecute), TEXT("\"%s\""), szPath);
_ASSERT(NULL != hSCManager);
// Create Service
hService = CreateService(hSCManager,
DEFAULT_BATTERYMONITORSERVICES_SERVICENAME,
DEFAULT_BATTERYMONITORSERVICES_DISPLAYNAME,
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_IGNORE,
szExecute,
TEXT("ShellSvcGroup"),
NULL,
NULL,
NULL,
NULL);
if (NULL == hService)
{
DWORD dwError = GetLastError();
if (ERROR_SERVICE_EXISTS != dwError) { break; }
else { if (NULL == (hService = OpenService(hSCManager, DEFAULT_BATTERYMONITORSERVICES_SERVICENAME, SERVICE_START))) { break; } }
}
else
{
// Set Service Description
SERVICE_DESCRIPTION sd;
sd.lpDescription = DEFAULT_BATTERYMONITORSERVICES_DESCRIPTION;
if (!ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &sd)) { _tprintf(TEXT("Change service configuration failed!\r\n")); }
}
_ASSERT(NULL != hService);
// Start Service
LPCTSTR lpszArgv[] = { DEFAULT_BATTERYMONITORSERVICE_COMMANDLINE_AUTORUN, lpszCmdLine };
if (!StartService(hService, _countof(lpszArgv), lpszArgv))
{
if (ERROR_SERVICE_ALREADY_RUNNING != GetLastError()) { _tprintf(TEXT("Start service failed!\r\n")); }
else { _tprintf(TEXT("Service is already running!\r\n")); bRet = TRUE; break; }
}
// Completed
bRet = TRUE;
} while (FALSE);
if (!bRet) { _tprintf(TEXT("Create service failed!\r\n")); }
else { _tprintf(TEXT("Create service scuccessful.\r\n")); }
if (NULL != hService) { CloseServiceHandle(hService); hService = NULL; }
if (NULL != hSCManager) { CloseServiceHandle(hSCManager); hSCManager = NULL; }
return bRet;
}
BOOL Delete(void)
{
BOOL bRet = FALSE;
SC_HANDLE hSCManager = NULL;
SC_HANDLE hService = NULL;
do
{
// Notify Battery Monitor Application Exit
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, DEFAULT_BATTERYMONITORSERVICES_QUIT_APPLICATION);
if (NULL != hEvent) { SetEvent(hEvent); CloseHandle(hEvent); hEvent = NULL; }
// Open Service Control Manager
if (NULL == (hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) { break; }
_ASSERT(NULL != hSCManager);
// Open Service
if (NULL == (hService = OpenService(hSCManager, DEFAULT_BATTERYMONITORSERVICES_SERVICENAME, SERVICE_ALL_ACCESS)))
{
_tprintf(TEXT("Service does not exist or has been removed!\r\n"));
break;
}
SERVICE_STATUS status = { 0 };
if (QueryServiceStatus(hService, &status))
{
if (SERVICE_STOPPED != status.dwCurrentState)
{
if (ControlService(hService, SERVICE_CONTROL_STOP, &status))
{
while (QueryServiceStatus(hService, &status) && (SERVICE_STOP_PENDING == status.dwCurrentState)) { Sleep(200); }
}
}
}
// Delete Service
if (!DeleteService(hService)) { break; }
// Completed
bRet = TRUE;
} while (FALSE);
if (!bRet) { _tprintf(TEXT("Delete services failed!\r\n")); }
else { _tprintf(TEXT("Delete services Scuccessful.\r\n")); }
if (NULL != hService) { CloseServiceHandle(hService); hService = NULL; }
if (NULL != hSCManager) { CloseServiceHandle(hSCManager); hSCManager = NULL; }
return bRet;
}
void Dispatch(void)
{
// Dispatch Service
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ DEFAULT_BATTERYMONITORSERVICES_SERVICENAME, ServiceMain },
{ NULL, NULL }
};
if (!StartServiceCtrlDispatcher(DispatchTable))
{
_tprintf(TEXT("Start service control dispatcher failed!\r\n"));
}
}
void WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
{
CCommon::PRINT(CCommon::INF, TEXT("ServiceMain(+)."));
do
{
// Parse Command Line
BOOL bAutoRun = FALSE;
for (DWORD i = 0; i != dwArgc; ++i)
{
CCommon::PRINT(CCommon::INF, TEXT("ServiceMain() Argv[%u] = %s."), i, lpszArgv[i]);
LPCTSTR lpszTask = NULL;
if (0 == _tcsicmp(DEFAULT_BATTERYMONITORSERVICE_COMMANDLINE_AUTORUN, lpszArgv[i])) { bAutoRun = TRUE; }
else if(NULL != (lpszTask = _tcsstr(lpszArgv[i], DEFAULT_BATTERYMONITORSERVICE_COMMANDLINE_TOKEN)))
{
CCommon::PRINT(CCommon::INF, TEXT("ServiceMain() Parse Task Parameters."));
// Parse Task Parameters
TASK task = (TASK)_tcstoul(lpszTask + _tcslen(DEFAULT_BATTERYMONITORSERVICE_COMMANDLINE_TOKEN), NULL, 16);
CCommon::UpdateXML(DEFAULT_BATTERYMONITOR_CONFIG_SCHEDULE, (TASK_SCHEDULE & task) ? 1 : 0);
CCommon::UpdateXML(DEFAULT_BATTERYMONITOR_CONFIG_INTERVAL, (TASK_INTERVAL & task) ? 1 : 0);
CCommon::UpdateXML(DEFAULT_BATTERYMONITOR_CONFIG_POLLING, (TASK_POLLING & task) ? 1 : 0);
}
}
// Initialize SERIVCE_STATUS
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SESSIONCHANGE;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwServiceSpecificExitCode = 0;
// Register the handler function for the service
CCommon::PRINT(CCommon::INF, TEXT("Registry Service Control Handler..."));
ServiceStatusHandle = RegisterServiceCtrlHandlerEx(DEFAULT_BATTERYMONITORSERVICES_SERVICENAME, ServiceCtrlHandler, NULL);
_ASSERT(NULL != ServiceStatusHandle);
if (NULL == ServiceStatusHandle) { CCommon::PRINT(CCommon::ERR, GetLastError(), TEXT("RegisterServiceCtrlHandler")); break; }
// Report service status to the SCM
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 3000;
if (!SetServiceStatus(ServiceStatusHandle, &ServiceStatus)) { CCommon::PRINT(CCommon::ERR, GetLastError(), TEXT("SetServiceStatus")); break; }
CCommon::PRINT(CCommon::INF, TEXT("Initialize and Create Stop Event."));
// Report initial status to the SCM
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus(ServiceStatusHandle, &ServiceStatus)) { CCommon::PRINT(CCommon::ERR, GetLastError(), TEXT("SetServiceStatus")); break; }
// Create Event
_ASSERT(NULL == StopEventHandle);
StopEventHandle = CreateEvent(NULL, TRUE, FALSE, NULL);
_ASSERT(NULL != StopEventHandle);
if (NULL == StopEventHandle) { CCommon::PRINT(CCommon::ERR, GetLastError(), TEXT("CreateEvent")); break; }
// Run Application
if (bAutoRun) { Run(DEFAULT_BATTERYMONITORSERVICES_APPLICATION, NULL); }
// If Run completed and notify event to close
CCommon::PRINT(CCommon::INF, TEXT("Wait Stop Event Signal and Stop Service..."));
WaitForSingleObject(StopEventHandle, INFINITE);
if (NULL != StopEventHandle) { CloseHandle(StopEventHandle); StopEventHandle = NULL; }
// Report service status to the SCM
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus(ServiceStatusHandle, &ServiceStatus)) { CCommon::PRINT(CCommon::ERR, GetLastError(), TEXT("SetServiceStatus")); }
CCommon::PRINT(CCommon::INF, TEXT("Service Stop Completed."));
// Completed
} while (FALSE);
CCommon::PRINT(CCommon::INF, TEXT("ServiceMain(-)."));
}
DWORD WINAPI ServiceCtrlHandler(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
UNREFERENCED_PARAMETER(lpEventData);
UNREFERENCED_PARAMETER(lpContext);
CCommon::PRINT(CCommon::INF, TEXT("ServiceCtrlHandler(+)."));
// Handle the requested control code.
switch (dwControl)
{
case SERVICE_CONTROL_SESSIONCHANGE:
{
switch (dwEventType)
{
case WTS_CONSOLE_CONNECT:
CCommon::PRINT(CCommon::INF, TEXT("Session Notify : WTS_CONSOLE_CONNECT."));
break;
case WTS_CONSOLE_DISCONNECT:
CCommon::PRINT(CCommon::INF, TEXT("Session Notify : WTS_CONSOLE_DISCONNECT."));
break;
case WTS_REMOTE_CONNECT:
CCommon::PRINT(CCommon::INF, TEXT("Session Notify : WTS_REMOTE_CONNECT."));
break;
case WTS_REMOTE_DISCONNECT:
CCommon::PRINT(CCommon::INF, TEXT("Session Notify : WTS_REMOTE_DISCONNECT."));
break;
case WTS_SESSION_LOGON:
CCommon::PRINT(CCommon::INF, TEXT("Session Notify : WTS_SESSION_LOGON."));
Run(DEFAULT_BATTERYMONITORSERVICES_APPLICATION, NULL); /