Windows服务程序运行于系统的后台来处理一些系统操作,当然我们有时也希望自已能够实现系像系统服务那样对特定的程序
进行操作.至于关于Windows操作系统中系统服务的详细说明,网上资料有很多了,偶也就不多写了,怕写也写不明白.写在这里的
目的也是希望给自已一个记载,省得以后用到的时候找不到了.嘿嘿.
在这里我通过系统服务实现了保证某应用程序一直处于运行状态这样一个简单功能:服务启动后,检测系统中某应用程序(Okilpr.exe,当然也可以换成记事本之类的应用程序,在这里称为App吧)是否处于运行状态,如果App已经处于运行状态,则不对其进行任何操作,如果App已被
用户关闭,那么这个系统服务就会根据App所在的路径,创建一个App进程,则启动它,并将启动成功与否的log信息写入到log文件中.. 这就是服务实现的功能.
那么为了使服务便于操作,创建了一个界面操作小工具,对服务能够进行Install,Start,Stop,Quer,Delete功能,并将服务的运
行状态在界面上进行显示.
作为一个行走在Windows编程道路上的新人,经验非常有限;在程序的编写中,借鉴了 Northtibet译的MSDN"Five Steps to Writing Windows Services in C "(用 C 语言编写 Windows 服务程序的五个步骤http://www.vckbase.com/document/viewdoc/?id=1474)
实现后的界面如下所示:
因为不知道如何将代码上传,只好贴代码了.
//About the System Service
//Date:2009-12-14
//Function:Use the Service to start Application.
//Author:yzli
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <tlhelp32.h>
#define SLEEP_TIME 5000
#define LOGFILE "C://MyServices//memstatus.txt"
// Declare several global variables to share
// their values across multiple functions of your program.
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;
// Make the forward definitions of functions prototypes.
//
void ServiceMain(int argc, char** argv);
void ControlHandler(DWORD request);
int InitService();
int WriteToLog(char* str)
{
//Get Current Directory
TCHAR szLogPath[MAX_PATH];
TCHAR szLogName[MAX_PATH];
ZeroMemory(szLogPath, MAX_PATH);
GetModuleFileName(NULL,szLogPath,sizeof(szLogPath));
lstrcpy(szLogName,"MemoryStatus.txt");
int iLen = strlen(szLogPath);
int iNameLen = strlen(szLogName);
iLen --;//find from the second-last character.
while(iLen)
{
if(szLogPath[iLen]== '//')
{
break;
}
iLen--;
}
while(iNameLen)
{
szLogPath[iLen+ iNameLen] = szLogName[iNameLen-1];
iNameLen--;
}
//Write to Log
FILE* log;
log = fopen(szLogPath, "a+");
if (log == NULL){
OutputDebugString("Log file open failed.");
return -1;
}
fprintf(log, "%s/n", str);
fclose(log);
return 0;
}
///
BOOL IsOkilprRun()
{
HANDLE hProcessSnap = NULL;
BOOL bRet = FALSE;
PROCESSENTRY32 pe32 = {0};
TCHAR lpName[MAX_PATH];
lstrcpy(lpName,"Okilpr.exe");
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)))
{
CloseHandle(hProcessSnap);
return TRUE;
}
}while(Process32Next(hProcessSnap,&pe32));
}
else
{
CloseHandle(hProcessSnap);
return FALSE;
}
}
///
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
{
bRet =FALSE;
}
CloseHandle(hProcessSnap);
return(bRet);
}
//
BOOL RunProcess(LPCSTR lpImage)
{
if(!lpImage)
return FALSE;
HANDLE hToken;
if(!GetTokenByName(hToken,"WINLOGON.EXE"))
{
return FALSE;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = TEXT("winsta0//default");
BOOL bResult = CreateProcessAsUser(hToken,
lpImage,NULL,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi);
CloseHandle(hToken);
if(bResult)
{
WriteToLog("CreateProcessAsUser OK!/r/n");
}
else
{
WriteToLog("CreateProcessAsUser false!/r/n");
}
return bResult;
}
//
// Service initialization
int InitService()
{
OutputDebugString("Monitoring started.");
int result;
result = WriteToLog("Monitoring started.");
return(result);
}
// Control Handler
void ControlHandler(DWORD request)
{
switch(request)
{
case SERVICE_CONTROL_STOP:
OutputDebugString("Monitoring stopped.");
WriteToLog("Monitoring stopped.");
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
case SERVICE_CONTROL_SHUTDOWN:
OutputDebugString("Monitoring stopped.");
WriteToLog("Monitoring stopped.");
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
default:
break;
}
// Report current status
SetServiceStatus (hStatus, &ServiceStatus);
return;
}
/
/
void ServiceMain(int argc, char** argv)
{
int error;
//The Okilpr.exe will be started onley one time by service.
BOOL bManualStart = FALSE;//if LPR was started,the value is TRUE;
ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
hStatus = RegisterServiceCtrlHandler(
"MemoryStatus",
(LPHANDLER_FUNCTION)ControlHandler);
if (hStatus == (SERVICE_STATUS_HANDLE)0)
{
// Registering Control Handler failed
return;
}
// Initialize Service
error = InitService();
if (error)
{
// Initialization failed
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
// We report the running status to SCM.
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus (hStatus, &ServiceStatus);
MEMORYSTATUS memory;
// The worker loop of a service
while (ServiceStatus.dwCurrentState ==
SERVICE_RUNNING)
{
///*****************************************************************
char szPath[MAX_PATH], szCommand[MAX_PATH];
//SECURITY_ATTRIBUTES sa;
//STARTUPINFO si;
//PROCESS_INFORMATION pi;
ZeroMemory(szPath,MAX_PATH);
ZeroMemory(szCommand,MAX_PATH);
//sprintf( szPath,"%s","C://Program Files//Okidata//OKI LPR Utility");
sprintf( szCommand,"%s","C://Program Files//Okidata//OKI LPR Utility//Okilpr.exe");
sprintf( szCommand,"%s","Okilpr.exe");
//ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
//sa.nLength = sizeof(SECURITY_ATTRIBUTES);
//ZeroMemory(&si, sizeof(STARTUPINFO));
//si.cb = sizeof(STARTUPINFO);
//si.dwFlags = STARTF_USESHOWWINDOW;
//si.wShowWindow = SW_SHOWMINIMIZED;
//si.lpDesktop = "WinSta0//Default";
//ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
//
//if(!FindWindow("Okilpr", NULL))
//{
// if(CreateProcess(NULL, szCommand, &sa, &sa, TRUE, CREATE_SUSPENDED, NULL, szPath, &si, &pi))
// {
// ResumeThread(pi.hThread);
// WaitForInputIdle(pi.hProcess, 10000);
// while(!FindWindow("Okilpr", NULL));
// CloseHandle(pi.hProcess);
// CloseHandle(pi.hThread);
//
// if(!WriteToLog("LPR process start."))
// {
// OutputDebugString("SUCCESS/n");
// }
// }
//}
//**************************************************************
if((!IsOkilprRun()) && (!bManualStart))
{
RunProcess(szCommand);
bManualStart = TRUE;
}
//***************************************************************
char buffer[16];
GlobalMemoryStatus(&memory);
sprintf(buffer, "%d", memory.dwAvailPhys);
OutputDebugString(buffer);
int result = WriteToLog(buffer);
if (result)
{
ServiceStatus.dwCurrentState =
SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus,
&ServiceStatus);
return;
}
Sleep(SLEEP_TIME);
}
return;
}
void main(int argc, char* argv[])
{
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = "MemoryStatus";
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
// Start the control dispatcher thread for our service
StartServiceCtrlDispatcher(ServiceTable);
}
//About the Control Dialog of Service
//Date:2009-12-14
//Function:Use the Service to start Application.
//Author:yzli
// ServiceCtrlDlg.cpp : implementation file
//
#include "stdafx.h"
#include "ServiceCtrl.h"
#include "ServiceCtrlDlg.h"
#include <windows.h>
#include <winsvc.h>
#include <shlobj.h>
#include <dsclient.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CServiceCtrlDlg dialog
CServiceCtrlDlg::CServiceCtrlDlg(CWnd* pParent /*=NULL*/)
: CDialog(CServiceCtrlDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_uiTimer = 0;
}
void CServiceCtrlDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CServiceCtrlDlg, CDialog)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BTNSTART, &CServiceCtrlDlg::OnBnClickedBtnstart)
ON_BN_CLICKED(IDC_BTNSTOP, &CServiceCtrlDlg::OnBnClickedBtnstop)
ON_BN_CLICKED(IDC_BTNQUERY, &CServiceCtrlDlg::OnBnClickedBtnquery)
ON_WM_TIMER()
ON_WM_DESTROY()
ON_BN_CLICKED(IDC_INSTALL, &CServiceCtrlDlg::OnBnClickedInstall)
ON_BN_CLICKED(IDC_DELETE, &CServiceCtrlDlg::OnBnClickedDelete)
END_MESSAGE_MAP()
// CServiceCtrlDlg message handlers
BOOL CServiceCtrlDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
// Set the default service name
SetDlgItemText(IDC_SERVNAME, _T("MemoryStatus"));
// Start the auto-update timer
m_uiTimer = SetTimer(1,1000, NULL); // 1 second interval
//**************************************************************************
//**************************************************************************
return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CServiceCtrlDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CServiceCtrlDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CServiceCtrlDlg::OnBnClickedBtnstart()
{
// TODO: Add your control notification handler code here
// Get the service name
char szServiceName[64];
ZeroMemory(szServiceName,64);
szServiceName[0] = '/0';
GetDlgItemText(IDC_SERVNAME, (LPTSTR)szServiceName, sizeof(szServiceName));
if (strlen(szServiceName) == 0) return;
// open the service control manager
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
ASSERT(hSCM);
// open the service
SC_HANDLE hService = OpenService(hSCM,
szServiceName,
SERVICE_ALL_ACCESS);
ASSERT(hService);
SERVICE_STATUS ss;
memset(&ss, 0, sizeof(ss));
BOOL b = QueryServiceStatus(hService,
&ss);
if(!b)
{
DWORD dwErr = GetLastError();
ASSERT(0);
}
else
{
DWORD dwErr = ss.dwWin32ExitCode;
DWORD dwState = ss.dwCurrentState;
// If the service is running, send a control request
// to get its current status
if (dwState == SERVICE_RUNNING)
{
AfxMessageBox(_T("The Service is running."));
return;
}
}
// start the service
b = StartService(hService, 0, NULL);
if(!b) {
DWORD dwErr = GetLastError();
AfxMessageBox(_T("The Service could not run."));
return;
}
// close the service handle
CloseServiceHandle(hService);
// close the service control manager handle
CloseServiceHandle(hSCM);
ShowState();
}
void CServiceCtrlDlg::OnBnClickedBtnstop()
{
// TODO: Add your control notification handler code here
// Get the service name
char szServiceName[64];
szServiceName[0] = '/0';
GetDlgItemText(IDC_SERVNAME, szServiceName, sizeof(szServiceName));
if (strlen(szServiceName) == 0) return;
// open the service control manager
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
ASSERT(hSCM);
// open the service
SC_HANDLE hService = OpenService(hSCM,
szServiceName,
SERVICE_ALL_ACCESS);
ASSERT(hService);
// stop the service
SERVICE_STATUS ss;
BOOL b = ControlService(hService,
SERVICE_CONTROL_STOP,
&ss);
if(!b) {
DWORD dwErr = GetLastError();
ASSERT(0);
}
// close the service handle
CloseServiceHandle(hService);
// close the service control manager handle
CloseServiceHandle(hSCM);
ShowState();
}
void CServiceCtrlDlg::OnBnClickedBtnquery()
{
// TODO: Add your control notification handler code here
ShowState();
}
void CServiceCtrlDlg::ShowState()
{
// Get the service name
char szServiceName[64];
szServiceName[0] = '/0';
DWORD dwState = 0xFFFFFFFF;
DWORD dwErr = 0xFFFFFFFF;
GetDlgItemText(IDC_SERVNAME, szServiceName, sizeof(szServiceName));
if (strlen(szServiceName) != 0) {
// open the service control manager
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
ASSERT(hSCM);
// open the service
SC_HANDLE hService = OpenService(hSCM,
szServiceName,
SERVICE_ALL_ACCESS);
if (hService) {
// Get the current status
SERVICE_STATUS ss;
memset(&ss, 0, sizeof(ss));
BOOL b = QueryServiceStatus(hService,
&ss);
if(!b) {
DWORD dwErr = GetLastError();
ASSERT(0);
} else {
dwErr = ss.dwWin32ExitCode;
dwState = ss.dwCurrentState;
// If the service is running, send a control request
// to get its current status
if (dwState == SERVICE_RUNNING) {
b = ::ControlService(hService,
SERVICE_CONTROL_INTERROGATE,
&ss);
if (b) {
dwErr = ss.dwWin32ExitCode;
dwState = ss.dwCurrentState;
}
}
}
// close the service handle
CloseServiceHandle(hService);
}
// close the service control manager handle
CloseServiceHandle(hSCM);
}
// See what we got
char buf[64];
if (dwErr == 0xFFFFFFFF) {
SetDlgItemText(IDC_EXITCODE, "<unknown>");
} else {
sprintf(buf, "%8.8lXH (%d)", dwErr, dwErr);
SetDlgItemText(IDC_EXITCODE, buf);
}
switch (dwState) {
case SERVICE_STOPPED:
strcpy(buf, "Stopped");
break;
case SERVICE_START_PENDING:
strcpy(buf, "Start pending");
break;
case SERVICE_STOP_PENDING:
strcpy(buf, "Stop pending");
break;
case SERVICE_RUNNING:
strcpy(buf, "Running");
break;
case SERVICE_CONTINUE_PENDING:
strcpy(buf, "Continue pending");
break;
case SERVICE_PAUSE_PENDING:
strcpy(buf, "Pause pending");
break;
case SERVICE_PAUSED:
strcpy(buf, "Paused");
break;
default:
strcpy(buf, "<Unknown>");
break;
}
SetDlgItemText(IDC_STATE, buf);
}
void CServiceCtrlDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: Add your message handler code here and/or call default
ShowState();
CDialog::OnTimer(nIDEvent);
}
void CServiceCtrlDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
if (m_uiTimer != 0) {
KillTimer(1);
}
}
void CServiceCtrlDlg::OnBnClickedInstall()
{
// TODO: Add your control notification handler code here
SC_HANDLE hSCM, hService;
char szServiceName[64];
ZeroMemory(szServiceName,64);
TCHAR szServicePath[MAX_PATH];
ZeroMemory(szServicePath,MAX_PATH);
//lstrcpy( szServicePath, _T("C://MyServices//MemoryStatus.exe") );
GetDlgItemText(IDC_SERVNAME,szServiceName,sizeof(szServiceName));
GetModuleFileName(NULL,szServicePath,sizeof(szServicePath));
CString strServicePath, strServiceName;
strServicePath.Format(_T("%s"),szServicePath);
strServiceName.Format(_T("%s"),szServiceName);
int iPos =strServicePath.ReverseFind('//');
if(iPos)
{
strServicePath = strServicePath.Left(iPos+1);
strServicePath += strServiceName;
strServicePath += _T(".exe");
}
GetDlgItemText(IDC_SERVNAME,szServiceName,sizeof(szServiceName));
if(strlen(szServiceName) !=0)
{
// open the service control manager
hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
ASSERT(hSCM);
// open the service
SC_HANDLE hService = OpenService(hSCM,
szServiceName,
SERVICE_ALL_ACCESS);
if(hService)
{
::AfxMessageBox(_T("The Service has installed."));
return;
}
hService = CreateService(
hSCM,//SCManager database
szServiceName,//name of Service
szServiceName,//Service name to display
SERVICE_ALL_ACCESS,//desired access
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,//Service type
SERVICE_AUTO_START,//start type
SERVICE_ERROR_NORMAL,//error control type
(LPCTSTR)strServicePath, //path to service's binary
NULL,//no load ordering group
NULL,//no tag identifier
NULL,//no dependencies
NULL,//localSystem account
NULL);//no Password
if(hService)
{
AfxMessageBox(_T("Service is installed successfully."));
}
else
{
AfxMessageBox(_T("Service is installed Failed."));
}
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
}
}
void CServiceCtrlDlg::OnBnClickedDelete()
{
// TODO: Add your control notification handler code here
SC_HANDLE hSCM, hService;
char szServiceName[64];
ZeroMemory(szServiceName,64);
GetDlgItemText(IDC_SERVNAME,szServiceName,sizeof(szServiceName));
if(strlen(szServiceName) !=0)
{
hSCM = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
ASSERT(hSCM);
hService = OpenService(hSCM,szServiceName,SERVICE_ALL_ACCESS);
if(hService)
{
if(!DeleteService(hService))
{
AfxMessageBox(_T("The Service is delete failed."));
}
else
{
AfxMessageBox(_T("The Service is delete Successfully."));
}
}
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
}
}
///END