由于Windows C++ 没有现成的Windows server程序的开发框架,而C#则有,所以为了方便大家以及我以后使用C++更方便的开发Windows server程序,特意写此文。
Github源码地址
#pragma region Includes
#include
#include
#include "ServiceInstaller.h"
#include "ServiceBase.h"
#include "SampleService.h"
#pragma endregion
// Internal name of the service
#define SERVICE_NAME L"CppWindowsService"
// Displayed name of the service
#define SERVICE_DISPLAY_NAME L"CppWindowsService Sample Service"
// Service start options.
#define SERVICE_START_TYPE SERVICE_AUTO_START
// List of service dependencies - "dep1\0dep2\0\0"
#define SERVICE_DEPENDENCIES L""
// The name of the account under which the service should run
#define SERVICE_ACCOUNT L"NT AUTHORITY\\LocalService"
// The password to the service account name
#define SERVICE_PASSWORD NULL
//
// FUNCTION: wmain(int, wchar_t *[])
//
// PURPOSE: entrypoint for the application.
//
// PARAMETERS:
// argc - number of command line arguments
// argv - array of command line arguments
//
// RETURN VALUE:
// none
//
// COMMENTS:
// wmain() either performs the command line task, or run the service.
//
int wmain(int argc, wchar_t *argv[])
{
//MessageBoxA(nullptr, "1", "1", MB_OK);
if ((argc > 1) && ((*argv[1] == L'-' || (*argv[1] == L'/'))))
{
if (_wcsicmp(L"install", argv[1] + 1) == 0)
{
// Install the service when the command is
// "-install" or "/install".
InstallService(
SERVICE_NAME, // Name of service
SERVICE_DISPLAY_NAME, // Name to display
SERVICE_START_TYPE, // Service start type
SERVICE_DEPENDENCIES, // Dependencies
SERVICE_ACCOUNT, // Service running account
SERVICE_PASSWORD // Password of the account
);
//MessageBoxA(nullptr, "install", "install", MB_OK);
}
else if (_wcsicmp(L"remove", argv[1] + 1) == 0)
{
// Uninstall the service when the command is
// "-remove" or "/remove".
UninstallService(SERVICE_NAME);
//MessageBoxA(nullptr, "remove", "remove", MB_OK);
}
}
else
{
wprintf(L"Parameters:\n");
wprintf(L" -install to install the service.\n");
wprintf(L" -remove to remove the service.\n");
CSampleService service(SERVICE_NAME);
if (!CServiceBase::Run(service))
{
wprintf(L"Service failed to run w/err 0x%08lx\n", GetLastError());
}
//MessageBoxA(nullptr, "run", "run", MB_OK);
}
return 0;
}
#pragma region "Includes"
#include
#include
#include "ServiceInstaller.h"
#pragma endregion
//
// FUNCTION: InstallService
//
// PURPOSE: Install the current application as a service to the local
// service control manager database.
//
// PARAMETERS:
// * pszServiceName - the name of the service to be installed
// * pszDisplayName - the display name of the service
// * dwStartType - the service start option. This parameter can be one of
// the following values: SERVICE_AUTO_START, SERVICE_BOOT_START,
// SERVICE_DEMAND_START, SERVICE_DISABLED, SERVICE_SYSTEM_START.
// * pszDependencies - a pointer to a double null-terminated array of null-
// separated names of services or load ordering groups that the system
// must start before this service.
// * pszAccount - the name of the account under which the service runs.
// * pszPassword - the password to the account name.
//
// NOTE: If the function fails to install the service, it prints the error
// in the standard output stream for users to diagnose the problem.
//
void InstallService(PWSTR pszServiceName,
PWSTR pszDisplayName,
DWORD dwStartType,
PWSTR pszDependencies,
PWSTR pszAccount,
PWSTR pszPassword)
{
wchar_t szPath[MAX_PATH];
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)) == 0)
{
wprintf(L"GetModuleFileName failed w/err 0x%08lx\n", GetLastError());
goto Cleanup;
}
// Open the local default service control manager database
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT |
SC_MANAGER_CREATE_SERVICE);
if (schSCManager == NULL)
{
wprintf(L"OpenSCManager failed w/err 0x%08lx\n", GetLastError());
goto Cleanup;
}
// Install the service into SCM by calling CreateService
schService = CreateService(
schSCManager, // SCManager database
pszServiceName, // Name of service
pszDisplayName, // Name to display
SERVICE_QUERY_STATUS, // Desired access
SERVICE_WIN32_OWN_PROCESS, // Service type
dwStartType, // Service start type
SERVICE_ERROR_NORMAL, // Error control type
szPath, // Service's binary
NULL, // No load ordering group
NULL, // No tag identifier
pszDependencies, // Dependencies
pszAccount, // Service running account
pszPassword // Password of the account
);
if (schService == NULL)
{
wprintf(L"CreateService failed w/err 0x%08lx\n", GetLastError());
goto Cleanup;
}
wprintf(L"%s is installed.\n", pszServiceName);
Cleanup:
// Centralized cleanup for all allocated resources.
if (schSCManager)
{
CloseServiceHandle(schSCManager);
schSCManager = NULL;
}
if (schService)
{
CloseServiceHandle(schService);
schService = NULL;
}
}
//
// FUNCTION: UninstallService
//
// PURPOSE: Stop and remove the service from the local service control
// manager database.
//
// PARAMETERS:
// * pszServiceName - the name of the service to be removed.
//
// NOTE: If the function fails to uninstall the service, it prints the
// error in the standard output stream for users to diagnose the problem.
//
void UninstallService(PWSTR pszServiceName)
{
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
SERVICE_STATUS ssSvcStatus = {};
// Open the local default service control manager database
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (schSCManager == NULL)
{
wprintf(L"OpenSCManager failed w/err 0x%08lx\n", GetLastError());
goto Cleanup;
}
// Open the service with delete, stop, and query status permissions
schService = OpenService(schSCManager, pszServiceName, SERVICE_STOP |
SERVICE_QUERY_STATUS | DELETE);
if (schService == NULL)
{
wprintf(L"OpenService failed w/err 0x%08lx\n", GetLastError());
goto Cleanup;
}
// Try to stop the service
if (ControlService(schService, SERVICE_CONTROL_STOP, &ssSvcStatus))
{
wprintf(L"Stopping %s.", pszServiceName);
Sleep(1000);
while (QueryServiceStatus(schService, &ssSvcStatus))
{
if (ssSvcStatus.dwCurrentState == SERVICE_STOP_PENDING)
{
wprintf(L".");
Sleep(1000);
}
else break;
}
if (ssSvcStatus.dwCurrentState == SERVICE_STOPPED)
{
wprintf(L"\n%s is stopped.\n", pszServiceName);
}
else
{
wprintf(L"\n%s failed to stop.\n", pszServiceName);
}
}
// Now remove the service by calling DeleteService.
if (!DeleteService(schService))
{
wprintf(L"DeleteService failed w/err 0x%08lx\n", GetLastError());
goto Cleanup;
}
wprintf(L"%s is removed.\n", pszServiceName);
Cleanup:
// Centralized cleanup for all allocated resources.
if (schSCManager)
{
CloseServiceHandle(schSCManager);
schSCManager = NULL;
}
if (schService)
{
CloseServiceHandle(schService);
schService = NULL;
}
}
这个类也是自己要实现的功能,根据自己的需要来定义函数即可。
#pragma region Includes
#include "SampleService.h"
#include "ThreadPool.h"
#pragma endregion
CSampleService::CSampleService(PWSTR pszServiceName,
BOOL fCanStop,
BOOL fCanShutdown,
BOOL fCanPauseContinue)
: CServiceBase(pszServiceName, fCanStop, fCanShutdown, fCanPauseContinue)
{
m_fStopping = FALSE;
// Create a manual-reset event that is not signaled at first to indicate
// the stopped signal of the service.
m_hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hStoppedEvent == NULL)
{
throw GetLastError();
}
}
CSampleService::~CSampleService(void)
{
if (m_hStoppedEvent)
{
CloseHandle(m_hStoppedEvent);
m_hStoppedEvent = NULL;
}
}
//
// FUNCTION: CSampleService::OnStart(DWORD, LPWSTR *)
//
// PURPOSE: The function is executed when a Start command is sent to the
// service by the SCM or when the operating system starts (for a service
// that starts automatically). It specifies actions to take when the
// service starts. In this code sample, OnStart logs a service-start
// message to the Application log, and queues the main service function for
// execution in a thread pool worker thread.
//
// PARAMETERS:
// * dwArgc - number of command line arguments
// * lpszArgv - array of command line arguments
//
// NOTE: A service application is designed to be long running. Therefore,
// it usually polls or monitors something in the system. The monitoring is
// set up in the OnStart method. However, OnStart does not actually do the
// monitoring. The OnStart method must return to the operating system after
// the service's operation has begun. It must not loop forever or block. To
// set up a simple monitoring mechanism, one general solution is to create
// a timer in OnStart. The timer would then raise events in your code
// periodically, at which time your service could do its monitoring. The
// other solution is to spawn a new thread to perform the main service
// functions, which is demonstrated in this code sample.
//
void CSampleService::OnStart(DWORD dwArgc, LPWSTR *lpszArgv)
{
// Log a service start message to the Application log.
WriteEventLogEntry(L"CppWindowsService in OnStart",
EVENTLOG_INFORMATION_TYPE);
//MessageBoxA(nullptr, "OnStart", "OnStart", MB_OK);
// Queue the main service function for execution in a worker thread.
CThreadPool::QueueUserWorkItem(&CSampleService::ServiceWorkerThread, this);
}
//
// FUNCTION: CSampleService::ServiceWorkerThread(void)
//
// PURPOSE: The method performs the main function of the service. It runs
// on a thread pool worker thread.
//
void CSampleService::ServiceWorkerThread(void)
{
// Periodically check if the service is stopping.
while (!m_fStopping)
{
// Perform main service function here...
::Sleep(2000); // Simulate some lengthy operations.
}
// Signal the stopped event.
SetEvent(m_hStoppedEvent);
}
//
// FUNCTION: CSampleService::OnStop(void)
//
// PURPOSE: The function is executed when a Stop command is sent to the
// service by SCM. It specifies actions to take when a service stops
// running. In this code sample, OnStop logs a service-stop message to the
// Application log, and waits for the finish of the main service function.
//
// COMMENTS:
// Be sure to periodically call ReportServiceStatus() with
// SERVICE_STOP_PENDING if the procedure is going to take long time.
//
void CSampleService::OnStop()
{
// Log a service stop message to the Application log.
WriteEventLogEntry(L"CppWindowsService in OnStop",
EVENTLOG_INFORMATION_TYPE);
//MessageBoxA(nullptr, "OnStop", "OnStop", MB_OK);
// Indicate that the service is stopping and wait for the finish of the
// main service function (ServiceWorkerThread).
m_fStopping = TRUE;
if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0)
{
throw GetLastError();
}
}
服务程序一定不能放到桌面上,因为所有的服务程序起痘都是在桌面程序起痘之前,所以如果放到桌面上,将会导致加载不到该文件,提示文件被拒绝。