vc是vs的一部分。
VC(即VC++、Visual C++)在6.0版本和之前,是有单独的版本的,之后,一直是集成在VS(Microsoft Visual Studio)之中的。VS完全版必然有对应版本的VC存在。
比如VS2008,里面有VC2008,对应的内部版本是VC 8.0
Microsoft Visual C++(简称Visual C++、MSVC、VC++或VC)是微软公司的C++开发工具,具有集成开发环境,可提供编辑C语言,C++以及C++/CLI等编程语言。
VC++集成了便利的除错工具,特别是集成了微软Windows视窗 *** 作系统应用程序接口(Windows API)、三维动画DirectX API,Microsoft .NET框架。目前最新的版本是Microsoft Visual C++ 2015。
拓展资料:Visual Studio 是微软公司推出的开发环境,Visual Studio 可以用来创建 Windows 平台下的 Windows 应用程序和网络应用程序,也可以用来创建网络服务、智能设备应用程序和 Office 插件。Visual Studio 是目前最流行的 Windows 平台应用程序开发环境。目前已经开发到 11 beta 版本,也就是 Visual Studio 2011 beta,但是最新的稳定版本依然是Visual Studio 2010。
Visual Studio 2008 包括各种增强功能,例如可视化设计器(使用 .NET Framework 3.5 加速开发)、对 Web 开发工具的大量改进,以及能够加速开发和处理所有类型数据的语言增强功能。Visual Studio 2008 为开发人员提供了所有相关的工具和框架支持,帮助创建引人注目的、令人印象深刻并支持 AJAX 的 Web 应用程序。
开发人员能够利用这些丰富的客户端和服务器端框架轻松构建以客户为中心的 Web 应用程序,这些应用程序可以集成任何后端数据提供程序、在任何当前浏览器内运行并完全访问 ASP NET 应用程序服务和 Microsoft 平台。
第一步:主函数和全局定义第二步:ServiceMain
函数
第三步:处理控制请求
第四步:安装和配置服务
第五步:测试服务
以下是一些基本知识, 不得不耐下心去理解,这对程序理解和编写非常用帮助.首先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 entrytable[2]
entrytable[0].lpServiceName="testservice"
entrytable[0].lpServiceProc=(LPSERVICE_MAIN_FUNCTION)ServiceMain
entrytable[1].lpServiceName=NULL
entrytable[1].lpServiceProc=NULL
StartServiceCtrlDispatcher(entrytable)
在这之后系统将自动创建一个线程去执行ServiceMain函数的内容,你应该将你要执行的任务
在ServiceMain中循环,这样服务就开始运行了。
2.ServiceMain函数为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的第一个参数是HANDLE hToken,该参数通常应该用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, 控制台应用程序 一个.cpp文件.
//服务程序主函数。
[cpp] view plaincopy
#include"stdio.h"
#include"vector"
#include"Tlhelp32.h"
#include<afx.h>
#define_AFXDLL
//由于做的图像识别需要opencv头文件, 需要什么文件自行更改
#include"cv.h"
#include"highgui.h"
usingnamespacestd
//你的服务程序需要以下代码
SERVICE_STATUS servicestatus
SERVICE_STATUS_HANDLE hstatus//全局变量. 是setServiceStatus()的参数, 改变服务状态
voidWINAPI ServiceMain(intargc,char**argv)
voidWINAPI CtrlHandler(DWORD request)
boolbrun=false//原来代码有的,我没有用,还是保留
//以下是以获取登录用户名
BOOL GetTokenByName(HANDLE &hToken,LPSTR lpName)
BOOL RunProcess(LPCSTR lpImage)
//自己添加的代码
inttrain_time//以分钟计
vector<CString>Vec_Dir//存放图片文件夹目录名称
vector<CString>Vec_Img//
voidTraverseDir(CString&strDir,std::vector<CString>&vecDir)
intTraverseImg(CString&strDir,std::vector<CString>&vecFile)
voidTraverseDir(CString&strDir,std::vector<CString>&vecDir)
{
WIN32_FIND_DATA FindFileData
CStringstrDirTmp
strDirTmp =strDir
strDirTmp +="\\*.*"
HANDLE hFind=::FindFirstFile(strDirTmp,&FindFileData)
if(INVALID_HANDLE_VALUE ==hFind)
{
return
}
while(TRUE)
{
if(FindFileData.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)
{
if(FindFileData.cFileName[0]!=_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)
}
intTraverseImg(CString&strDir,std::vector<CString>&vecFile)//输入路径,得到img路径文件名 不用的请忽视
{
intImgNum=0
WIN32_FIND_DATA FindFileData
CStringstrDirTmp
strDirTmp =strDir
strDirTmp +="\\*.*"
HANDLE hFind=::FindFirstFile(strDirTmp,&FindFileData)
if(INVALID_HANDLE_VALUE ==hFind)
{
//return
}
while(TRUE)
{
if(FindFileData.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)
{
if(FindFileData.cFileName[0]!=_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)
returnImgNum
}
voidWINAPI ServiceMain(intargc,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)
{
return
}
//向SCM 报告运行状态
servicestatus.dwCurrentState =SERVICE_RUNNING
SetServiceStatus(hstatus,&servicestatus)
//下面就
brun=true
//以下是自己要写的代码的执行调用地方.开始任务循环了,你可以添加你自己希望服务做的工作
//SYSTEMTIME t
//GetLocalTime(&t)
//int hour = t.wHour //获取小时, 可以在固定某个小时执行程序
while(1)//
{
CStringSamplesDirPath=_T("G:\\Samples")
TraverseDir(SamplesDirPath,Vec_Dir)//获取目录名称到vec_Dir
for(inti(0)i<Vec_Dir.size()i++)//
{
intImg_Num=TraverseImg(Vec_Dir[i],Vec_Img)//某个目录下的所有图片
if(Img_Num>10)
{
for(intj=Img_Num-10-1j>=0j--)
{
remove(Vec_Img[j])
}
}
Vec_Img.clear()
}
//几种调用外部程序的方法,但除了RunProcess其他都是以system身份打开程序.
//WinExec("G:\\about_MFC\\GetFeatureDATA.exe", 0)
//system( "GetFeatureDATA.exe")
//ShellExecute(NULL,"open","G:\\about_MFC\\GetFeatureDATA.exe",NULL,NULL,SW_SHOWNORMAL)
RunProcess("G:\\about_MFC\\GetFeatureDATA.exe")
//从硬盘里读取时间来做个每隔多少时间进行
CvFileStorage*Threshold=cvOpenFileStorage("./service_time.xml",0,CV_STORAGE_READ)//读取预值
CvFileNode*ThresholdNode=cvGetFileNodeByName(Threshold,0,"circle_time")
doubleservice_time =cvReadRealByName(Threshold,ThresholdNode,"circle_time")
Sleep(service_time*60*1000)//sleep自定时间后再次执行 *** 作
}
}
BOOL GetTokenByName(HANDLE &hToken,LPSTR lpName)
{
if(!lpName)
{
returnFALSE
}
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)
{
returnFALSE
}
HANDLE hToken
if(!GetTokenByName(hToken,"EXPLORER.EXE"))
{
returnFALSE
}
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)
{
OutputDebugString("CreateProcessAsUser ok!\r\n")
}
else
{
OutputDebugString("CreateProcessAsUser false!\r\n")
}
returnbResult
}
然后安装服务
点开始运行cmd.exe
输入以下:
sc create your_service_name binpath= D:\backup\GetXML.exe //这步注意等号右边有个空格
sc start your_service_name //启动服务, 也可以启动任务管理器在服务一栏中找到你的服务启动或停止
sc stop testservicename //停止服务
sc delete testservicename //删除服务,该服务将在下次重启后删除,在重启之前将不能注册
同一个名字的服务。
启动服务, 停止服务,等也可以在windows任务管理器中管理
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)