QQ登录

只需一步,快速开始

228上位机VC MFC实现服务程序安装卸载启动停止及执行任务

[ 复制链接 ]

228上位机VC MFC实现服务程序安装卸载启动停止及执行任务

228上位机VC MFC实现服务程序安装卸载启动停止及执行任务
228上位机VC MFC实现服务程序安装卸载启动停止及执行任务
功能展示
窗口服务程序能够在后台无声息实现多种功能,能够随系统一同启动,那么如何实现窗口服务程序的编写呢?我们当前例程实现窗口服务程序的编写,以及编写另一例程实现服务程序的安装,卸载,启动停止及执行指定功能,效果如图;
要点提示
服务程序可以用ATL创建向导建立工程。
1.程序的进入点是全局函数_tWinMain()函数中有三个参数由外部程序调用传入RegServer这个实现本地服务器注册,Service这个实现服务程序的注册,UnRegServer这个实现服务程序的删除;
2.向导为我们建立了一个类:CServiceModule,全局变量_Module就是这个类的实例。还有函数Init():这个函数用于完成一些初始化工作;Run():这个函数就是服务开始运行后的内容。
Install()函数为服务程序安装时调用,有如下一段代码
SC_HANDLE hService =::CreateService(
        hSCM, m_szServiceNamem_szServiceName,
        SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS,
        SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,
        szFilePath, NULL, NULL,_T("RPCSS\0"), NULL, NULL);
注意:如果服务中启动的程序具有窗口(即具有交互功能则要求使用如下代码)
SC_HANDLE hService =::CreteService(
        hSCM, m_szServiceName,m_szServiceName,
        SERVICE_ALL_ACCESS,SERVICE_WIN32_SHARE_PROCESS | SERVICE_INTERACTIVE_PROCESS,
        SERVICE_AUTO_START,SERVICE_ERROR_NORMAL,
        szFilePath, NULL, NULL,_T("RPCSS\0"), NULL, NULL);
这个CreateService函数原型为:
SC_HANDLE CreateService(
SC_HANDLE hSCManager, // handle to SCM database
LPCTSTR lpServiceName, // name of service to start
LPCTSTR lpDisplayName, // display name
DWORD dwDesiredAccess, // type of access to service
DWORD dwServiceType, // type of service
DWORD dwStartType, // when to start service
DWORD dwErrorControl, // severity of servicefailure
LPCTSTR lpBinaryPathName, // name of binary file
LPCTSTR lpLoadOrderGroup, // name of load ordering group
LPDWORD lpdwTagId, // tag identifier
LPCTSTR lpDependencies, // array of dependency names
LPCTSTR lpServiceStartName, // account name
LPCTSTR lpPassword // account password
);
第六个参数是服务的启动类型。
SERVICE_DEMAND_START是手动启动,SERVICE_AUTO_START是自动启动。
第十一个参数是服务的依存关系,比如说服务的启动想要依存SQL Server的启动,那我们可以把这个参数写成:_T("MSSQLSERVER\0");
如果我们写的服务不依存于其他的任何服务,那我们就将此参数设置为NULL就可以了。
接下来我们实现我们需要实现的业务。
首先,我们在类CServiceModule中找到Run函数,并在Run函数中找到以下代码:
    MSG msg;
    while (GetMessage(&msg, 0, 0,0))
        DispatchMessage(&msg);
并在此代码前加入自己的代码,实现自己想要的功能;当然也可以在函数Handler()中实现功能,如例程添加代码实现指定功能case SERVICE_CONTROL_CUSTOM:CustomFunc();break;
3.有时我们会用到MFC类如Cstring时会编译出错,可以在stdafx.h头文件中找到#include<atlbase.h>位置,并在它之前加入#include   <afx.h>。重新编译即可。
4.如果需要修改出现在scm中的服务名,可以在工程中找到资源文件中的IDS_SERVICENAME项的内容就可以
5.服务程序的安装,卸载,启动,停止,执行任务,可以参考调用例程的按钮代码
实现功能
1.新建基于ATL COM AppWizard工程的服务(EXE)(S)程序;
2.在头文件stdafx.h头文件中找到#include <atlbase.h>,前面添加代码//<>
#include <afx.h> //CString 等MFC类头文件
#include<shlobj.h>//SHGetSpecialFolderPath 函数头文件
#define SERVICE_CONTROL_CUSTOM  129//定义用户消息
3.添加自定义函数CustomFunc(),并在函数Handler()中调用caseSERVICE_CONTROL_CUSTOM: CustomFunc();break;
  1. void CServiceModule::CustomFunc()
  2. {
  3.         BOOL bRes = FALSE;
  4.         char lpPath[MAX_PATH];
  5.         DWORD RetVal           = 0;
  6.         DWORD ErrCode          = 0;
  7.         DWORD ConsoleSessionId = 0;
  8.         // 函数的句柄
  9.         HMODULE hInstKernel32    = NULL;
  10.         HMODULE hInstWtsapi32    = NULL;
  11.         // Token的句柄
  12.         HANDLE hTokenUser        = NULL;
  13.         HANDLE hTokenThisProcess = NULL;
  14.         HANDLE hTokenThis        = NULL;
  15.         // WTSGetActiveConsoleSessionId 函数,得到当前登录用户的会话ID
  16.         // 例程使用VC6.0编译,新版编译器已包含此函数,无需LoadLibrary。
  17.         typedef DWORD (WINAPI *WTSGetActiveConsoleSessionIdPROC)();
  18.         WTSGetActiveConsoleSessionIdPROC WTSGetActiveConsoleSessionId = NULL;
  19.         hInstKernel32 = LoadLibrary("Kernel32.dll");
  20.         if (!hInstKernel32) return ;
  21.         WTSGetActiveConsoleSessionId = (WTSGetActiveConsoleSessionIdPROC)GetProcAddress(hInstKernel32,"WTSGetActiveConsoleSessionId");
  22.         if (!WTSGetActiveConsoleSessionId) return ;
  23.         // WTSQueryUserToken 函数,通过会话ID得到令牌
  24.         typedef BOOL (WINAPI *WTSQueryUserTokenPROC)(ULONG SessionId, PHANDLE phToken );
  25.         WTSQueryUserTokenPROC WTSQueryUserToken = NULL;
  26.         hInstWtsapi32 = LoadLibrary("Wtsapi32.dll
复制代码
  1. if (!hInstWtsapi32)        return ;
  2.         WTSQueryUserToken = (WTSQueryUserTokenPROC)GetProcAddress(hInstWtsapi32,"WTSQueryUserToken");
  3.         if (!WTSQueryUserToken)          return ;
  4.         // 得到当前激活用户的会话ID
  5.         ConsoleSessionId = WTSGetActiveConsoleSessionId();
  6.         // 得到当前登录用户的令牌
  7.         bRes = WTSQueryUserToken( ConsoleSessionId, &hTokenUser);
  8.         if (!bRes) return ;
  9.         // 模仿成当前登录用户
  10.         bRes = ImpersonateLoggedOnUser(hTokenUser);
  11.         if (!bRes)         return ;
  12.         bRes = SHGetSpecialFolderPath(NULL,lpPath,CSIDL_DESKTOP,TRUE);
  13.         if (!bRes) return ;
  14.         RevertToSelf();// 终止模拟
  15.         //<>
  16.         TCHAR szFilePath[_MAX_PATH];
  17.         ::GetModuleFileName(NULL, szFilePath, _MAX_PATH);//获取窗口服务程序路径
  18.         CString sServiceName(szFilePath);;
  19.         sServiceName=sServiceName.Right(sServiceName.GetLength()-sServiceName.ReverseFind('\\'));/*获取窗口服务程序名+\\*/
  20.         CString sTo(lpPath);
  21.         sTo+=sServiceName;
  22.         //<>
  23.         //执行功能1:复制服务程序到桌面
  24.         CopyFile(szFilePath,sTo,true);
  25.         //执行功能2:保存源路径与目标路径到桌面
  26.         sTo=lpPath;
  27.         sTo+="\\gkbc8.txt";
  28.         CStdioFile file(sTo,CFile::modeCreate|CFile::modeReadWrite);
  29.         file.WriteString(szFilePath);
  30.         file.WriteString("\r\n");
  31.         file.WriteString(sTo);
  32. }
复制代码
4.再新建一个基于对话框的程序;
5.分别添加编辑框按钮ID为IDC_EDIT1,按钮控件<安装服务程序><启/停服务程序><卸载服务程序><让服务程序执行指定功能>分别关联按钮的点击函数,函数体参考例程源码
6.最后在头文件StdAfx.h中添加以下代码
#include <winsvc.h>//服务函数头文件
#define SERVICE_CONTROL_CUSTOM  129//自定义消息
便可实现服务程序的注册卸载,启动停止,执行功能;
我们来演示下功能实现的整个过程
请点击此处下载

请先注册会员后在进行下载

已注册会员,请先登录后下载

文件名称:228.上位机VC MFC实现服务程序安装卸载启动停止及执行任务.rar 
文件大小:197.77 KB  售价:10金币
下载权限: 不限 以上或 VIP会员   [购买捐助会员]   [充值积分]   有问题联系我

  

您的支持是我们创作的动力!  

  

您可花点闲钱积分自助任意充值

  

成为VIP会员 全站资源任意下载永久更新!


回复

使用道具 举报

快速回复 返回列表 客服中心 搜索