用VC++开发Windows服务

用.net开发服务很简单,此处讲解使用VC++开发Windows服务
1. 服务的组成
一个服务由三部分组成:
第一部分Service Control Manager(SCM),每个Windows系统都有一个SCM,SCM存在于Service.exe中,在Windows启动的时候会自动运行,伴随着操作系统的启动和关闭而产生和终止;
第二部分为服务本身,一个服务拥有能从SCM收到信号和命令所必须的特殊代码,并且能在处理后将它的状态回传回SCM;
第三部分是Service Control Dispatcher(SCP),是一个拥有用户界面,允许用户开始、停止、暂停、继续,并且控制一个或多个安装在计算机上服务的Win32应用程序。

2. 三个重要函数
2.1 服务程序入口函数
头文件:Winsvc.h 
库:Advapi32.lib
DLL:Advapi32.dll

BOOL WINAPI StartServiceCtrlDispatcher(
  _In_  const SERVICE_TABLE_ENTRY *lpServiceTable
);

2.2 服务入口回调函数
头文件:Winsvc.h
VOID WINAPI ServiceMain(
  _In_  DWORD dwArgc,
  _In_  LPTSTR *lpszArgv
);

2.3 服务控制回调函数
VOID WINAPI CtrlHandler(DWORD fdwControl) //控制命令

下面是一个摘录于<计算机病毒揭秘与对抗>>作者:王倍昌一书中的例子,可以编译到控制台下直接使用,可以看做是编写服务的一个框架。
服务的功能是监控系统中的可移动磁盘,然后向其中写入文件a.txt。

编译后执行 FirstService.exe install 安装服务,然后在服务窗口中启动该服务。
卸载服务  FirstService.exe uninstall

// FirstService.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>
#include <tchar.h>
#define SERVICE_NAME _T("FirstService")
SERVICE_STATUS g_status;
SERVICE_STATUS_HANDLE g_hServiceStatus;
HANDLE g_hEvent = NULL;
void Init()
{
g_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_status.dwCurrentState = SERVICE_STOPPED;
// 设置服务可以使用的控制
// 如果希望服务启动后不能停止,去掉SERVICE_ACCEPT_STOP
// SERVICE_ACCEPT_PAUSE_CONTINUE是服务可以“暂停/继续”
g_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;
g_status.dwWin32ExitCode = 0;
g_status.dwServiceSpecificExitCode = 0;
g_status.dwCheckPoint = 0;
g_status.dwWaitHint = 0;
//创建初始为有信号的手动内核事件。
g_hEvent = CreateEvent(NULL, TRUE, TRUE, "Pause");
}


void SetStatus(long lCurrentStatus)
{
g_status.dwCurrentState = lCurrentStatus;
SetServiceStatus(g_hServiceStatus, &g_status);
}


void WINAPI Handler(DWORD dwOpcode)
{
switch (dwOpcode)
{
case SERVICE_CONTROL_STOP:
{ //收到停止服务命令停止服务
SetStatus(SERVICE_STOP_PENDING);
SetStatus(SERVICE_STOPPED);
}
break;
case SERVICE_CONTROL_PAUSE:
{
SetStatus(SERVICE_PAUSE_PENDING);
ResetEvent(g_hEvent); //通知RUN函数开始等待
SetStatus(SERVICE_PAUSED);
}
break;
case SERVICE_CONTROL_CONTINUE:
{
SetStatus(SERVICE_CONTINUE_PENDING);
SetEvent(g_hEvent);//通知RUN函数继续执行
SetStatus(SERVICE_RUNNING);
}
break;
case SERVICE_CONTROL_INTERROGATE:
break;
case SERVICE_CONTROL_SHUTDOWN:
{ //关机时停止服务
SetStatus(SERVICE_STOP_PENDING);
SetStatus(SERVICE_STOPPED);
}
break;
default:
break;
}
}


void Run()
{
while (1)   //循环扫描系统磁盘
{
TCHAR tcBuffer[4] = {0}; //准备较小内存,先试探出实际需要的内存大小。
DWORD dwNeededSize = GetLogicalDriveStrings(4, tcBuffer); //第一次执行,获得实际需要内存。
if (dwNeededSize > 4)
{   //返回值大于指定内存大小,需要重新准备足够内存再次执行。
TCHAR *pBuffer = new TCHAR[dwNeededSize];  //准备足够大的内存
dwNeededSize = GetLogicalDriveStrings(dwNeededSize, pBuffer); //获得逻辑驱动器字符串
TCHAR *pDrive = pBuffer;
int iPreLength = 0;
while (1)
{
pDrive = pBuffer+iPreLength;  //获得下一个驱动器
if (pDrive[0] == 0) //获取驱动器结束
{
break; //退出循环
}
DWORD dwDriveType = GetDriveType(pDrive); //获取驱动器类型
if (dwDriveType == DRIVE_REMOVABLE)
{   //如果是移动驱动器
TCHAR tcFile[MAX_PATH] = {0};
_stprintf(tcFile, _T("%sa.txt"), pDrive);
//打开已存在的a.txt文件
HANDLE hFile = CreateFile(tcFile, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
//打开失败则创建一个。
hFile = CreateFile(tcFile, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwWrite = 0;
WriteFile(hFile, _T("Hello"), 5, &dwWrite, NULL);
}
CloseHandle(hFile);
}
iPreLength += _tcslen(pDrive);  //跳过当前驱动器
iPreLength += 1;//sizeof(TCHAR);    //跳过'\0'。 应该是字符数,加1跳过\0才对
}
if (pBuffer != NULL)
{
delete []pBuffer;  //释放内存
pBuffer = NULL;
}
}
Sleep(500);  //暂停500毫秒后继续扫描
//如何g_hEvent无信号则暂停执行
WaitForSingleObject(g_hEvent, INFINITE);
}
}


void WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
{
// 注册控制请求句柄
g_hServiceStatus = RegisterServiceCtrlHandler(SERVICE_NAME, Handler);
if (g_hServiceStatus == NULL) return;
SetStatus(SERVICE_START_PENDING);
SetStatus(SERVICE_RUNNING);
// 当 Run 函数返回时,服务已经结束。
Run();
g_status.dwWin32ExitCode = S_OK;
g_status.dwCheckPoint = 0;
g_status.dwWaitHint = 0;
g_status.dwCurrentState = SERVICE_STOPPED;
//设置服务状态为停止,从而退出服务.
SetServiceStatus(g_hServiceStatus, &g_status);
}


BOOL IsInstalled()
{
    BOOL bResult = FALSE;
//打开服务控制管理器
    SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);


    if (hSCM != NULL)
    {
//打开服务
        SC_HANDLE hService = OpenService(hSCM, SERVICE_NAME, SERVICE_QUERY_CONFIG);
        if (hService != NULL)
        {
            bResult = TRUE;
            CloseServiceHandle(hService);
        }
        CloseServiceHandle(hSCM);
    }
    return bResult;
}


BOOL Install()
{
    if (IsInstalled()) //服务已安装则直接返回真
        return TRUE;


//打开服务控制管理器
    SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (hSCM == NULL)
    {
        return FALSE;
    }


    TCHAR szFilePath[MAX_PATH];
   DWORD dwLen = GetModuleFileName(NULL, szFilePath, MAX_PATH);
   //判断程序路径是否包含空格,如果包含则给路径加上引号.
   if (_tcschr(szFilePath, ' ') != NULL)
   {
  dwLen += 3;
  TCHAR *lpFilePath = new TCHAR[dwLen];
  if (lpFilePath != NULL)
  {
  _stprintf(lpFilePath, _T("\"%s\""), szFilePath);
  _tcscpy(szFilePath, lpFilePath);
  delete []lpFilePath;
  }
}
//创建一个手动启动的服务
    SC_HANDLE hService = CreateService(
        hSCM, SERVICE_NAME, SERVICE_NAME,
        SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
        SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
        szFilePath, NULL, NULL, _T(""), NULL, NULL);


    if (hService == NULL)
    {
        CloseServiceHandle(hSCM);
        return FALSE;
    }
    CloseServiceHandle(hService);
    CloseServiceHandle(hSCM);
    return TRUE;
}


BOOL Uninstall()
{
    if (!IsInstalled()) //如果服务已卸载直接返回真
        return TRUE;
    SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);


    if (hSCM == NULL)
    {
        return FALSE;
    }
    SC_HANDLE hService = OpenService(hSCM, SERVICE_NAME, SERVICE_STOP | DELETE);
    if (hService == NULL)
    {
        CloseServiceHandle(hSCM);
        return FALSE;
    }
    SERVICE_STATUS status; 
//首先停止服务,确保服务能够立即被删除.
    ControlService(hService, SERVICE_CONTROL_STOP, &status);
//删除服务
    BOOL bDelete = DeleteService(hService);
    CloseServiceHandle(hService);
    CloseServiceHandle(hSCM);
    if (bDelete)
        return TRUE;
    return FALSE;
}


int main(int argc, char* argv[])
{
Init(); //初始化服务数据信息
//判断参数决定如何执行代码
if (argv[1] != NULL && _tcsicmp(argv[1], _T("install")) == 0)
{
Install();
}
else if (argv[1] != NULL && _tcsicmp(argv[1], _T("uninstall")) == 0)
{
Uninstall();
}
else
{ //如果没有参数则是由SCM启动的服务程序
SERVICE_TABLE_ENTRY st[] =
{
{ SERVICE_NAME, ServiceMain },
{ NULL, NULL }
};
StartServiceCtrlDispatcher(st);
}
CloseHandle(g_hEvent);
return 0;
}









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值