
Windows XP 更新是以 Service Pack 形式分发的。Service Pack 有助于使 Windows XP 保持最新状态,并且可以扩展和更新计算机的功能。
为了成功安装最新的 Windows XP Service Pack,请按照步骤检查 PC 的状态。
Windows XP Service Pack 3 (SP3) 只能应用于 32 位版本的 Windows *** 作系统。要检查您的系统是 32 位还是 64 位,请单击 如何确定计算机运行的是 32 位版本还是 64 位版本的 Windows *** 作系统
安装 Windows XP Service Pack 3 (SP3) 之前,必须预先安装 Windows XP Service Pack 2 (SP2) 或 Windows XP Service Pack 1a (SP1a)。要检查您的计算机上当前安装的是哪个 Service Pack,请单击“检查当前安装的是哪个 Service Pack”。要安装早期的 Windows XP Service Pack,请使用以下选项之一:
单击此处 下载 Windows XP Service Pack 2 (SP2)
单击此处 下载 Windows XP Service Pack 1a (SP1a)
安装 Windows XP Service Pack 3 (SP3)
单击此处获取自动修复步骤
单击此处手动下载 Service Pack 3。
单击此处订购 Windows XP Service Pack 3 CD
重要说明 这些 Service Packs 只适用于 32 位版本的 Windows XP。 有关 Windows XP Professional x64 Edition 的更多信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
889100 (>
以下是一些基本知识, 不得不耐下心去理解,这对程序理解和编写非常用帮助
首先Microsoft Windows 服务(即,以前的 NT 服务)使您能够创建在它们自己的Windows 会话中可长时间运行的可执行应用程序。这些服务可以在计算机启动时自动启动,可以暂停和重新启动而且不显示任何用户界面。这使服务非常适合在服务器上使用,或任何时候,为了不影响在同一台计算机上工作的其他用户,需要长时间运行功能时使用。还可以在不同于登录用户的特定用户帐户或默认计算机帐户的安全上下文中运行服务。
服务是有状态的,当我们使用windows自带的服务管理程序scexe 查看服务状态时可以显示服务的当前状态,这个状态是由我们在程序代码中进行控制的。你最好在服务初始化的时候将服务设置为SERVICE_START_PENDING,当初始化完毕时设为SERVICE_RUNNING,这些状
态是系统自定义的状态,可通过msdn查看其他状态。这个状态信息你会在scexe中看到。
在编写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,即正在初始化。我们进行如下赋值:
servicestatusdwServiceType = SERVICE_WIN32;
servicestatusdwCurrentState = SERVICE_START_PENDING;
servicestatusdwControlsAccepted=SERVICE_ACCEPT_SHUTDOWN|SERVICE_ACCEPT_STOP;
//在本例中只接受系统关机和停止服务两种控制命令
servicestatusdwWin32ExitCode = 0;
servicestatusdwServiceSpecificExitCode = 0;
servicestatusdwCheckPoint = 0;
servicestatusdwWaitHint = 0;
hstatus = ::RegisterServiceCtrlHandler("testservice", CtrlHandler);
CtrlHandler为void WINAPI CtrlHandler(DWORD request)型的函数,函数名字可以任意设定。将在下一点讲到。
Hstatus 为SERVICE_STATUS_HANDLE 类 型 的 全 局 变 量 。 当 需 要 改 变 服 务 状 态 时SetServiceStatus()函数需要它做为参数来标识一个服务。
3 void WINAPI CtrlHandler(DWORD request),函数的主要功能是,接收系统传递的控制命令,比如当你通过scexe关闭服务时,该函数会收到SERVICE_CONTROL_STOP消息,你就可以对服务进行必要的管理。在本例子程序中就只接收SERVICE_ACCEPT_SHUTDOWN 和
SERVICE_ACCEPT_STOP消息,这是通过前面给servicestatus赋值设定的。 这样一个基本的服务程序就完成了。 本文结束的时候会附上如
何安装服务。
当服务程序需要使用某些功能时,由于用户的关系而受到限制,比如访问注册表的HKEY_CURRENT_USER键,使用网络等等,这时候就需要以当前登陆用户的身份去进行 *** 作,通常会创建一个进程来完成需要的功能。如果使用CreateProcess, 来创建进程的话,新创建的进程和服务程序依然是相同的用户身份,还是无法达到目的,只有使用CreateProcessAsUser了。但CreateProcessAsUser的第一个参数是HANDLE hToken,该参数通常应该用LogonUser来获得,但是LogonUser又需要用户名和用户密码,这样就很不现实。那应该怎么办呢?我想到了一个方法可以绕过LogonUser直接获得hToken。因为用户已经登陆,那么肯定有Shell(就是EXPLOREREXE)运行了,我们可以通过遍历进程来取得Shell的hToken来运行进程。
因此需要
BOOL GetTokenByName(HANDLE &hToken,LPSTR lpName);
BOOL RunProcess(LPCSTR lpImage);两个函数
示例是关于基于opencv人脸识别, 遍历样本文件夹,删除多余的保留10张, 然后执行 外部自定义程序"GetFeatureDATAexe "函数提取特征
GetFeatureDATAexe中最头上加上#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"")就可以隐藏控制台窗口
开发环境vs2010, 控制台应用程序 一个cpp文件
//服务程序主函数。
[cpp] view plaincopy
#include"stdioh"
#include"vector"
#include"Tlhelp32h"
#include<afxh>
#define_AFXDLL
//由于做的图像识别需要opencv头文件, 需要什么文件自行更改
#include"cvh"
#include"highguih"
usingnamespacestd;
//你的服务程序需要以下代码
SERVICE_STATUS servicestatus;
SERVICE_STATUS_HANDLE hstatus;//全局变量 是setServiceStatus()的参数, 改变服务状态
voidWINAPI ServiceMain(intargc,charargv);
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(FindFileDatadwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)
{
if(FindFileDatacFileName[0]!=_T(''))
{
strDirTmp =strDir;
strDirTmp +="\\";
strDirTmp +=FindFileDatacFileName;
vecDirpush_back(strDirTmp);//保存所有目录
//TraverseDir(strDirTmp,vecFile) ;
}
}
else//是文件
{
/strDirTmp = strDir;
strDirTmp += "\\";
strDirTmp += FindFileDatacFileName;
vecFilepush_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(FindFileDatadwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)
{
if(FindFileDatacFileName[0]!=_T(''))
{
/strDirTmp = strDir;
strDirTmp += "\\";
strDirTmp += FindFileDatacFileName;
TraverseDir(strDirTmp,vecFile) ;/
}
}
else
{
strDirTmp =strDir;
strDirTmp +="\\";
strDirTmp +=FindFileDatacFileName;
vecFilepush_back(strDirTmp);//将路径传入
ImgNum++;
}
if(!FindNextFile(hFind,&FindFileData))
break;
}
FindClose(hFind);
returnImgNum;
}
voidWINAPI ServiceMain(intargc,charargv)
{
servicestatusdwServiceType =SERVICE_WIN32;
servicestatusdwCurrentState =SERVICE_START_PENDING;
servicestatusdwControlsAccepted =SERVICE_ACCEPT_SHUTDOWN|SERVICE_ACCEPT_STOP;//在本例中只接受系统关机和停止服务两种控制命令
servicestatusdwWin32ExitCode =0;
servicestatusdwServiceSpecificExitCode =0;
servicestatusdwCheckPoint =0;
servicestatusdwWaitHint =0;
hstatus =::RegisterServiceCtrlHandler("testservice",CtrlHandler);
if(hstatus==0)
{
return;
}
//向SCM 报告运行状态
servicestatusdwCurrentState =SERVICE_RUNNING;
SetServiceStatus(hstatus,&servicestatus);
//下面就
brun=true;
//以下是自己要写的代码的执行调用地方开始任务循环了,你可以添加你自己希望服务做的工作
//SYSTEMTIME t;
//GetLocalTime(&t);
//int hour = twHour ;//获取小时, 可以在固定某个小时执行程序
while(1)//
{
CStringSamplesDirPath=_T("G:\\Samples");
TraverseDir(SamplesDirPath,Vec_Dir);//获取目录名称到vec_Dir
for(inti(0);i<Vec_Dirsize();i++)//
{
intImg_Num=TraverseImg(Vec_Dir[i],Vec_Img);//某个目录下的所有
if(Img_Num>10)
{
for(intj=Img_Num-10-1;j>=0;j--)
{
remove(Vec_Img[j]);
}
}
Vec_Imgclear();
}
//几种调用外部程序的方法,但除了RunProcess其他都是以system身份打开程序
//WinExec("G:\\about_MFC\\GetFeatureDATAexe", 0);
//system( "GetFeatureDATAexe");
//ShellExecute(NULL,"open","G:\\about_MFC\\GetFeatureDATAexe",NULL,NULL,SW_SHOWNORMAL);
RunProcess("G:\\about_MFC\\GetFeatureDATAexe");
//从硬盘里读取时间来做个每隔多少时间进行
CvFileStorageThreshold=cvOpenFileStorage("/service_timexml",0,CV_STORAGE_READ);//读取预值
CvFileNodeThresholdNode=cvGetFileNodeByName(Threshold,0,"circle_time");
doubleservice_time =cvReadRealByName(Threshold,ThresholdNode,"circle_time");
Sleep(service_time601000);//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);
pe32dwSize =sizeof(PROCESSENTRY32);
if(Process32First(hProcessSnap,&pe32))
{
do
{
if(!strcmp(_strupr(pe32szExeFile),_strupr(lpName)))
{
HANDLE hProcess =OpenProcess(PROCESS_QUERY_INFORMATION,
FALSE,pe32th32ProcessID);
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,"EXPLOREREXE"))
{
returnFALSE;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si,sizeof(STARTUPINFO));
sicb=sizeof(STARTUPINFO);
silpDesktop =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;
}
然后安装服务
点开始运行cmdexe
输入以下:
sc create your_service_name binpath= D:\backup\GetXMLexe //这步注意等号右边有个空格
sc start your_service_name //启动服务, 也可以启动任务管理器在服务一栏中找到你的服务启动或停止
sc stop testservicename //停止服务
sc delete testservicename //删除服务,该服务将在下次重启后删除,在重启之前将不能注册
同一个名字的服务。
启动服务, 停止服务,等也可以在windows任务管理器中管理
Option Explicit
Private Sub Command1_Click()
MsgBox ExePath("vb6exe")
End Sub
Public Function ExePath(ExeNm As String) As String
Dim objWMIService, colProcesslist, objProcess
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\\root\cimv2")
Set colProcesslist = objWMIServiceExecQuery("Select from Win32_Process Where Name = '" & ExeNm & "'")
If colProcesslistCount > 0 Then
For Each objProcess In colProcesslist
ExePath = ExePath & objProcessExecutablePath & vbCrLf
Next
End If
Set objWMIService = Nothing
Set colProcesslist = Nothing
End Function
当你了解Service的生命周期以后,你就会明白,你可以在onStop 或者onDestroy()中记录一下状态,onStop 执行以后,那么service肯定是停止的,Service是在一段不定的时间运行在后台,不和用户交互应用组件。每个Service必须在manifest中 通过<service>来声明。可以通过contectstartservice和contectbindserverice来启动。
Service生命周期
使用contextstartService() 启动Service是会会经历:
contextstartService() ->onCreate()- >onStart()->Service running
contextstopService() | ->onDestroy() ->Service stop
在Service每一次的开启关闭过程中,只有onStart可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。
而启动service,根据onStartCommand的返回值不同,有两个附加的模式:
1 START_STICKY 用于显示启动和停止service。
2 START_NOT_STICKY或START_REDELIVER_INTENT用于有命令需要处理时才运行的模式。
Service不能自己运行,需要通过调用ContextstartService()或ContextbindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。
使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。如果打算采用ContextstartService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用ContextstopService()方法结束服务,服务结束时会调用onDestroy()方法。
使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。onBind()只有采用ContextbindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用ContextbindService()方法并不会导致该方法被多次调用。采用ContextbindService()方法启动服务时只能调用onUnbind()方法解除调用者与服务解除,服务结束时会调用onDestroy()方法。
官方文档告诉我们,Android系统会尽量保持拥有service的进程运行,只要在该service已经被启动(start)或者客户端连接(bindService)到它。当内存不足时,需要保持,拥有service的进程具有较高的优先级。
1 如果service正在调用onCreate,onStartCommand或者onDestory方法,那么用于当前service的进程则变为前台进程以避免被killed。
2 如果当前service已经被启动(start),拥有它的进程则比那些用户可见的进程优先级低一些,但是比那些不可见的进程更重要,这就意味着service一般不会被killed
3 如果客户端已经连接到service (bindService),那么拥有Service的进程则拥有最高的优先级,可以认为service是可见的。
4 如果service可以使用startForeground(int, Notification)方法来将service设置为前台状态,那么系统就认为是对用户可见的,并不会在内存不足时killed。
以上就是关于如何获取 Windows XP Service Pack 3全部的内容,包括:如何获取 Windows XP Service Pack 3、什么是Service以及描述下它的生命周期。Service有哪些启动方法,有什么区别,怎样停用Service、C++ windows 本地Service等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)