(02)C++ builder之WINDOWS系统服务编写与WINDOWS桌面程序调用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dlboy2018/article/details/79563345

(中行雷威2018.3.12)

(同一个世界,同一个梦想,交流学习C++Builder XE10,传承c++builder的魅力!欢迎各地朋友加入我的QQ群484979943,进群密码“BCB”,同时也请将该群号广为宣传,希望能够广集各方高手,共同进步。如需下载开发工具及源代码请加入我的QQ群)

【阅读倡议】

1、有问题请留言;

2、没问题请点赞;

3、看连载请加群;

4、下源码请加群;

【开发工具】

1、C++Builder10.2.2tokyo

-------------------------------------------------------------------------------------------------------------------------------

本文将介绍如何创建一个操作系统层面的服务程序,并同步介绍如何通过系统服务自动监控桌面程序进程,如何杀掉进程,如何启动进程。本文穿越了WIN7以后操作系统session隔离的新特性,有效解决了旧版本下好用的调用功能在新系统下调用成功但是客户看不到界面的问题。

一、新建项目

1、新建服务项目smartService

File->New->Other新建一个Service Application服务项目


将窗口文件Unit???.cpp保存为UnitMain.cpp,将项目文件保存为bocSmartService.cbproj。

打开MainForm窗口,在左侧属性设置界面里将Name属性和DisplayName属性都设置为smartService,

将Interactive属性设置为True。

2、新建线程smartThread

File-》New-》other新建线程smartThread,下图选择ThreadObject


在新建线程窗口里输入你的线程的类名称TsmartThread


将新建的线程的Unit???.cpp文件保存为UnitThread.cpp

3、设置wchar_t编码映射关系


二、代码实现

1、MainForm.cpp代码

//---------------------------------------------------------------------------

#include "UnitMain.h"
#include "UnitThread.h"


/*自定义*/

#include <Registry.hpp>//读取可执行文件同名ini配置文件的头文件声明


TsmartThread *smartThread;//定义全局smart线程变量
String openFilePath,openFileName;//定义要坚守的程序目录(c:\dir)和名称(b.exe)





//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"


TsmartService *smartService;
//---------------------------------------------------------------------------
__fastcall TsmartService::TsmartService(TComponent* Owner)
: TService(Owner)
{
}


void __stdcall ServiceController(unsigned CtrlCode)
{
smartService->Controller(CtrlCode);
}


TServiceController __fastcall TsmartService::GetServiceController(void)
{
return (TServiceController) ServiceController;
}


//FormMain添加的Pause暂停事件---------------------------------------------------------------------------
void __fastcall TsmartService::ServicePause(TService *Sender, bool &Paused)
{
//暂停
smartThread->Suspend();
Paused = true;
}
//FormMain添加的Start启动事件---------------------------------------------------------------------------
void __fastcall TsmartService::ServiceStart(TService *Sender, bool &Started)
{
//启动
smartThread = new TsmartThread(false);//新建线程
Started = true;
}
//FormMain添加的Stop停止事件---------------------------------------------------------------------------
void __fastcall TsmartService::ServiceStop(TService *Sender, bool &Stopped)
{
//结束
smartThread->Terminate();
Stopped = true;
}
//FormMain添加的Continue继续事件---------------------------------------------------------------------------
void __fastcall TsmartService::ServiceContinue(TService *Sender, bool &Continued)
{
//继续
smartThread->Resume();
Continued = true;
}
//FormMain添加的OnCreate事件---------------------------------------------------------------------------
void __fastcall TsmartService::ServiceCreate(TObject *Sender)
{
//读取出程序的同名配置文件bocSmartService.ini
TIniFile *ini;
ini = new TIniFile( ChangeFileExt( Vcl::Forms::Application->ExeName, ".INI" ) );
openFileName = ini->ReadString ( "SERVICE", "openFileName", "smartOffice.exe" );
openFilePath = ini->ReadString ( "SERVICE", "openFilePath", "c:\\smartOffice" );
delete ini;
}

//---------------------------------------------------------------------------

2、MainForm.h代码

//---------------------------------------------------------------------------

#ifndef UnitMainH
#define UnitMainH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <SvcMgr.hpp>
#include <vcl.h>
//---------------------------------------------------------------------------
class TsmartService : public TService
{
__published:    // IDE-managed Components
void __fastcall ServicePause(TService *Sender, bool &Paused);
void __fastcall ServiceStart(TService *Sender, bool &Started);
void __fastcall ServiceStop(TService *Sender, bool &Stopped);
void __fastcall ServiceContinue(TService *Sender, bool &Continued);
void __fastcall ServiceCreate(TObject *Sender);
private:        // User declarations
public:         // User declarations
__fastcall TsmartService(TComponent* Owner);
TServiceController __fastcall GetServiceController(void);
friend void __stdcall ServiceController(unsigned CtrlCode);
};
//---------------------------------------------------------------------------
extern PACKAGE TsmartService *smartService;
//---------------------------------------------------------------------------

#endif

3、UnitThread.cpp代码

//---------------------------------------------------------------------------
#include <System.hpp>
#pragma hdrstop
/*进程*/
#include <tlhelp32.h>  //进程api相关
#include <Wtsapi32.h>
#include <Userenv.h>   //用户token相关


#include "UnitThread.h"

#include "UnitMain.h"//引用FormMain窗口头文件

#pragma package(smart_init)
/*自定义*/
#pragma comment(lib,"Wtsapi32.lib")
#pragma comment(lib,"Userenv.lib")

//---------------------------------------------------------------------------


//   Important: Methods and properties of objects in VCL can only be
//   used in a method called using Synchronize, for example:
//
//      Synchronize(&UpdateCaption);
//
//   where UpdateCaption could look like:
//
//      void __fastcall TsmartThread::UpdateCaption()
//      {
//        Form1->Caption = "Updated in a thread";
//      }
//---------------------------------------------------------------------------


__fastcall TsmartThread::TsmartThread(bool CreateSuspended)
: TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
void __fastcall TsmartThread::Execute()
{
/*

功能:服务执行事件

windows服务调用windows线程,windows服务的主要功能都在线程OnExecute事件里添加具体代码实现

*/
while (!Terminated)//循环
{
if(!openFilePath.IsEmpty() && !openFileName.IsEmpty())
{
StartProgress(openFileName,openFilePath+"\\"+openFileName);//调用自定义函数启动桌面程序
}
Sleep(10000);//循环间隔时间(毫秒)
}
}
//自定义函数关闭进程,本项目未用到---------------------------------------------------------------------------
bool __fastcall TsmartThread::CloseProgress( AnsiString Progress )
{
/*
功能:查找进程并关闭进程
调用:CloseProgress("coreTeam.exe");
*/
HANDLE   hSnapshotPro;
HANDLE   hSnapshotMod;
char *cStr;
wchar_t *wStr;
size_t len;


//创建遍历进程所需要的SnapshotPro
hSnapshotPro   =   CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if   (!hSnapshotPro)
return false;
//循环遍历进程列表中的进程
PROCESSENTRY32   ProcessEntry;
ProcessEntry.dwSize=sizeof(PROCESSENTRY32);


Process32First(hSnapshotPro,   &ProcessEntry);
int   ppid = -1;
while   (Process32Next(hSnapshotPro,   &ProcessEntry)!=0)
{
wStr=ProcessEntry.szExeFile;
len=wcslen(wStr)+1;
cStr=(char *)malloc(len*sizeof(char));
wcstombs(cStr,wStr,len);
if( strcmp(cStr , Progress.c_str() ) == 0 )
{
ppid = ProcessEntry.th32ProcessID;
}
}
HANDLE   ps = OpenProcess(1,false,ppid);
if(ps&&TerminateProcess(ps,-9))
{
//myLog("程序"+Progress+"停止成功 Stop success");
return true;
}
else
{
//myLog("程序"+Progress+"停止失败 Stop fail");
return false;
}
}
//自定义函数查找启动进程---------------------------------------------------------------------------
bool __fastcall TsmartThread::StartProgress( AnsiString Progress,AnsiString File )
{
/*
功能:判断进程是否存在,如果不存在就启动
调用:StartProgress("coreTeam.exe","C:\\coreTeam\\coreTeam.exe");
*/
bool startFlag=true;
char *cStr;
wchar_t *wStr;
size_t len;
HANDLE   hSnapshotPro;
HANDLE   hSnapshotMod;
//创建遍历进程所需要的SnapshotPro
hSnapshotPro   =   CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(!hSnapshotPro)
{
return false;
}
//循环遍历进程列表中的进程
PROCESSENTRY32   ProcessEntry;
ProcessEntry.dwSize=sizeof(PROCESSENTRY32);
Process32First(hSnapshotPro,   &ProcessEntry);
int   ppid = -1;
while   (Process32Next(hSnapshotPro,   &ProcessEntry)!=0)
{
wStr=ProcessEntry.szExeFile;
len=wcslen(wStr)+1;
cStr=(char *)malloc(len*sizeof(char));
wcstombs(cStr,wStr,len);
if( strcmp(cStr, Progress.c_str() ) == 0 )
{
startFlag=false;
//myLog("程序"+Progress+"正在运行");
break;
}
}
//启动进程
if(!startFlag)
return false;
/*
WINDOWS后操作系统增加了安全隔离,需要先获得token才能正常显示服务调用出来的程序,
否则程序能调用起来,但是出于被隔离的system用户下面,当前用户看不到。
*/
//获取当前活动的SessionId
DWORD dwSessionId = WTSGetActiveConsoleSessionId();
HANDLE hToken = NULL;
HANDLE hTokenDup = NULL;
LPVOID  pEnv = NULL;
STARTUPINFO si;
PROCESS_INFORMATION pi;
//获取用户Token
if (!WTSQueryUserToken(dwSessionId, &hToken))
{
CloseHandle(hToken);
return false;
}
//复制Token
if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hTokenDup))
{
CloseHandle(hToken);
return false;
}
//获取环境信息
if (!CreateEnvironmentBlock(&pEnv, hTokenDup, FALSE))
{
CloseHandle(hToken);
CloseHandle(hTokenDup);
return false;
}
//设置启动参数信息
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = L"winsta0\\default";
ZeroMemory(&pi, sizeof(pi));
DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE;
//以当前用户启动记事本
cStr=File.c_str();
len=strlen(cStr)+1;
wStr=(wchar_t *)malloc(len*sizeof(wchar_t));
mbstowcs(wStr,cStr,len);
if (!CreateProcessAsUser(hTokenDup, wStr, NULL, NULL, NULL, FALSE, dwCreationFlag, pEnv, NULL, &si, &pi))
{
DestroyEnvironmentBlock(pEnv);
CloseHandle(hTokenDup);
CloseHandle(hToken);
}
//等待启动的进程结束
WaitForSingleObject(pi.hProcess, INFINITE);


//清理工作
DestroyEnvironmentBlock(pEnv);
CloseHandle(hTokenDup);
CloseHandle(hToken);
return true;


}
//---------------------------------------------------------------------------

4、UnitThread.h代码

//---------------------------------------------------------------------------
#ifndef UnitThreadH
#define UnitThreadH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
//---------------------------------------------------------------------------
class TsmartThread : public TThread
{
/*自定义*/
bool __fastcall CloseProgress( AnsiString Progress );//关闭进程
bool __fastcall StartProgress( AnsiString Progress,AnsiString File );//启动进程



private:
protected:
void __fastcall Execute();
public:
__fastcall TsmartThread(bool CreateSuspended);
};
//---------------------------------------------------------------------------
#endif


extern String openFilePath,openFileName;//引用FormMain开头定义的全局变量


三、服务安装

编辑两个服务安装和卸载脚本,放到上面编译后的可执行程序bocSmartService的同级别目录里。

1、instatll.bat

bocSmartService /install

net start smartService

pause

2、uninstall.bat

net stop smartService

bocSmartService /uninstall

pause

3、编辑配置文件

配置文件名字应该为可执行程序的同名.ini文件,本项目为bocSmartService.ini文件,在配置文件里设置你要监控的程序的目录和文件名称(目录不能以“\”结尾)

[SERVICE]

openFilePath=c:\smartOffice

openFileName=smartOffice.exe

四、测试效果

右键运行上述的install.bat,服务安装后将每十秒调用启动一次你配置的被监控程序smartOffice.exe,如果程序已经启动则不动作,否则就启动它。牛逼了我的哥,一个通过服务看守桌面程序,不允许关闭的功能实现了。

注意:每次重新编译前要先在服务里将你安装的服务停用


猜你喜欢

转载自blog.csdn.net/dlboy2018/article/details/79563345