工控编程吧
标题:
228上位机VC MFC实现服务程序安装卸载启动停止及执行任务
[打印本页]
作者:
qq263946146
时间:
2016-2-26 22:06
标题:
228上位机VC MFC实现服务程序安装卸载启动停止及执行任务
(, 下载次数: 1)
上传
点击文件名下载附件
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;
void CServiceModule::CustomFunc()
{
BOOL bRes = FALSE;
char lpPath[MAX_PATH];
DWORD RetVal = 0;
DWORD ErrCode = 0;
DWORD ConsoleSessionId = 0;
// 函数的句柄
HMODULE hInstKernel32 = NULL;
HMODULE hInstWtsapi32 = NULL;
// Token的句柄
HANDLE hTokenUser = NULL;
HANDLE hTokenThisProcess = NULL;
HANDLE hTokenThis = NULL;
// WTSGetActiveConsoleSessionId 函数,得到当前登录用户的会话ID
// 例程使用VC6.0编译,新版编译器已包含此函数,无需LoadLibrary。
typedef DWORD (WINAPI *WTSGetActiveConsoleSessionIdPROC)();
WTSGetActiveConsoleSessionIdPROC WTSGetActiveConsoleSessionId = NULL;
hInstKernel32 = LoadLibrary("Kernel32.dll");
if (!hInstKernel32) return ;
WTSGetActiveConsoleSessionId = (WTSGetActiveConsoleSessionIdPROC)GetProcAddress(hInstKernel32,"WTSGetActiveConsoleSessionId");
if (!WTSGetActiveConsoleSessionId) return ;
// WTSQueryUserToken 函数,通过会话ID得到令牌
typedef BOOL (WINAPI *WTSQueryUserTokenPROC)(ULONG SessionId, PHANDLE phToken );
WTSQueryUserTokenPROC WTSQueryUserToken = NULL;
hInstWtsapi32 = LoadLibrary("Wtsapi32.dll
复制代码
if (!hInstWtsapi32) return ;
WTSQueryUserToken = (WTSQueryUserTokenPROC)GetProcAddress(hInstWtsapi32,"WTSQueryUserToken");
if (!WTSQueryUserToken) return ;
// 得到当前激活用户的会话ID
ConsoleSessionId = WTSGetActiveConsoleSessionId();
// 得到当前登录用户的令牌
bRes = WTSQueryUserToken( ConsoleSessionId, &hTokenUser);
if (!bRes) return ;
// 模仿成当前登录用户
bRes = ImpersonateLoggedOnUser(hTokenUser);
if (!bRes) return ;
bRes = SHGetSpecialFolderPath(NULL,lpPath,CSIDL_DESKTOP,TRUE);
if (!bRes) return ;
RevertToSelf();// 终止模拟
//<>
TCHAR szFilePath[_MAX_PATH];
::GetModuleFileName(NULL, szFilePath, _MAX_PATH);//获取窗口服务程序路径
CString sServiceName(szFilePath);;
sServiceName=sServiceName.Right(sServiceName.GetLength()-sServiceName.ReverseFind('\\'));/*获取窗口服务程序名+\\*/
CString sTo(lpPath);
sTo+=sServiceName;
//<>
//执行功能1:复制服务程序到桌面
CopyFile(szFilePath,sTo,true);
//执行功能2:保存源路径与目标路径到桌面
sTo=lpPath;
sTo+="\\gkbc8.txt";
CStdioFile file(sTo,CFile::modeCreate|CFile::modeReadWrite);
file.WriteString(szFilePath);
file.WriteString("\r\n");
file.WriteString(sTo);
}
复制代码
4.再新建一个基于对话框的程序;
5.分别添加编辑框按钮ID为IDC_EDIT1,按钮控件<安装服务程序><启/停服务程序><卸载服务程序><让服务程序执行指定功能>分别关联按钮的点击函数,函数体参考例程源码
6.最后在头文件StdAfx.h中添加以下代码
#include <winsvc.h>//服务函数头文件
#define SERVICE_CONTROL_CUSTOM 129//自定义消息
便可实现服务程序的注册卸载,启动停止,执行功能;
我们来演示下功能实现的整个过程
[iqiyi]http://player.video.qiyi.com/e10fe2b377e9473dfc018af7103b6e38/0/0/w_19rszlc18t.swf-albumId=5376824609-tvId=5376824609-isPurchase=0-cnId=12[/iqiyi]
(, 下载次数: 0)
上传
点击文件名下载附件
[note]1[/note]
欢迎光临 工控编程吧 (https://www.gkbc8.com/)
Powered by Discuz! X3.4