import process;
namespace service;
::Advapi32 := ..raw.loadDll("Advapi32.dll");
class manager{
ctor(desiredAccess,machineName,databaseName){
this.handle = ::Advapi32.OpenSCManagerW(machineName,databaseName,desiredAccess:1/*_SC_MANAGER_CONNECT*/);
..table.gc(this, "close");
};
create = function(binaryPathName,serviceName,displayName,desiredAccess,serviceType,startType,errorControl,loadOrderGroup,tagId,dependencies,serviceStartName,password){
if(!this.handle) return ;
if( type(binaryPathName) != type.string || !#serviceName ) error("请指定服务启动程序,参数@1错误",2);
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名,参数@2错误",2);
if( desiredAccess === null ) desiredAccess = 0x10/*_SERVICE_START*/;
if( serviceType === null ) serviceType = 0x10/*_SERVICE_WIN32_OWN_PROCESS*/;
if( startType === null ) startType = 0x2/*_SERVICE_AUTO_START*/;
if( errorControl === null ) errorControl = 0x0/*_SERVICE_ERROR_IGNORE*/;
if( displayName === null ) displayName = serviceName;
if( ..io.localpath(binaryPathName) ) binaryPathName = ..io.localpath(binaryPathName);
var hService = ::Advapi32.CreateServiceW(this.handle,serviceName,displayName,desiredAccess,serviceType,startType,errorControl,binaryPathName,loadOrderGroup,tagId,dependencies,serviceStartName,password);
if( hService ){
var ret = ::Advapi32.StartServiceW(hService,0,null);
::Advapi32.CloseServiceHandle(hService);
return !!ret;
}
};
open = function(serviceName,desiredAccess){
if(!this.handle) return ;
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
if( desiredAccess === null ) desiredAccess = 4/*_SERVICE_QUERY_STATUS*/
return ::Advapi32.OpenServiceW(this.handle, serviceName, desiredAccess );
};
start =function(serviceName,...){
if(!this.handle) return ;
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
var hService = this.open(serviceName, 0x10/*_SERVICE_START*/)
if (hService) {
var args;
var len = 0;
if(...){
args = { ustring v[] = {serviceName;...} };
len = #args.v;
}
var ret = ::Advapi32.StartServiceW(hService,len,args);
::Advapi32.CloseServiceHandle(hService);
return !!ret;
}
};
control = function(serviceName,desiredAccess,control){
if(!this.handle) return ;
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
var hService = this.open(serviceName, desiredAccess)
if (hService) {
var status = SERVICE_STATUS();
var ret = ::Advapi32.ControlServiceW(hService,control,status);
::Advapi32.CloseServiceHandle(hService);
return !!ret,status;
}
};
stop = function(serviceName,term){
if(!this.handle) return ;
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
if(! this.control(serviceName, 0x20/*_SERVICE_STOP*/,0x1/*_SERVICE_CONTROL_STOP*/) ){
if( this.isStopped(serviceName) ) return true;
return term ? this.terminate(serviceName);
}
return true;
};
terminate = function(serviceName){
var status = this.queryStatus(serviceName)
if( status && status.processId ) {
var prcs = ..process( status.processId );
if( prcs ){
prcs.terminate();
prcs.free();
return true;
}
}
if( this.isStopped(serviceName) ) return true;
};
pause = function(serviceName){
if(!this.handle) return ;
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
return this.control(serviceName, 0x40/*_SERVICE_PAUSE_CONTINUE*/,0x2/*_SERVICE_CONTROL_PAUSE*/);
};
resume = function(serviceName){
if(!this.handle) return ;
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
return this.control(serviceName, 0x40/*_SERVICE_PAUSE_CONTINUE*/,0x3/*_SERVICE_CONTROL_CONTINUE*/);
};
restart = function(serviceName,stopSec,startSec){
this.stop(serviceName,true);
var sec = 0;
while( ! this.isStopped(serviceName) ){
..thread.delay(1000);
sec++;
if( (stopSec!==null) && (stopSec< sec) ){
this.terminate(serviceName);
break;
}
}
if(! this.start(serviceName) ){
if( this.terminate(serviceName) )this.start(serviceName);
}
var sec = 0;
while( !this.isRunning(serviceName) ){
..thread.delay(1000);
sec++;
if( (startSec!==null) && (startSec < sec) )return false;
}
this.close();
return true;
};
delete = function(serviceName){
if(!this.handle) return ;
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
this.stop(serviceName);
var hService = this.open(serviceName, 0x10000/*_DELETE*/ )
if (hService) {
var ret = ::Advapi32.DeleteService(hService);
::Advapi32.CloseServiceHandle(hService);
return ret;
}
};
isExist = function(serviceName){
if(!this.handle) return ;
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
var hService = this.open(serviceName, 4/*_SERVICE_QUERY_STATUS*/)
if (hService) {
::Advapi32.CloseServiceHandle(hService);
return true;
}
};
queryStatus = function(serviceName){
if(!this.handle) return ;
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
var hService = this.open(serviceName, 4/*_SERVICE_QUERY_STATUS*/)
if (hService) {
var status = SERVICE_STATUS_PROCESS();
var cbBytesNeeded = {INT value};
if( ! ::Advapi32.QueryServiceStatusExW(hService, 0/*_SC_STATUS_PROCESS_INFO*/, status,..raw.sizeof(status),cbBytesNeeded) ){
status = null;
}
else {
status.state = STATE_TEXT[status.currentState];
}
::Advapi32.CloseServiceHandle(hService);
return status;
}
};
wait = function(serviceName,state){
state = state : 4/*_SERVICE_RUNNING*/;
while( var status = this.queryStatus(serviceName) ) {
if(status.currentState == state) return status;
..thread.delay(100);
}
};
startAndWait = function(serviceName,desiredAccess){
if(!this.isRunning(serviceName)){
if(!this.start(serviceName)) return;
}
var status = this.wait(serviceName);
if(status[["processId"]]){
return ..process(status.processId,desiredAccess);
}
};
isStopped = function(serviceName){
var status = this.queryStatus(serviceName);
return status ? (status.currentState == 1/*_SERVICE_STOPPED*/);
};
isRunning = function(serviceName){
var status = this.queryStatus(serviceName);
return status ? (status.currentState == 0x4/*_SERVICE_RUNNING*/);
};
changeDescription = function(serviceName,desc){
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
return this.changeConfig2(serviceName,0x1/*_SERVICE_CONFIG_DESCRIPTION*/,{ustring value=desc});
};
queryDescription = function(serviceName){
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
var out = {ustring value=desc};
if( this.queryConfig2(serviceName,0x1/*_SERVICE_CONFIG_DESCRIPTION*/,out) )
return out.value;
};
queryBinaryPathName = function(serviceName){
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
var cfg = this.queryConfig(serviceName)
if( cfg ) return cfg.binaryPathName;
};
startDelayed = function(serviceName,delayed){
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
return this.startAutomatic(serviceName) ? this.changeConfig2(serviceName,3/*_SERVICE_CONFIG_DELAYED_AUTO_START_INFO*/,{bool delayed=delayed});
};
startManual = function(serviceName){
return this.changeConfig(serviceName,,0x3/*_SERVICE_DEMAND_START*/);
};
startAutomatic = function(serviceName){
return this.changeConfig(serviceName,,0x2/*_SERVICE_AUTO_START*/);
};
startDisabled = function(serviceName){
return this.changeConfig(serviceName,,0x4/*_SERVICE_DISABLED*/);
};
changeConfig = function(serviceName,serviceType,startType,errorControl,binaryPathName,loadOrderGroup,tagId,dependencies,serviceStartName,password,displayName){
if(!this.handle) return ;
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
if( startType === null ) startType = 0x2/*_SERVICE_AUTO_START*/
if( serviceType === null ) serviceType = 0xFFFFFFFF/*_SERVICE_NO_CHANGE_INT*/
if( errorControl === null ) errorControl = 0xFFFFFFFF/*_SERVICE_NO_CHANGE_INT*/
var hService = this.open(serviceName,0x2/*_SERVICE_CHANGE_CONFIG*/ )
if (hService) {
if(!tagId[["_struct"]]) tagId = null;// { INT value = tagId };
var ret = ::Advapi32.ChangeServiceConfigW(hService,serviceType,startType,errorControl,binaryPathName,loadOrderGroup,tagId,dependencies,serviceStartName,password,displayName);
::Advapi32.CloseServiceHandle(hService);
return !!ret;
}
};
changeConfig2 = function(serviceName,infoLevel,struct){
if(!this.handle) return ;
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
if( !struct[["_struct"]] ) error("参数@3必须是结构体",2)
var hService = this.open(serviceName, 0x2/*_SERVICE_CHANGE_CONFIG*/);
if (hService) {
var ret = ::Advapi32.ChangeServiceConfig2W(hService,infoLevel,struct);
::Advapi32.CloseServiceHandle(hService);
return !!ret;
}
}
queryConfig2 = function(serviceName,infoLevel,struct){
if(!this.handle) return ;
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
if( !struct[["_struct"]] ) error("参数@3必须是结构体",2)
var hService = this.open(serviceName, 1/*_SERVICE_QUERY_CONFIG*/)
if (hService) {
var needSize = {INT size};
::Advapi32.QueryServiceConfig2W(hService,infoLevel,null,0,needSize);
var buffer = ..raw.buffer(needSize.size);
var ret = ::Advapi32.QueryServiceConfig2(hService,infoLevel,buffer,#buffer,needSize);;
::Advapi32.CloseServiceHandle(hService);
if( ret ){
..raw.convert(buffer,struct)
}
return ret;
}
}
queryConfig = function(serviceName){
if(!this.handle) return ;
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
var hService = this.open(serviceName, 0x1/*_SERVICE_QUERY_CONFIG*/)
if (hService) {
var cfg;
var cbBytesNeeded = {INT value};
::Advapi32.QueryServiceConfig(hService,null,0,cbBytesNeeded)
if( ::GetLastError() != 0x7A/*_ERROR_INSUFFICIENT_BUFFER*/) return;
var buf = ..raw.buffer(cbBytesNeeded.value);
if( ::Advapi32.QueryServiceConfig(hService,buf,cbBytesNeeded.value,cbBytesNeeded) ){
cfg = ..raw.convert(buf,QUERY_SERVICE_CONFIG());;
}
::Advapi32.CloseServiceHandle(hService);
return cfg;
}
};
each = function(serviceType,serviceState,groupName){
if( serviceType === null ) serviceType = 0x30/*_SERVICE_WIN32*/;
if( serviceState === null )serviceState = 0x3/*_SERVICE_STATE_ALL*/;
if(!this.handle) return ;
var cbBytesNeeded = {INT size};
var servicesReturned = {INT size};
var resumeHandle = {INT handle};
var ok = ::Advapi32.EnumServicesStatusExW(this.handle,0/*_SC_ENUM_PROCESS_INFO*/,serviceType,serviceState,null,0,cbBytesNeeded,servicesReturned,resumeHandle,groupName);
if( ok || ( ::GetLastError() != 0xEA/*_ERROR_MORE_DATA*/) ){ return function(){} };
var buffer = ..raw.buffer(cbBytesNeeded.size);
var ok = ::Advapi32.EnumServicesStatusExW(this.handle,0/*_SC_ENUM_PROCESS_INFO*/,serviceType,serviceState,buffer,cbBytesNeeded.size,cbBytesNeeded,servicesReturned,resumeHandle,groupName);
if( !ok ){
return function(){ }
}
var offset = 0;
var count = servicesReturned.size;
var info = {
ustring serviceName;
ustring displayName;
struct svrStatusProcess = SERVICE_STATUS_PROCESS();
}
var infoSize = ..raw.sizeof(info);
return function(){
if( !count ) return;
..raw.convert(buffer,info,offset);
offset = offset + infoSize;
count--;
info.svrStatusProcess.state = STATE_TEXT[info.svrStatusProcess.currentState];
return info.serviceName,info.displayName,info.svrStatusProcess;
}
};
eachDependent = function(serviceName,serviceState){
if( serviceState === null )serviceState = 0x3/*_SERVICE_STATE_ALL*/;
if(!this.handle) return ;
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名",2);
var hService = this.open(serviceName, 8/*_SERVICE_ENUMERATE_DEPENDENTS*/)
if (!hService) return;
var cbBytesNeeded = {INT size};
var servicesReturned = {INT size};
var ok = ::Advapi32.EnumDependentServicesW(hService,serviceState,null,0,cbBytesNeeded,servicesReturned);
if( ok || ( ::GetLastError() != 0xEA/*_ERROR_MORE_DATA*/) ){ ::Advapi32.CloseServiceHandle(hService);return function(){} };
var buffer = ..raw.buffer(cbBytesNeeded.size);
var ok = ::Advapi32.EnumDependentServicesW(hService,serviceState,buffer,cbBytesNeeded.size,cbBytesNeeded,servicesReturned);
if( !ok ){ ::Advapi32.CloseServiceHandle(hService); return function(){} };
var offset = 0;
var count = servicesReturned.size;
var info = {
ustring serviceName;
ustring displayName;
struct serviceStatus = SERVICE_STATUS();
}
var infoSize = ..raw.sizeof(info);
return function(){
if( !count ) return;
..raw.convert(buffer,info,offset);
offset = offset + infoSize;
count--;
info.serviceStatus.state = STATE_TEXT[info.serviceStatus.currentState];
return info.serviceName,info.displayName,info.serviceStatus;
},function(){
::Advapi32.CloseServiceHandle(hService);
}
};
close = function(){
if( this.handle ){
::Advapi32.CloseServiceHandle(this.handle);
this.handle = null;
}
}
}
namespace manager {
class QUERY_SERVICE_CONFIG {
INT serviceType;
INT startType;
INT errorControl;
ustring binaryPathName;
ustring loadOrderGroup;
INT tagId;
ustring dependencies;
ustring serviceStartName;
ustring displayName;
}
class SERVICE_STATUS_PROCESS {
INT serviceType;
INT currentState;
INT controlsAccepted;
INT win32ExitCode;
INT serviceSpecificExitCode;
INT checkPoint;
INT waitHint;
INT processId;
INT serviceFlags;
}
class SERVICE_STATUS {
INT serviceType;
INT currentState;
INT controlsAccepted;
INT win32ExitCode;
INT serviceSpecificExitCode;
INT checkPoint;
INT waitHint;
}
STATE_TEXT = {
[5] = "CONTINUE_PENDING";
[6] = "PAUSE_PENDING";
[7] = "PAUSED";
[4] = "RUNNING";
[2] = "START_PENDING";
[3] = "STOP_PENDING";
[1] = "STOPPED";
}
}
isExist = function(serviceName){
var srvMgr = manager();
var ret = srvMgr.isExist( serviceName );
srvMgr.close();
return ret;
}
start = function(serviceName){
var srvMgr = manager();
var ret = srvMgr.start( serviceName );
srvMgr.close();
return ret;
}
pause = function(serviceName){
var srvMgr = manager();
var ret = srvMgr.pause( serviceName );
srvMgr.close();
return ret;
}
resume = function(serviceName){
var srvMgr = manager();
var ret = srvMgr.resume( serviceName );
srvMgr.close();
return ret;
}
stop = function(serviceName,term){
var srvMgr = manager();
var ret = srvMgr.stop( serviceName,term );
srvMgr.close();
return ret;
}
terminate = function(serviceName){
var srvMgr = manager();
var ret = srvMgr.terminate( serviceName );
srvMgr.close();
return ret;
}
restart = function(serviceName,stopSec,startSec){
var srvMgr = manager();
var ret = srvMgr.restart( serviceName );
srvMgr.close();
return ret;
}
isStopped = function(serviceName){
var srvMgr = manager();
var ret = srvMgr.isStopped( serviceName );
srvMgr.close();
return ret;
}
isRunning = function(serviceName){
var srvMgr = manager();
var ret = srvMgr.isRunning( serviceName );
srvMgr.close();
return ret;
}
delete = function(serviceName){
var srvMgr = manager();
var ret = srvMgr.delete( serviceName );
srvMgr.close();
return ret;
}
create = function(binaryPathName,serviceName,displayName,description,...){
if( binaryPathName === null ) binaryPathName = ..io._exepath;
if( type(binaryPathName) != type.string || !#binaryPathName ) error("请指定服务启动程序,参数@1错误",2);
if( type(serviceName) != type.string || !#serviceName ) error("请指定服务名,参数@2错误",2);
var srvMgr = manager(0x2/*_SC_MANAGER_CREATE_SERVICE*/);
var ret = srvMgr.create( binaryPathName,serviceName,displayName,...);
if( ret ){
srvMgr.changeDescription(serviceName,description)
}
srvMgr.close();
return ret;
}
each = function(serviceType,serviceState,groupName){
var serviceMgr = manager(0x4/*_SC_MANAGER_ENUMERATE_SERVICE*/);
return serviceMgr.each(serviceType,serviceState,groupName),function(){
serviceMgr.close();
}
}
_serveiceTableEntry = {};
//服务没有结束前此函数不会返回,注册的入口函数启动服务以后应当首先调用registerServiceCtrlHandler
startDispatchThread = function( disp ){
if(type(disp)!="table"){
if(type(disp)=="boolean"){
error("service.startDispatchThread 函数接收到的参数类型错误,
参数表的首个键名如果放在下标操作符 [] 内,则不能省略包围表的 { } 符号。
正确格式:
service.startDispatchThread( {
[service.serviceName] = function(serviceName,argv){
}
} )",2);
}
else{
error("service.startDispatchThread 函数的参数必须是表对象")
}
}
for(serviceName,serviceProc in disp){
..table.push( _serveiceTableEntry,{ustring serviceName = serviceName; pointer lpServiceProc = ..thread.tostdcall(
function(argc,argv){
import service;
service.serviceName = serviceName;
if( argc ){
argv = ..raw.convertArray(argv,argc,"ustring")
}
return owner.serviceProc(owner.serviceName,argv);
},"void(int,pointer)",{serviceProc = serviceProc;serviceName=serviceName}) } );
}
..table.push( _serveiceTableEntry ,{ustring serviceName;pointer lpServiceProc} );
::Advapi32.StartServiceCtrlDispatcherW( { struct entry[] = _serveiceTableEntry } );
}
_serveiceCtrlHandler = {};
registerCtrlThread = function( serviceName,handler ){
if( type(serviceName) != type.string || !#serviceName) error("请指定服务名,参数@1错误",2);
_serveiceCtrlHandler[serviceName] = ..thread.tostdcall(handler,"int(int,int,ptr,ptr)",{serviceName=serviceName});
var hServiceStatus = ::Advapi32.RegisterServiceCtrlHandlerExW( serviceName,_serveiceCtrlHandler[serviceName],null);
if(hServiceStatus){
var status = manager.SERVICE_STATUS();
status.serviceType = 0x30/*_SERVICE_WIN32*/
status.currentState = 0x2/*_SERVICE_START_PENDING*/
status.controlsAccepted = 0x1/*_SERVICE_ACCEPT_STOP*/
status.hServiceStatus = hServiceStatus;
status.threadId = ..thread.getId();
..thread.set("NT_SERVICE_STATUS(" + serviceName + ")", )
return status;
}
}
updateStatus = function(status,serviceName){
if( type(serviceName) != type.string || !#serviceName) error("请指定服务名,参数@1错误",2);
if( status.threadId == ..thread.getId() && status._struct ){
..thread.set("NT_SERVICE_STATUS(" + serviceName + ")", status )
}
else {
status = ..table.assign( ..thread.get("NT_SERVICE_STATUS(" + serviceName + ")"),status);
}
return ::Advapi32.SetServiceStatusW( status.hServiceStatus,status);
}
::Wtsapi32 := ..raw.loadDll("Wtsapi32.dll");
sessions = function(){
var infos = {ptr p}
var count = {INT v}
if (::Wtsapi32.WTSEnumerateSessions(serverHandle,,1,infos,count)){
var ret = ..raw.convertArray(infos.p,count.v,{
INT sessionId;
ustring stationName;
int state;
})
::Wtsapi32.WTSFreeMemory(infos.p);
return ret;
}
}
eachSession = function(){
var s = sessions() : {};
var i,v;
return function(){
i,v = ..table.next(s,i);
if(v) return v.id,v.station,v.state;
}
}
activeSessionId = lambda() ::Kernel32.WTSGetActiveConsoleSessionId();
msgbox = function(str,title,timeout,style,sid){
if( sid === null ) sid = activeSessionId();
if(sid===null) return;
if(style===null) style = 0x40 //_MB_OK|_MB_ICONINFORMATION;
else style = ({"error":0x10,stop:0x10,hand:0x10,question:0x23,confirm:0x21,test:0x21,warn:0x30,info:0x40})[style]||tonumber(style)||0;
if( type(str) == type.table) str = ..table.tostring(str);
str = ..string.toUtf16(tostring(str));
title = ..string.toUtf16(tostring(title : self.serviceName : "service" ) );
var resp = {int v}
if( ::Wtsapi32.WTSSendMessageW(0,sid,
title,#title,str,#str,style,timeout,resp,timeout!==nul) ){
return resp.v;
}
}
msgboxErr = function(str,title){
return msgbox(str,title,,0x10/*_MB_ICONHAND*/);
}
msgboxTest = function(str,title,timeout){
return msgbox(str,title,0x1 | 0x20 /*_MB_OKCANCEL|_MB_ICONQUESTION*/ ,timeout:10000 ) == 1/*_IDOK*/;
}
/**details(说明)
发布为 EXE 以后,在桌面上直接双击运行就会显示控制台。
在控制台窗口按 Y 注册系统服务,按 N 卸载系统服务。
操作系统开机就会自动启动注册成功的后台服务。
服务进程不能在用户桌面上直接显示界面,
新系统在 ~~服务管理器中勾选 【允许与桌面交互】~~ 是无效的。
但可以通过 service.msgbox,service.msgboxErr,service.msgboxTest 等函数向用户桌面发送对话框。
记录运行时数据或错误信息的一些方法:
- 使用 fsys.log 读写日志文件
- 简单写数据到文件可以使用 io.file.write 或 string.save 函数
- 可使用 JSON.save 函数将对象以 JSON 格式输出到文件。
end details**/
/**intellisense()
service = NT 服务操作\n部分操作需要管理权限
service.serviceName = 当前服务线程中运行的 NT 服务名,\n主线程应自行指定
service.isExist(.("服务名") = 是否存在指定的服务
service.start(.("服务名") = 启动服务,\n成功返回 true,\n失败请使用 lasterr 函数获取错误信息
service.restart(.("服务名",停止超时,启动超时) = 重新启动服务,成功返回 true ,\n超时以秒为单位,省略则不限时间等待操作完成\n停止超时达到时间后服务未正常停止则强制中断服务进程
service.stop(.("服务名") = 停止服务,\n成功返回 true ,\n失败请使用 lasterr 函数获取错误信息
service.stop(.("服务名",true) = 停止服务,如果失败就强制中断服务进程,\n成功返回 true ,\n失败请使用 lasterr 函数获取错误信息
service.terminate(.("服务名") = 强制中断服务进程,\n成功返回 true ,
service.isStopped(.("服务名") = 服务是否已停止
service.isRunning(.("服务名") = 服务是否正在运行
service.pause(.("服务名") = 暂停服务,\n成功返回 true ,\n失败请使用 lasterr 函数获取错误信息
service.resume(.("服务名") = 暂停状态恢复运行,\n成功返回 true ,\n失败请使用 lasterr 函数获取错误信息
service.create(.(启动路径,服务名,显示全名,服务描述) = 创建服务,\n参数@1可为空,默认使用当前应用程序路径,\n其他可选参数未列出请查看函数源码
service.delete(.("服务名") = 删除服务\n注意删除服务前最好关闭服务管理器
service.manager(.(desiredAccess,machineName,databaseName) = 创建管理器
service.manager() = !ntsrvmgr.
!ntsrvmgr.create(.(启动路径,服务名,显示全名) = 创建服务,其他可选参数未列出请查看函数源码
!ntsrvmgr.open(serviceName,desiredAccess) = 打开服务句柄
!ntsrvmgr.close() = 关闭
!ntsrvmgr.isExist(.("服务名") = 是否存在指定的服务
!ntsrvmgr.start(.("服务名") = 启动服务,\n成功返回 true ,\n失败请使用 lasterr 函数获取错误信息
!ntsrvmgr.stop(.("服务名") = 停止服务,\n成功返回 true ,\n失败请使用 lasterr 函数获取错误信息
!ntsrvmgr.stop(.("服务名",true) = 停止服务,如果失败就强制中断服务进程,\n成功返回 true ,\n失败请使用 lasterr 函数获取错误信息
!ntsrvmgr.terminate(.("服务名") = 强制中断服务进程,\n成功返回 true ,
!ntsrvmgr.pause(.("服务名") = 暂停服务,\n成功返回 true ,\n失败请使用 lasterr 函数获取错误信息
!ntsrvmgr.resume(.("服务名") = 暂停状态恢复运行,\n成功返回 true ,\n失败请使用 lasterr 函数获取错误信息
!ntsrvmgr.delete(.("服务名") = 删除服务\n注意删除服务前最好关闭服务管理器
!ntsrvmgr.control(.(serviceName,desiredAccess,control) = 控制服务
!ntsrvmgr.queryStatus(.("服务名") = 成功返回一个表示服务状态的表对象
!ntsrvmgr.wait(.("服务名",状态码) = 等待服务切换到指定状态\n状态码不指定时默认为 4/*_SERVICE_RUNNING*/\n成功返回一个表示服务状态的表对象
!ntsrvmgr.startAndWait(.("服务名",进程权限) = 启动服务并等待服务进程切换到运行状态,\n返回打开的进程对象(process 对象),可选用参数@2指定进程访问权限
!ntsrvmgr.isStopped(.("服务名") = 服务是否已停止
!ntsrvmgr.isRunning(.("服务名") = 服务是否正在运行
!ntsrvmgr.queryConfig(.("服务名") = 返回配置
!ntsrvmgr.changeDescription(.("服务名","说明") = 修改服务说明
!ntsrvmgr.queryDescription(.("服务名") = 返回服务说明
!ntsrvmgr.queryBinaryPathName(.("服务名") = 返回启动路径以及参数
!ntsrvmgr.changeConfig(.(serviceName,serviceType,startType) = 修改配置,其他可选参数未列出请查看函数源码
!ntsrvmgr.queryConfig2(.("服务名",配置项,配置值) = 获取配置\n配置值必须是结构体
!ntsrvmgr.startDelayed(.("服务名",是否延时) = 设置为延时启动
!ntsrvmgr.startManual(.("服务名") = 设置为手动启动
!ntsrvmgr.startAutomatic(.("服务名") = 设置为自动启动
!ntsrvmgr.startDisabled(.("服务名") = 设置为禁用
!ntsrvmgr.changeConfig2(.("服务名",配置项,配置值) = 修改配置\n配置值必须是结构体
!ntsrvmgr.eachDependent() = !ntsrvsta2.
!ntsrvmgr.eachDependent("服务名") = @for(serviceName,displayName,serviceStatus in ??.eachDependent("__/*指定服务名列出依赖此服务的服务*/") ){
}
service.each(serviceType,serviceState,groupName) = @for( serviceName,displayName,svrStatusProcess in service.each()){
io.print(serviceName, displayName,svrStatusProcess.state)
}
service.updateStatus(.(服务状态表,服务名) = 参数@1应是registerCtrlHandler函数的返回值,\n在CtrlHandler函数中指定部分需要更新的值即可
service.startDispatchThread(服务回调函数表) = @.service.startDispatchThread( \n 服务名 = function(serviceName,argv){\n import service; \n var srvStatus = service.registerCtrlThread(serviceName,function(control,eventType,pEventData){ \n import service; \n if( control == 0x1/*_SERVICE_CONTROL_STOP*/ ){ \n service.updateStatus({currentState = 0x1/*_SERVICE_STOPPED*/},owner.serviceName); \n } \n } )\n \n srvStatus.controlsAccepted = 0x1/*_SERVICE_ACCEPT_STOP*/\n srvStatus.currentState = 0x4/*_SERVICE_RUNNING*/;\n service.updateStatus(srvStatus,serviceName)\n \n __/*服务运行代码*/\n \n srvStatus.controlsAccepted = 0;\n srvStatus.currentState = 0x1/*_SERVICE_STOPPED*/\n service.updateStatus(srvStatus,serviceName)\n }\n)
service.registerCtrlThread(serviceName,handle) = @.registerCtrlThread( serviceName,function(control,eventType,pEventData){\n \n }\n)
service.registerCtrlThread() = !ntsrvsta2.
service.each() = !ntsrvsta2.
!ntsrvmgr.queryStatus() = !ntsrvsta2.
!ntsrvmgr.wait() = !ntsrvsta2.
!ntsrvmgr.startAndWait() = !process.
!ntsrvsta2.serviceType = serviceType
!ntsrvsta2.currentState = currentState
!ntsrvsta2.state = state
!ntsrvsta2.controlsAccepted = controlsAccepted
!ntsrvsta2.win32ExitCode = win32ExitCode
!ntsrvsta2.serviceSpecificExitCode = serviceSpecificExitCode
!ntsrvsta2.checkPoint = checkPoint
!ntsrvsta2.waitHint = waitHint
!ntsrvsta2.processId = processId
!ntsrvsta2.serviceFlags = processId
!ntsrvmgr.queryConfig() = !ntsrvconfig.
!ntsrvconfig.serviceType = serviceType
!ntsrvconfig.startType = startType
!ntsrvconfig.errorControl = errorControl
!ntsrvconfig.binaryPathName = binaryPathName
!ntsrvconfig.loadOrderGroup = loadOrderGroup
!ntsrvconfig.tagId = tagId
!ntsrvconfig.dependencies = dependencies
!ntsrvconfig.serviceStartName = serviceStartName
!ntsrvconfig.displayName = displayName
service.sessions() = 返回操作系统所有登录用户会话,\n更多会话控制请参考标准库 win.ts
service.eachSession() = @for id,station,state in service.eachSession(){
if( state == 0 ) return id;__/*遍历操作系统所有登录用户会话,\nid 为会话 ID,station 为会话名,state 为会话状态。\nstate 为 0 表示登录激活状态,1 为已连接,4 为断开状态*/
}
service.activeSessionId() = 返回操作系统活动用户会话ID,\n更多会话控制请参考标准库 win.ts
service.msgboxErr(.("文本","标题") = 弹出错误对话框。\n所有者窗口参数可选。\n如果参数 @1 是表对象,则自动调用 table.tostring 序列化为文本。\n其他类型调用 tostring 转为字符串。
service.msgbox(.("文本","标题",等待超时值,样式) = 弹出对话框。\n返回用户操作 ID,如果不指定超时值则不等待用户操作,并总是返回 32001/*_IDASYNC*/。\n超时值以毫秒为单位,超时为 0 表示一直等待,。不指定超时则不等待用户操作。\n除参数 @1 以外,其他所有参数可选。\n如果参数 @1 是表对象,自动调用 table.tostring 序列化为文本。\n参数 @1 是其他类型则调用 tostring 转为字符串。\n\n可选参数 @4 可用字符串或数值指定图标样式(参考 _MB_ 前缀常量值,设为 0 去掉图标与提示音),可选字符串值:\n- "error","stop","hand" 错误图标\n- "question" 询问图标,显示是、否、取消按钮,返回值为 `6/*_IDYES*/,7/*_IDNO*/, 2/*_IDCANCEL*/` 之一。\n- "confirm","test" 询问图标,显示确定与取消按钮,返回值为 `1/*_IDOK*/,2/*_IDCANCEL*/` 之一。\n- "warn" 警告图标\n- "info" 信息图标。
service.msgboxTest(.("文本","标题") = 返回布尔值表示用户是否按了“确定”按钮。\n标题,所有者窗口参数可选
end intellisense**/
/**intellisense()
_SERVICE_FILE_SYSTEM_DRIVER=@2/*_SERVICE_FILE_SYSTEM_DRIVER*/
_SERVICE_KERNEL_DRIVER=@1/*_SERVICE_KERNEL_DRIVER*/
_SERVICE_WIN32_OWN_PROCESS=@0x10/*_SERVICE_WIN32_OWN_PROCESS*/
_SERVICE_WIN32_SHARE_PROCESS=@0x20/*_SERVICE_WIN32_SHARE_PROCESS*/
_SERVICE_CONTINUE_PENDING=@5/*_SERVICE_CONTINUE_PENDING*/
_SERVICE_PAUSE_PENDING=@6/*_SERVICE_PAUSE_PENDING*/
_SERVICE_PAUSED=@7/*_SERVICE_PAUSED*/
_SERVICE_RUNNING=@4/*_SERVICE_RUNNING*/
_SERVICE_START_PENDING=@2/*_SERVICE_START_PENDING*/
_SERVICE_STOP_PENDING=@3/*_SERVICE_STOP_PENDING*/
_SERVICE_STOPPED=@1/*_SERVICE_STOPPED*/
_SERVICE_ACCEPT_NETBINDCHANGE=@0x10/*_SERVICE_ACCEPT_NETBINDCHANGE*/
_SERVICE_CONTROL_NETBINDADD=@7/*_SERVICE_CONTROL_NETBINDADD*/
_SERVICE_CONTROL_NETBINDREMOVE=@8/*_SERVICE_CONTROL_NETBINDREMOVE*/
_SERVICE_CONTROL_NETBINDENABLE=@9/*_SERVICE_CONTROL_NETBINDENABLE*/
_SERVICE_CONTROL_NETBINDDISABLE=@0xA/*_SERVICE_CONTROL_NETBINDDISABLE*/
_SERVICE_ACCEPT_PARAMCHANGE=@8/*_SERVICE_ACCEPT_PARAMCHANGE*/
_SERVICE_CONTROL_PARAMCHANGE=@6/*_SERVICE_CONTROL_PARAMCHANGE*/
_SERVICE_ACCEPT_PAUSE_CONTINUE=@2/*_SERVICE_ACCEPT_PAUSE_CONTINUE*/
_SERVICE_CONTROL_PAUSE=@2/*_SERVICE_CONTROL_PAUSE*/
_SERVICE_CONTROL_CONTINUE=@3/*_SERVICE_CONTROL_CONTINUE*/
_SERVICE_ACCEPT_SHUTDOWN=@4/*_SERVICE_ACCEPT_SHUTDOWN*/
_SERVICE_CONTROL_SHUTDOWN=@5/*_SERVICE_CONTROL_SHUTDOWN*/
_SERVICE_ACCEPT_STOP=@1/*_SERVICE_ACCEPT_STOP*/
_SERVICE_CONTROL_STOP=@1/*_SERVICE_CONTROL_STOP*/
_SERVICE_CONTROL_INTERROGATE=@4/*_SERVICE_CONTROL_INTERROGATE*/
_SERVICE_ACCEPT_HARDWAREPROFILECHANGE=@0x20/*_SERVICE_ACCEPT_HARDWAREPROFILECHANGE*/
_SERVICE_CONTROL_HARDWAREPROFILECHANGE=@0xC/*_SERVICE_CONTROL_HARDWAREPROFILECHANGE*/
_SERVICE_ACCEPT_POWEREVENT=@0x40/*_SERVICE_ACCEPT_POWEREVENT*/
_SERVICE_CONTROL_POWEREVENT=@0xD/*_SERVICE_CONTROL_POWEREVENT*/
_SERVICE_ACCEPT_SESSIONCHANGE=@0x80/*_SERVICE_ACCEPT_SESSIONCHANGE*/
_SERVICE_CONTROL_SESSIONCHANGE=@0xE/*_SERVICE_CONTROL_SESSIONCHANGE*/
_SERVICE_RUNS_IN_SYSTEM_PROCESS=@1/*_SERVICE_RUNS_IN_SYSTEM_PROCESS*/
_SERVICE_AUTO_START=@2/*_SERVICE_AUTO_START*/
_SERVICE_BOOT_START=@0/*_SERVICE_BOOT_START*/
_SERVICE_DEMAND_START=@3/*_SERVICE_DEMAND_START*/
_SERVICE_DISABLED=@4/*_SERVICE_DISABLED*/
_SERVICE_SYSTEM_START=@1/*SERVICE_SYSTEM_START*/
_SERVICE_ADAPTER=@4/*_SERVICE_ADAPTER*/
_SERVICE_FILE_SYSTEM_DRIVER=@2/*_SERVICE_FILE_SYSTEM_DRIVER*/
_SERVICE_KERNEL_DRIVER=@1/*_SERVICE_KERNEL_DRIVER*/
_SERVICE_RECOGNIZER_DRIVER=@8/*_SERVICE_RECOGNIZER_DRIVER*/
_SERVICE_WIN32_OWN_PROCESS=@0x10/*_SERVICE_WIN32_OWN_PROCESS*/
_SERVICE_WIN32_SHARE_PROCESS=@0x20/*_SERVICE_WIN32_SHARE_PROCESS*/
_SERVICE_WIN32 =@0x30/*_SERVICE_WIN32*/
_SERVICE_ACTIVE=@1/*_SERVICE_ACTIVE*/
_SERVICE_CHANGE_CONFIG=@2/*_SERVICE_CHANGE_CONFIG*/
_SERVICE_INACTIVE=@2/*_SERVICE_INACTIVE*/
_SERVICE_INTERROGATE=@0x80/*_SERVICE_INTERROGATE*/
_SERVICE_PAUSE_CONTINUE=@0x40/*_SERVICE_PAUSE_CONTINUE*/
_SERVICE_USER_DEFINED_CONTROL=@0x100/*_SERVICE_USER_DEFINED_CONTROL*/
end intellisense**/