几乎每个操作系统在系统启动时都有一个过程机制,不依赖于用户的交互。Windows下面,类似的机制被称为服务或Windows服务。服务是一种在后台运行的程序类型。服务程序通常可以在本地和 *** 上为用户提供一些功能,服务将在操作系统启动时启动。服务程序可能是EXE程序有其独立的过程,也可能是DLL例如,文件依附于某个过程svchost.exe),更有可能是SYS文件位于系统的核心。由于服务的核心地位、启动模式等因素,也是反病毒软件和恶意软件“兵家必争之地”。对系统安全的研究非常重要。
01 如何查看系统服务?
在Windows下面,跟随操作系统启动的服务很多。跟随操作系统启动哪些具体服务?怎么看?其实很简单。“我的电脑”单击鼠标右键,然后选择弹出菜单“管理”,打开“计算机管理”工具,单击左侧树形列表“服务和应用程序”打开子列表,选择“服务”,服务项目列表出现在右侧。更简单的 *** 是直接在那里“运行”窗口中输入“services.msc”,打开服务管理器。服务管理器主要用于显示系统中现有的应用程序服务,显示服务描述,并控制服务的启动状态和启动模式。服务管理器如图1所示。
图1 Windows以下服务管理程序
只能在图1显示的服务列表中查看Win32无法查看驱动程序的服务。您可以使用其他工具查看驱动程序级别的服务。图2使用SREng查看驱动程序相关服务列表。
图2 使用SREng查看驱动程序服务列表
接下来,您将编写一个类似的程序,可以查看应用程序服务列表或驱动程序服务列表。编写后的程序界面如图3所示。
图3
可以查看编制的服务管理程序“Win32服务应用程序”,也可以查看“驱动服务程序”,并且可以简单地控制它们的运行状态。这里开发的服务控制管理器使用MFC其中使用了对话框CListCtrl控件。现在开始建立自己的服务控制管理器。
02 实现服务控制管理器
服务控制管理器的开发过程类似于注册表启动管理器的开发过程,主要是列举服务并显示在列表控件中。通过服务控制服务状态API函数完成。首先,编写代码。我希望你能掌握与服务相关的信息API函数。在代码的背面,将涉及到开发服务管理器API相应的解释。
学习API函数的使用,MSDN是更好的老师,详细、透彻、权威。在编程的道路上,要不断阅读他人的代码来提高你的编程能力,你需要掌握奇怪的API当时一定要想到查阅函数。MSDN。
1. 服务类型
服务控制管理器的界面已经熟悉,界面的布局可以根据自己的方式进行调整。在枚举服务中,“Win32应用程序服务”和“驱动程序服务”分开枚举,这样有助于对各种服务的了解。
这两种服务的主要区别在于调用EnumServicesStatus()函数传递的第二个参数。如果枚举“Win32应用程序服务”,所以传递的参数是SERVICE_WIN32;如果枚举“驱动程序服务”,所以传递的参数是SERVICE_DRIVER。这两个参数实际上是系统定义的宏,它们是定义的WinNt.h头文件中,具体定义如下:
#defineSERVICE_DRIVER(SERVICE_KERNEL_DRIVER|\SERVICE_FILE_SYSTEM_DRIVER|\SERVICE_RECOGNIZER_DRIVER)#defineSERVICE_WIN32(SERVICE_WIN32_OWN_PROCESS|\SERVICE_WIN32_SHARE_PROCESS)SERVICE_DRIVER 和 SERVICE_WIN32 是其他宏的组合,那些宏有具体的价值。下面是其他宏的含义。
SERVICE_DRIVER 宏由 3 个宏组成,具体如下:
#defineSERVICE_KERNEL_DRIVER0x00000001///设备驱动程序#defineSERVICE_FILE_SYSTEM_DRIVER0x00000002///#defineSERVICE_RECOGNIZER_DRIVER0x00000008///文件系统识别器驱动程序SERVICE_WIN32 宏由两个宏组成,具体如下:
#defineSERVICE_WIN32_OWN_PROCESS0x00000010////服务独占一个流程#defineSERVICE_WIN32_SHARE_PROCESS0x00000020///与其他服务共享服务流程如果您想列举所有类型的服务,请使用它们SERVICE_TYPE_ALL宏可以,宏的定义如下:
#defineSERVICE_TYPE_ALL(SERVICE_WIN32|\SERVICE_ADAPTER|\SERVICE_DRIVER|\SERVICE_INTERACTIVE_PROCESS)2. 服务枚举函数
使用服务枚举API函数是EnumServicesStatus(),该函数中需要指定的枚举类型是SERVICE_DRIVER和SERVICE_WIN32。
具体来说,服务枚举函数代码如下:
VOIDCManageServicesDlg::ShowServiceList(DWORDdwServiceType){m_ServiceList.DeleteAllItems();///打开服务管理器SC_HANDLEhSCM=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);if(NULL==hSCM){AfxMessageBox("OpenSCMangerError!");return;}DWORDServiceCount=0;DWORDdwSize=0;LPENUM_SERVICE_STATUSlpInfo;//之一次调用BOOLbRet=EnumServicesStatus(hSCM,dwServiceType,SERVICE_STATE_ALL,NULL,0,&dwSize,&ServiceCount,NULL);///由于没有给定接收服务列表的缓冲区,这里将调用失败失败的原因是ERROR_MORE_DATA//说明需要更大的缓冲区来保存数据if(!bRet&&GetLastError()==ERROR_MORE_DATA){///分配缓冲区,保存服务列表lpInfo=(LPENUM_SERVICE_STATUS)(newBYTE[dwSize]);bRet=EnumServicesStatus(hSCM,dwServiceType,SERVICE_STATE_ALL,(LPENUM_SERVICE_STATUS)lpInfo,dwSize,&dwSize,&ServiceCount,NULL);if(!bRet){CloseServiceHandle(hSCM);return;}///逐个获取数据,添加到列表控件for(DWORDi=0;i<ServiceCount;i ){CStringstr;m_ServiceList.InsertItem(i,lpInfo[i].lpServiceName);m_ServiceList.SetItemText(i,1,lpInfo[i].lpDisplayName);switch(lpInfo[i].ServiceStatus.dwCurrentState){caseSERVICE_PAUSED:{m_ServiceList.SetItemText(i,2,"暂停");break;}caseSERVICE_STOPPED:{m_ServiceList.SetItemText(i,2,"停止");break;}caseSERVICE_RUNNING:{m_ServiceList.SetItemText(i,2,"运行");break;}default:{m_ServiceList.SetItemText(i,2,"其他");}}}//发布申请空间deletelpInfo;}//关闭服务管理器句柄CloseServiceHandle(hSCM);}该函数有一个指示枚举类型的参数“Win32应用程序服务”,还是“驱动程序服务”。该函数的默认参数为“Win32应用程序服务”,函数的定义如下:
VOIDShowServiceList(DWORDdwServiceType=SERVICE_WIN32);3. 枚举服务相关API函数解释
(1)打开和关闭服务管理器
打开服务管理器的函数定义如下:
SC_HANDLEOpenSCManager(LPCTSTRlpMachineName,//computernameLPCTSTRlpDatabaseName,//SCMdatabasenameDWORDdwDesiredAccess//accesstype);参数说明如下。
lpMachineName:本机设置为 NULL。
lpDatabaseName:目标主机 SCM 数据库名字字符串p>
dwDesiredAccess:指定对 SCM 数据库访问权限。
函数调用成功,返回 SCM 句柄,否则返回 NULL。
SCM这意味着服务控制管理器,它是系统服务的一部分,与开发的软件不同。
关闭服务句柄的函数定义如下:
BOOLCloseServiceHandle(SC_HANDLEhSCObject//handletoserviceorSCMobject);该函数用于关闭原因OpenSCManager()和OpenService()打开句柄。
(2)枚举函数服务
枚举服务的函数定义如下:
BOOLEnumServicesStatus(SC_HANDLEhSCManager,//handletoSCMdatabaseDWORDdwServiceType,//servicetypeDWORDdwServiceState,//servicestateLPENUM_SERVICE_STATUSlpServices,//statu *** ufferDWORDcbBufSize,//sizeofstatu *** ufferLPDWORDpcbBytesNeeded,//buffersizeneededLPDWORDlpServicesReturned,//numberofentriesreturnedLPDWORDlpResumeHandle//nextentry);参数说明如下。
hSCManager:OpenSCManager()函数返回的句柄。
dwServiceType:指定枚举的服务类型,即自定义函数的参数。
dwServiceState:枚举指定状态的服务。
lpServices:指向 ENUM_SERVICE_STATUS 型指针。
cbBufSize:指定缓冲区的大小。
pcbBytesNeeded:回到实际使用的内存空间大小。
lpServicesReturned:返回枚举服务数量。
lpResumeHandle:回枚举是否成功。
ENUM_SERVICE_STATUS 结构体的定义如下:
typedefstruct_ENUM_SERVICE_STATUS{LPTSTRlpServiceName;LPTSTRlpDisplayName;SERVICE_STATUSServiceStatus;}ENUM_SERVICE_STATUS,*LPENUM_SERVICE_STATUS;SERVICE_STATUS 结构体的定义如下:
typedefstruct_SERVICE_STATUS{DWORDdwServiceType;DWORDdwCurrentState;DWORDdwControlsAccepted;DWORDdwWin32ExitCode;DWORDdwServiceSpecificExitCode;DWORDdwCheckPoint;DWORDdwWaitHint;}SERVICE_STATUS,*LPSERVICE_STATUS;两次调用代码EnumServicesStatus()函数。之一次没有传输第四和第五个参数,使函数返回FALSE,用GetLastError()错误的原因是ERROR_MORE_DATA。此时,第六个参数pcbBytesNeeded返回实际使用的内存大小,以便通过new动态应用所需的堆空间。这样,实际缓冲区的大小就更多了。请理解。
4. 服务的启停
只介绍两种服务操作,一种是启动服务,另一种是停止服务,即改变服务状态。停止服务的操作经常被使用,因为系统中有许多不可用的服务,但它仍然会随着系统的启动而启动,这不仅会影响系统的启动速度,还会占用宝贵的系统资源。因此,更好停止无用的系统服务(事实上,真正的停止服务是改变其启动状态,而不是这里介绍的运行状态)。
启动服务代码如下:
voidCManageServicesDlg::OnBtnStart(){//TODO:Addyourcontrolnotificationhandlercodehere///选择服务索引POSITIONPos=m_ServiceList.GetFirstSelectedItemPosition();intnSelect=-1;while(Pos){nSelect=m_ServiceList.GetNextSelectedItem(Pos);}if(-1==nSelect){AfxMessageBox("请选择要启动的服务");return;}///获取选定服务的服务名charszServiceName[MAXBYTE]={0};m_ServiceList.GetItemText(nSelect,0,szServiceName,MAXBYTE);SC_HANDLEhSCM=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);if(NULL==hSCM){AfxMessageBox("OpenSCManagerError");return;}//打开指定服务SC_HANDLEhSCService=OpenService(hSCM,szServiceName,SERVICE_ALL_ACCESS);//启动服务BOOLbRet=StartService(hSCService,0,NULL);if(bRet==TRUE){m_ServiceList.SetItemText(nSelect,2,"运行");}else{AfxMessageBox("启动失败!");}CloseServiceHandle(hSCService);CloseServiceHandle(hSCM);}停止服务的代码如下:
voidCManageServicesDlg::OnBtnStop(){//TODO:Addyourcontrolnotificationhandlercodehere///选择服务索引///这部分操作与启动服务相同。为了节省空间,这里省略了//……SC_HANDLEhSCM=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);if(NULL==hSCM){AfxMessageBox("OpenSCManagerError");return;}//打开指定服务SC_HANDLEhSCService=OpenService(hSCM,szServiceName,SERVICE_ALL_ACCESS);SERVICE_STATUSServiceStatus;//停止服务BOOLbRet=ControlService(hSCService,SERVICE_CONTROL_STOP,&ServiceStatus);if(bRet==TRUE){m_ServiceList.SetItemText(nSelect,2,"停止");}else{AfxMessageBox("停止失败!");}CloseServiceHandle(hSCService);CloseServiceHandle(hSCM);}5. 启动和停止服务API函数解释
打开指定服务的函数定义如下:
SC_HANDLEOpenService(SC_HANDLEhSCManager,//handletoSCMdatabaseLPCTSTRlpServiceName,//servicenameDWORDdwDesiredAccess//access);参数说明如下。
hSCManager:指定由 OpenSCManager()服务句柄打开函数。
lpServiceName:指定要打开的服务名称。
dwDesiredAccess:为了方便起见,将服务的访问权限指定为 SC_MANAGER_ALL_ACCESS。
启动服务的函数定义如下:
BOOLStartService(SC_HANDLEhService,//handletoserviceDWORDdwNumServiceArgs,//numberofargumentsLPCTSTR*lpServiceArgVectors//arrayofarguments);参数说明如下。
hService:指定要启动服务的句柄,由 OpenService()返回。
dwNumServiceArgs:指向启动服务所需的参数数。
lpServiceArgVectors:指向启动服务的参数。
停止服务的函数定义如下:
BOOLControlService(SC_HANDLEhService,//handletoserviceDWORDdwControl,//controlcodeLPSERVICE_STATUSlpServiceStatus//statusinformation);参数说明如下。
hService:由 指定一个OpenService()打开服务句柄。
dwControl:指定要发送的控制码。
lpServiceStatus:返回服务状态。
ControlService()可以对服务进行多种控制操作,每种控制操作对应一个控制码。当需要停止服务时,使用的控制码是 SERVICE_CONTROL_STOP。一定要注意停止服务,不要想当然地使用 StopService()因为没有这样的函数 API 函数。