将脚本作为服务运行 - Exsead Service Manager






3.75/5 (4投票s)
Exsead Service Manager 是一个开源(BSD 风格许可)的 Windows 服务,它通过使用脚本来启动任何内容。它刚刚被发布为开源,更多关于它的信息如下。
引言
Exsead Service Manager 是一个开源(BSD 风格许可)的 Windows 服务,它通过使用脚本来启动任何内容。
在 Unix 世界中,服务的等价物是通过脚本启动的。这使得工作非常简单。如果想添加一个后台活动,只需将它的启动程序添加到这些脚本之一中即可。不需要特殊编译的可执行文件。在 Windows 世界中,我们选择直接从 Windows 服务系统运行可执行文件。这些可执行文件必须编译进一个特殊的接口。虽然这种方法在许多情况下都有其优点,但它缺乏灵活性,并导致了糟糕的实现,例如使用“运行”级别的注册表指令,而服务将是更可取的。
Exsead Service Manager 的目标是成为整个 Exsead 概念的一部分:EXtreme Script Enterprise Application Development(极致脚本企业应用开发)。在这种情况下,具体目标是将脚本作为服务启动。一旦服务被脚本化,您就可以轻松地做任何事情!
请帮忙!ExseadServiceManager 现在是一个 Source Forge 项目。我正在积极开发,但需要帮助设置 Source Forge SSH、CVS 和网站。
如果您有兴趣帮助这个项目,请随时通过 ajt(at)nerds-central.com 与我联系。目前,当前版本和源代码可以在此处找到。随着我产品的开发,我将在那里发布新版本。请关注 Nerds-Central 获取新闻。我目前正在持续使用此版本,并且我认为核心功能对于 XP/SP2 来说是 beta 版。对于其他操作系统的一些功能,我将认为是 alpha 版。
ExseadServiceManager 实际上是如何工作的?
服务管理器本身只是一个可执行文件。这个可执行文件负责安装、配置、卸载和运行服务。它通过运行方式和命令行参数的性质来区分需要执行的操作。
安装和使用服务管理器的步骤如下:
命名服务
ExseadServiceManager
的所有设计都力求简单。我的意思是,我们花了很多心思来让这个应用程序的使用变得简单。这里是第一个例子。它管理的服务的名称由可执行文件的名称控制。如果您想创建一个名为“FlyingPigsNeedNappies
”(纸尿裤)的服务,那么您只需复制一份 ExseadServiceManager.exe 并将其重命名为 FlyingPigsNeedNappies.exe。就这么简单——真的。
它将在哪里运行?
当您使用 ExseadServiceManager
安装服务时,它会将服务的工作目录设置为执行安装的目录。所以,如果您创建一个目录 c:\FlyingPigs\Service 并打开一个 CMD 框,然后更改目录到 c:\FlyingPigs\Service 并运行 FlyingPigsNeedNappies.exe -I
,那么该服务将在 c:\FlyingPigs\Service 中运行。同样——简单。
安装服务
如上所述,您只需运行可执行文件并带上 -I
选项。这将使其以本地管理员身份运行。如果您使用 -i
选项,它将以不同的帐户运行。
配置服务
可以通过可执行文件的命令行选项来配置、启动、停止和卸载服务。
将服务连接到某个东西
设置好这个服务是很有用的,但它必须要做点什么。这是通过与可执行文件同名但扩展名为 vbs 的脚本来实现的。对于此版本,初始脚本仅支持 VBScript,但后续版本应解决此问题。所以,在 flying pigs 的例子中,初始脚本的名称将是 FlyingPigsNeedNappies.vbs。稍后我将在本文中讨论初始脚本的结构。
日志去哪里了?
当服务管理器作为服务运行时,其日志会发送到其运行帐户的默认临时目录。例如,如果它以本地管理员身份运行,它会将日志发送到 Windows\Temp 目录下的名称.log 文件。对于 flying pigs 的例子,它将是 Windows\FlyingPigsNeedNappies.log。请注意,发送到日志的信息量很少,因为运行服务的大部分工作是由初始脚本完成的,而不是服务管理器。以下是一个日志输出示例:
Service Main Called
Service Handler Acquired
Opening Service: 'TAGService'
Changing working dir to 'C:\CodeRepo\InfraStructure\InstallationAids'
About to run 'start'
Acquiring script object: TAGService.vbs
Acquired script object.
Loaded Script OK.
这是通过运行可执行文件并带上 -?
选项生成的命令行选项的完整列表:
Exsead Service Manager: Command Line Args
-? Print this message
-r run start method directly avoiding service
-e print out current env block
-i 'user' 'pass' install service
-I install service as local admin
-u uninstall service
-v print version info
-s start service
-k stop service
-K first kill all descendants of the service process then stop service
-Z first kill all descendants of the process then kill it.
-M set to manual start
-A set to auto start
-D set to disabled
-S set to system start
-B set to boot start
Notes: -K suspends the processes as it traverses the tree, but even with this
level of checking, it might not get them all or it might kill a process
that has just received the same pid as one that used to be a descendent.
Please use this function with caution. This also applies to -Z.
创建和初始化服务脚本
至少,初始脚本必须包含两个子例程:StartService
和 StopService
。这两个例程都不接受任何参数。
StartService
在服务本身启动时由服务管理器调用。这个子例程必须启动服务所做的任何事情。当这个子例程退出时,服务将停止。这意味着如果您希望服务保持运行,您必须不要让这个子例程退出,直到服务被强制停止。这可以通过一个无限循环来实现,请参见下面的示例。
StopService
在 Windows 请求停止服务时由服务管理器调用。这可以通过运行可执行文件并带上 -k
选项或使用其他实用程序来启动。StopService
是在与启动服务不同的活动线程中调用的,因此 StartService
没有退出并不重要。在 StopService
中,您必须执行任何必要的进程关闭和清理工作,然后返回。
这是一个实际的初始化脚本,用于运行 TAG Web 应用程序网关的 TAGService
。
Option Explicit
' Constants and identifiers
' =========================
CONST SERVICE_NAME = "TAGService"
CONST ForReading = 1, ForWriting = 2, ForAppending = 3
' Globals
' =======
Dim objWSHShell
Dim objWSHNetwork
Dim objFSO
Dim objLogger
Dim is_init
' This method ensures the globals are up
' but only creates the object (expensive)
' once.
sub init()
if not is_init then
Set objWSHShell = CreateObject("WScript.Shell")
Set objWSHNetwork = CreateObject("WScript.Network")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objLogger = new Logger
is_init=true
end if
end sub
class Logger
private logFile
Private Sub Class_Initialize()
set logFile=objFSO.openTextFile(SERVICE_NAME+"_script.log",ForWriting,true)
End Sub
public sub WriteLog(what)
logFile.writeLine(what)
end sub
Private Sub Class_Terminate()
logFile.close
End Sub
end class
sub StartService()
init
'objWSHShell.run SERVICE_NAME + ".exe -K"
Dim curdir
dim tagFile
curdir = objWSHShell.CurrentDirectory
tagFile = curdir & "\..\CRI\bin\TAG_Runner.exe"
If not objFSO.FileExists(tagFile) then
SilentReport "Could not find " & tagFile, 0
exit sub
end if
objWSHShell.CurrentDirectory=curdir +"\..\CRI\bin"
while 1=1
objWSHShell.run "TAG_Runner.exe",0,true
wend
end sub
sub StopService()
init
' Simply kill any running child processes of the script
objWSHShell.run SERVICE_NAME + ".exe -K"
end sub
Sub SilentReport(sString, iErr)
init
objLogger.WriteLog(now & ": " & sString & " , " & iErr)
End Sub
有关此主题和其他主题的更多信息,请参阅 Nerds-Central。