




已阅读5页,还剩6页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C+快速编写windows服务程序调用程序/lostinwinner/item/a24e9b3e3feb89ae124b143c2012-07-19 23:42:22|分类:C/C+|标签:windows服务程序c+快速简单|字号订阅 前不久,为完成项目中某个功能,需要写个windows服务程序, 定时来调用另外的一个exe程序, 完成过程遇到颇多问题,作为初学者,分享一下我的整个过程. 参考了多位大神的文章.资料来自网上, 最后给出链接.表示感谢以下是一些基本知识, 不得不耐下心去理解,这对程序理解和编写非常用帮助.首先Microsoft Windows 服务(即,以前的 NT 服务)使您能够创建在它们自己的Windows 会话中可长时间运行的可执行应用程序。这些服务可以在计算机启动时自动启动,可以暂停和重新启动而且不显示任何用户界面。这使服务非常适合在服务器上使用,或任何时候,为了不影响在同一台计算机上工作的其他用户,需要长时间运行功能时使用。还可以在不同于登录用户的特定用户帐户或默认计算机帐户的安全上下文中运行服务。服务是有状态的,当我们使用windows自带的服务管理程序sc.exe 查看服务状态时可以显示服务的当前状态,这个状态是由我们在程序代码中进行控制的。你最好在服务初始化的时候将服务设置为SERVICE_START_PENDING,当初始化完毕时设为SERVICE_RUNNING,这些状态是系统自定义的状态,可通过msdn查看其他状态。这个状态信息你会在sc.exe中看到。在编写windows服务程序过程中你需要关注的函数有:1.首先是main函数,由于windows服务不需要界面,所以大部分程序为win32控制台应用程序,所以程序主函数为main 而不是WinMain()。在主函数要做的主要工作就是初始化一个SERVICE_TABLE_ENTRY 分派表结构体,然后调用StartServiceCtrlDispatcher();这将把调用进程的主线程转换为控制分派器。该分派器启动一个新线程,该线程运行分派表中对应于你的服务的ServiceMain()函数。ServiceMain()函数将在下面提到。此过程示例代码如下:SERVICE_TABLE_ENTRY entrytable2; entrytable0.lpServiceName=testservice; entrytable0.lpServiceProc=(LPSERVICE_MAIN_FUNCTION)ServiceMain; entrytable1.lpServiceName=NULL; entrytable1.lpServiceProc=NULL;StartServiceCtrlDispatcher(entrytable);在这之后系统将自动创建一个线程去执行ServiceMain函数的内容,你应该将你要执行的任务在ServiceMain中循环,这样服务就开始运行了。2ServiceMain函数为void WINAPI ServiceMain(int argc, char* argv)格式的函数,函数名字可以任意定义。它的作用就是:将你需要执行的任务放到该函数中循环执行即可。这就是服务程序的工作函数。在ServiceMain执行你的任务前,需要给SERVICE_TABLE_ENTRY 分派表结构体进行赋值,注意由于此时服务还没有开始执行你的任务所以我们将服务的状态设置为SERVICE_START_PENDING,即正在初始化。我们进行如下赋值:servicestatus.dwServiceType = SERVICE_WIN32; servicestatus.dwCurrentState = SERVICE_START_PENDING; servicestatus.dwControlsAccepted=SERVICE_ACCEPT_SHUTDOWN|SERVICE_ACCEPT_STOP;/在本例中只接受系统关机和停止服务两种控制命令 servicestatus.dwWin32ExitCode = 0; servicestatus.dwServiceSpecificExitCode = 0; servicestatus.dwCheckPoint = 0; servicestatus.dwWaitHint = 0; hstatus = :RegisterServiceCtrlHandler(testservice, CtrlHandler);CtrlHandler为void WINAPI CtrlHandler(DWORD request)型的函数,函数名字可以任意设定。将在下一点讲到。Hstatus 为SERVICE_STATUS_HANDLE 类 型 的 全 局 变 量 。 当 需 要 改 变 服 务 状 态 时SetServiceStatus()函数需要它做为参数来标识一个服务。3. void WINAPI CtrlHandler(DWORD request),函数的主要功能是,接收系统传递的控制命令,比如当你通过sc.exe关闭服务时,该函数会收到SERVICE_CONTROL_STOP消息,你就可以对服务进行必要的管理。在本例子程序中就只接收SERVICE_ACCEPT_SHUTDOWN 和SERVICE_ACCEPT_STOP消息,这是通过前面给servicestatus赋值设定的。 这样一个基本的服务程序就完成了。 本文结束的时候会附上如何安装服务。当服务程序需要使用某些功能时,由于用户的关系而受到限制,比如访问注册表的HKEY_CURRENT_USER键,使用网络等等,这时候就需要以当前登陆用户的身份去进行操作,通常会创建一个进程来完成需要的功能。如果使用CreateProcess, 来创建进程的话,新创建的进程和服务程序依然是相同的用户身份,还是无法达到目的,只有使用CreateProcessAsUser了。但CreateProcessAsUser的第一个参数是HANDLEhToken,该参数通常应该用LogonUser来获得,但是LogonUser又需要用户名和用户密码,这样就很不现实。那应该怎么办呢?我想到了一个方法可以绕过LogonUser直接获得hToken。因为用户已经登陆,那么肯定有Shell(就是EXPLORER.EXE)运行了,我们可以通过遍历进程来取得Shell的hToken来运行进程。因此需要BOOL GetTokenByName(HANDLE &hToken,LPSTR lpName);BOOL RunProcess(LPCSTR lpImage);两个函数示例是关于基于opencv人脸识别, 遍历样本文件夹,删除多余的图片保留10张, 然后执行 外部自定义程序GetFeatureDATA.exe 函数提取特征GetFeatureDATA.exe中最头上加上#pragma comment(linker,/subsystem:Windows /entry:mainCRTStartup)就可以隐藏控制台窗口开发环境vs2010, 控制台应用程序./服务程序主函数。#include stdio.h#include vector#include Tlhelp32.h#include #define _AFXDLL/由于做的图像识别需要opencv头文件, 需要什么文件自行更改#include cv.h#include highgui.husing namespace std;/你的服务程序需要以下代码SERVICE_STATUS servicestatus; SERVICE_STATUS_HANDLE hstatus; /全局变量. 是setServiceStatus()的参数, 改变服务状态void WINAPI ServiceMain(int argc, char* argv); void WINAPI CtrlHandler(DWORD request);bool brun=false;/原来代码有的,我没有用,还是保留/以下是以获取登录用户名BOOL GetTokenByName(HANDLE &hToken,LPSTR lpName);BOOL RunProcess(LPCSTR lpImage);/自己添加的代码int train_time;/以分钟计vector Vec_Dir;/存放图片文件夹目录名称vector Vec_Img;/void TraverseDir(CString& strDir, std:vector& vecDir);int TraverseImg(CString& strDir, std:vector& vecFile);void TraverseDir(CString& strDir, std:vector& vecDir) WIN32_FIND_DATA FindFileData; CString strDirTmp; strDirTmp = strDir; strDirTmp += *.*; HANDLE hFind=:FindFirstFile(strDirTmp,&FindFileData); if(INVALID_HANDLE_VALUE = hFind) return; while(TRUE) if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) if(FindFileData.cFileName0!= _T(.) strDirTmp = strDir; strDirTmp += ; strDirTmp += FindFileData.cFileName; vecDir.push_back(strDirTmp);/保存所有目录 /TraverseDir(strDirTmp,vecFile) ; else/是文件 /*strDirTmp = strDir; strDirTmp += ; strDirTmp += FindFileData.cFileName; vecFile.push_back(strDirTmp);*/ if(!FindNextFile(hFind,&FindFileData) break; FindClose(hFind); int TraverseImg(CString& strDir, std:vector& vecFile)/输入路径,得到img路径文件名 int ImgNum = 0; WIN32_FIND_DATA FindFileData; CString strDirTmp; strDirTmp = strDir; strDirTmp += *.*; HANDLE hFind=:FindFirstFile(strDirTmp,&FindFileData); if(INVALID_HANDLE_VALUE = hFind) /return; while(TRUE) if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) if(FindFileData.cFileName0!= _T(.) /*strDirTmp = strDir; strDirTmp += ; strDirTmp += FindFileData.cFileName; TraverseDir(strDirTmp,vecFile) ;*/ else strDirTmp = strDir; strDirTmp += ; strDirTmp += FindFileData.cFileName; vecFile.push_back(strDirTmp);/将图片路径传入 ImgNum +; if(!FindNextFile(hFind,&FindFileData) break; FindClose(hFind); return ImgNum; void WINAPI ServiceMain(int argc, char* argv) servicestatus.dwServiceType = SERVICE_WIN32; servicestatus.dwCurrentState = SERVICE_START_PENDING; servicestatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN|SERVICE_ACCEPT_STOP;/在本例中只接受系统关机和停止服务两种控制命令 servicestatus.dwWin32ExitCode = 0; servicestatus.dwServiceSpecificExitCode = 0; servicestatus.dwCheckPoint = 0; servicestatus.dwWaitHint = 0; hstatus = :RegisterServiceCtrlHandler(testservice, CtrlHandler); if (hstatus=0) /WriteToLog(RegisterServiceCtrlHandler failed); return; /WriteToLog(RegisterServiceCtrlHandler success); /向SCM 报告运行状态 servicestatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus (hstatus, &servicestatus); /下面就开始任务循环了,你可以添加你自己希望服务做的工作 brun=true; /MEMORYSTATUS memstatus; /char str100; /memset(str,0,100); /while (brun) / / GlobalMemoryStatus(&memstatus); / int availmb=memstatus.dwAvailPhys/1024/1024; / sprintf_s(str,100,available memory is %dMB,availmb); / WriteToLog(str); / Sleep(SLEEP_TIME); / /WriteToLog(service stopped); /以下是自己要写的代码的执行调用地方 /SYSTEMTIME t; /GetLocalTime(&t); /int hour = t.wHour ;/获取小时, 可以在固定某个小时执行程序 while(1)/ CString SamplesDirPath = _T(G:Samples); TraverseDir(SamplesDirPath, Vec_Dir);/获取目录名称到vec_Dir for (int i(0); i10) for (int j=Img_Num - 10 - 1;j=0; j-) remove(Vec_Imgj); Vec_Img.clear(); /执行提取xml文件exe文件 /WinExec(G:about_MFCGetFeatureDATA.exe, 0); /system( GetFeatureDATA.exe); /ShellExecute(NULL,open,G:about_MFCGetFeatureDATA.exe,NULL,NULL,SW_SHOWNORMAL); RunProcess(G:about_MFCGetFeatureDATA.exe); /从硬盘里读取时间来做个每隔多少时间进行 CvFileStorage *Threshold = cvOpenFileStorage(./service_time.xml,0,CV_STORAGE_READ);/读取预值 CvFileNode *ThresholdNode = cvGetFileNodeByName(Threshold,0,circle_time); double service_time = cvReadRealByName(Threshold,ThresholdNode,circle_time); Sleep(service_time*60*1000);/sleep自定时间后再次执行操作 BOOL GetTokenByName(HANDLE &hToken,LPSTR lpName) if(!lpName) return FALSE; HANDLE hProcessSnap = NULL; BOOL bRet = FALSE; PROCESSENTRY32 pe32 = 0; hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcessSnap = INVALID_HANDLE_VALUE) return (FALSE); pe32.dwSize = sizeof(PROCESSENTRY32); if (Process32First(hProcessSnap, &pe32) do if(!strcmp(_strupr(pe32.szExeFile),_strupr(lpName) HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE,pe32.th32ProcessID); bRet = OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&hToken); CloseHandle (hProcessSnap); return (bRet); while (Process32Next(hProcessSnap, &pe32); bRet = TRUE; else
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025电力安装工程分布式光伏发电系统设计安装合同
- 二零二五年度餐饮行业劳务派遣中介服务协议
- 2025年度定制化教育软件研发合同
- 二零二五年度复杂地质条件基坑支护施工合同
- 2025年玻璃材料销售合同规范文本
- 2025版生态保护项目环评环保技术指导合同
- 二零二五年度精密仪器租赁服务合同范本模板
- 二零二五年度旅游纪念品合同封面素材设计采购协议
- 二零二五年酒店设施设备维修保养服务合同范本
- 二零二五版汽车销售合同范本(含车辆过户手续)
- GA/T 761-2024停车库(场)安全管理系统技术要求
- 疫苗冰箱温度记录表
- 围岩分类及围岩压力
- JB-QBL-EI-6000M火灾报警控制器安装使用说明书
- 汽车车身碰撞估损全套课件
- 安全学原理第2版-ppt课件(完整版)
- (完整版)形式发票模版(国际件通用)
- 员工职业发展通道图超级好用
- 1.进入网站httprlzy.0744cc.comzp并登录
- 附件1: MAIS听觉整合问卷 父母问卷(访谈) 一、 测试目的 1、了解聋儿
- 包河区政府采购中心询价文件
评论
0/150
提交评论