使用srvany.exe将任何程序作为Windows服务运行

!本文可能 超过1年没有更新,今后内容也许不会被维护或者支持,部分内容可能具有时效性,涉及技术细节或者软件使用方面,本人不保证相应的兼容和可操作性。

srvany.exe是什么?

srvany.exe是Microsoft Windows Resource Kits工具集的一个实用的小工具,用于将任何EXE程序作为Windows服务运行。也就是说srvany只是其注册程序的服务外壳,这个特性对于我们来说非常实用,我们可以通过它让我们的程序以SYSTEM账户启动,或者实现随机器启动而自启动,也可以隐藏不必要的窗口,比如说控制台窗口等等。

如何获取?

你可以通过下载并安装Microsoft Windows Resource Kits获得或者可以通过我分享的下载地址1(国内线路)下载地址2(国外线路)得到。

如何使用?

当你获取到srvany后并决定将某程序作为服务启动后,请先将srvany安装为系统服务,具体的安装方法有很多,比如说可以通过Microsoft Windows Resource Kits中另外一个实用的小工具instsrv.exe进行安装(下载地址),将srvany.exe和instsrv.exe拷贝到C:\Windows\System32\后,我们可以通过下面的命令行进行srvany.exe的服务安装:

instsrv ServiceName C:\Windows\System32\srvany.exe

ServiceName即你自己定义的服务名称,可以是要作为系统服务启动的应用程序的名称。

安装完毕后,我们需要对srvany.exe进行配置,以便于能够加载我们指定的程序,配置的方法是,开始 – 运行 – regedit,打开注册表,定位到下面的路径。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ServiceName

同样的ServiceName是你刚才安装服务时自定义的服务名称。

如果该服务名下没有Parameters项目,则对服务名称项目右击新建项,名称为Parameters,然后定位到Parameters项,新建以下几个字符串值。

名称 Application 值为你要作为服务运行的程序地址。
名称 AppDirectory 值为你要作为服务运行的程序所在文件夹路径。
名称 AppParameters 值为你要作为服务运行的程序启动所需要的参数。

比如这里是个配置实例,我们这里配置的服务名称是NGINX,其余是nginx的安装配置情况。

srvany配置

当然还有一个比较简单的做法,那就是将下面的文本保存为*.reg文件,然后双击导入注册表。

1
2
3
4
5
6
Windows Registry Editor Version 5.00 
 
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\服务名称\Parameters] 
"Application"="值为你要作为服务运行的程序地址"
"AppDirectory"="值为你要作为服务运行的程序所在文件夹路径"
"AppParameters"="值为你要作为服务运行的程序启动所需要的参数"

2011年7月14日更新

找到微软的官方文章《如何创建用户定义的服务》,大家可以看一看。

2012年2月27日更新

今天有朋友问到将某窗体程序通过srvany作为服务运行的时候,桌面右下角图标和窗体无法显示,这个就涉及到服务的运行方式了,一般服务程序是不包含窗体的,所以系统默认可能会抑制这些服务程序产生的窗体,如果你的服务程序比较特殊,确实需要出现窗体,可以参考下面的办法:

控制面板 – 管理工具 – 服务(或者 开始 – 运行 – services.msc 确认)打开服务管理器,选择你刚刚安装并需要展示窗体的服务,然后右击选择属性,切换到 “登录” 选项卡,勾选上 “允许服务与桌面交互” 然后按确定保存,重启你的服务,看看窗体是否出现了:

允许服务与桌面交互

2012年7月3日更新

为了大家利用srvany.exe创建自定义服务的方便我特别写了个名叫SrvanyUI的服务创建管理的小工具,大家可以移步这篇文章《SrvanyUI服务管理工具发布》来获得详细信息,这里放个截图:

SrvanyUI服务管理工具

2012年7月5日更新

找到微软的一篇文章可以参考《故障排除使用 Cmd.exe 的 SrvAny》

2012年7月23日更新

近期有朋友咨询为什么勾选上 “允许服务与桌面交互”,窗体程序依旧不能显示,其实这个办法只适用于Windows XP或者Windows 2003系列的操作系统,对于以上版本的Windows Vista、Windows 2008、Windows 7以及Windows 2008 R2,微软做了改变,使用了Session 0会话隔离策略,所以再使用这个办法强制服务窗体显示就会出现提示框,只有手动允许后才会出现界面,并且桌面风格也将被更改:

交互式服务检测提示

交互式服务检测

此计算机上运行的程序正在尝试显示一条消息,程序可能需要您的信息或权限来完成任务。

交互式服务检测
此计算机上运行的程序正在尝试显示一条消息
程序可能需要您的信息或权限来完成任务。

关于Vista及高版本Windows交互出现提示框是由Interactive Services Detection服务控制的。禁用此服务将不会出现上述提示框,当然窗体也就不会显示了。

更详细的信息可以参考MSDN的《Interactive Services》文章。

特别注意下面这段:

Important Services cannot directly interact with a user as of Windows Vista. Therefore, the techniques mentioned in the section titled Using an Interactive Service should not be used in new code.

如果要在新的Vista及以上操作系统上显示窗体,我们应当使用新的技术,比如使用WTSSendMessage在用户会话显示对话框,或者将服务程序与窗体分离开来再使用进程通信(推荐)。

关于编程的方法可以参考这篇文章《解决vista和win7在windows服务中交互桌面权限问题:穿透Session 0 隔离》

抱歉的是目前的办法仅限于编程方面的,其他有效的办法我暂时还没有找到。

部分参考文档:

2012年2月27日更新

对于带参数的命令行方式直接利用srvany.exe创建自定义服务请参考文章《WScript/VBScript命令行参数使用srvany.exe创建自定义服务》

END

若无特别说明,本网站文章均为原创,原则上这些文章不允许转载,但是如果阁下是出于研究学习目的可以转载到阁下的个人博客或者主页,转载遵循创作共同性“署名-非商业性使用-相同方式共享”原则,请转载时注明作者出处谢绝商业性、非署名、采集站、垃圾站或者纯粹为了流量的转载。谢谢合作!

  1. 你好,我自己添加了一个服务成功了。可是启动失败,提示1053错误。可能会是哪里的错误呢。。
    是不是执行程序做为服务的时候是有要求的。

    • @chy
      检查你的Application和AppDirectory路径值是否正确,下面以NGINX程序举个例子,reg文件内容应该形如下面这样,然后导入:
      Windows Registry Editor Version 5.00

      [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NGINX\Parameters]
      "Application"="E:\\nginx-0.8.16\\nginx.exe"
      "AppParameters"=""
      "AppDirectory"="E:\\nginx-0.8.16\\"
      如果已经导入了注册表,请选择开始,运行,输入regedit并确认以便于打开注册表编辑器,定位到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\你的服务名称\Parameters,检查路径和参数配置是否正确。
      如果问题依旧,建议打开控制面板,“管理工具”下面的“事件查看器”,选择旁边的“系统项目”,选择类型为错误的日志,看看具体内容是什么。

  2. 谢谢。还是1053错误,系统错误日志提示:服务没有及时响应启动服务和控制请求。
    是不是03系统对要做为系统服务的执行程序有什么要求呢。
    是不是利用instsrv工具的时候,执行程序只能是单独的一个执行程序,不能有动态库文件其他东西呢。。

    • @chy
      您好,貌似instsrv只能将服务程序(*.EXE)安装为服务,普通EXE程序,动态链接库等无法单独安装为服务,对于普通程序,建议采用本文所述利用instsrv将srvany.exe安装为服务,然后通过配置参数加载普通EXE程序作为服务运行,对于DLL,请参考svchost的做法进行加载,或者你可以写个简单的EXE服务程序,然后静态链接或者动态调用(LoadLibrary)这个DLL,然后再通过instsrv安装这个能加载DLL的简单EXE服务程序。

  3. 非常感谢您耐心的指导。
    还想问您一下,您说的“配置参数加载普通EXE程序作为服务运行”具体怎么理解呢。
    一个软件包含了可执行程序,dll文件,为了主执行程序作为系统服务运行,其他执行程序和dll文件都需要不同的操作吗。
    呵呵,我是个刚接触系统管理的小白,问的不对的地方请您见谅。

    • @chy
      通过配置参数主要是配置的srvany.exe参数,当我们把srvany.exe作为服务安装的时候,我们还要告诉srvany.exe要加载的EXE的路径等参数信息,这样这个EXE才能以“服务”的形式存在,具体的做法是修改注册表相关项,这点可以参考本篇文章,如果说单纯谈一个软件包,里面有一个调用的EXE和一堆DLL链接库,我们只需要加载EXE就可以了,那些DLL动态库是为EXE提供必要函数指令的,也就是说EXE主程序需要它们时才会加载它们,这个是这个EXE主程序的事情,我们只需要将EXE主程序作为服务运行即可,如果该EXE是服务程序,可以直接安装为系统服务,然后再启动,如果该EXE程序是普通程序,那么就不能直接作为服务程序启动,请利用本篇文章所述的srvany.exe加载的办法进行相关操作,你可以下载一个叫Dependency Walker的程序,然后利用这个程序打开你的软件包中的EXE,如果该程序没有经过加壳压缩(比如UPX等加壳程序),你应该就会发现其静态所需要加载的DLL了,当然程序内部通过LoadLibrary方式动态加载的DLL可能需要其他手段,比如反编译等才能追踪到。关于应用程序EXE和动态链接库的关系,可以参考《Windows核心编程》的动态链接库部分。没关系,有什么疑问,欢迎提出:-)

  4. 您好。你说的“服务程序”是不是指windows系统自带的执行程序。“普通程序”是自己开发的程序呢。如果是这样,我我们的普通程序能不能修改为服务程序呢。
    我要做的这个服务就是我同事自己开发的程序,我利用srvany.exe添加了服务,注册表也修改了,可是就是启动服务到一半的时候就会报1053的错误。
    真的很头大。%>_

    • @chy
      不是这样的,服务程序是指遵循微软的服务程序开发规范开发出来的特殊程序,这类程序和普通程序相比最大的特点是可以被系统作为服务启动,服务程序和普通程序都可以是自己开发的程序,普通程序不能直接作为服务程序启动,否则服务启动会报错,所以srvany.exe就是为解决这个问题而诞生的,srvany.exe本身是作为服务程序而开发的,其是遵循服务程序开发规范的,所以可以被系统作为服务程序启动,然后srvany.exe会根据注册表的配置参数启动你所设定的普通程序,所以进程列表会有两个一个是srvany.exe另一个是你的普通EXE程序,注意它们都是以SYSTEM账户启动的,如果srvany.exe服务被停止,那么相应的普通程序也会被srvany.exe停止,这样就将普通程序模拟出服务程序的功能了。你同事的那个程序是不是包含窗体界面,如果是这样的话,开始,运行,输入services.msc,打开服务管理器,找到你设置的那个服务项,右击属性,切换到“登录”选项卡,然后勾选“允许服务与桌面交互”试试,不过一般情况下不建议将有窗体的程序作为服务程序运行,这样会有一些问题。关于服务程序的介绍和开发示例可以参考《Using Services》《The Complete Service Sample》或者《用 C++ 创建简单的 Win32 服务程序》

  5. 您好。
    我现在可以把程序添加到服务,但是无法启动,是不是可以说是srvany.exe没有发挥作用的问题呢。

    • @chy
      首先这个程序必须是能够持续运行的程序,如果是那种一运行很快就结束的程序,那么使用srvany.exe就没有效果了,因为srvany.exe启动了这个程序,而这个程序却很快就运行结束自动退出了,那么你在进程中将看不到你所希望运行的程序,只看到srvany.exe进程,因为它已经运行结束了,对于持续性程序,就是你不点关闭、不中止进程程序就不会退出的那种,在srvany.exe启动这类程序时,进程列表中将有你要启动的程序名和srvany.exe这两项,这时如果你停止服务,这两个进程将自动结束。
      我们知道系统自带的notepad.exe和nslookup.exe都是那种持续性程序,你不点关闭它们将不会退出,这两个程序一个是窗体程序、一个是控制台程序,将instsrv.exe和srvany.exe拷贝到SYSTEM32文件夹中,下面我用这两个程序做了实验:
      1.notepad.exe
      instsrv sample1 C:\Windows\System32\srvany.exe
      将下面导入注册表:
      Windows Registry Editor Version 5.00

      [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\sample1\Parameters]
      "Application"="C:\\WINDOWS\\SYSTEM32\\notepad.exe"
      "AppDirectory"="C:\\WINDOWS\\SYSTEM32\\"
      "AppParameters"=""
      然后启动服务sample1,观察任务管理器进程列表,出现srvany.exe和notepad.exe两个SYSTEM账户运行的进程,停止sample1服务后,两个进程消失,证明窗体类程序可以正常挂到srvany.exe下作为服务运行。
      2.nslookup.exe
      instsrv sample2 C:\Windows\System32\srvany.exe
      将下面导入注册表:
      Windows Registry Editor Version 5.00

      [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\sample2\Parameters]
      "Application"="C:\\WINDOWS\\SYSTEM32\\nslookup.exe"
      "AppDirectory"="C:\\WINDOWS\\SYSTEM32\\"
      "AppParameters"=""
      同上操作,证明控制台程序也是可以被srvany.exe作为服务启动的。
      对于持续性程序,可以通过 输入等待getchar()、死循环、互斥、消息循环等方式实现。

  6. 始终出现:本地计算机上的XX服务启动后又停止了。一些服务自动停止,
    如果它们没有什么可做的,例如“性能日志和警报”服务

    • @枯燥洒徒哈达
      不知道你那个是不是因为程序是那种一闪而过的,自动结束的程序。看上面那条回复:
      “首先这个程序必须是能够持续运行的程序,如果是那种一运行很快就结束的程序,那么使用srvany.exe就没有效果了,因为srvany.exe启动了这个程序,而这个程序却很快就运行结束自动退出了,那么你在进程中将看不到你所希望运行的程序,只看到srvany.exe进程,因为它已经运行结束了,对于持续性程序,就是你不点关闭、不中止进程程序就不会退出的那种,在srvany.exe启动这类程序时,进程列表中将有你要启动的程序名和srvany.exe这两项,这时如果你停止服务,这两个进程将自动结束。”
      希望对你能有所帮助:-)

  7. 你好,我想请问个问题,我想给Server 2003 或 2007 设置特定登陆用户显示窗体程序 ,比如系统登陆用户默认管理员是 Administrator 我设置了一个 sample1,我登陆sample1的时候才开启 服务中已设置好的窗体程序。

    • 暂时没能找到如何针对不同的用户启动不同服务的解决方案,不过可以将要启动的程序存放到用户的个性化启动文件夹中,比如Windows 7下是:
      C:\Users\<用户名>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
      Windows XP下路径是:
      C:\Documents and Settings\<用户名>\「开始」菜单\程序\启动
      假如说你需要运行的是服务程序,可以先将服务程序设置为手动启动,然后在上述用户启动文件夹中编写如下批处理文件(另存为*.bat):

      net start 服务名称

      这样不同的用户启动计算机就会自动执行其启动目录下的程序了,如果正好是启动服务的批处理,那么这个手动的服务也会被启动了。

    • 假如程序本身就是那种一运行就自动结束的话,则无法作为服务运行的,服务程序要求的就是持续驻留内存,如果程序运行完就自动结束则没有必要设为服务,你可以将其加入系统自动启动项内来实现开机启动等功能。
      典型的只要不手动关闭就持续运行的程序也有不少比如notepad.exe和nslookup.exe,你运行这些程序后,如果不输入退出命令或者点击右上角叉的话程序是不会自动结束的,所以这类程序更适合于被srvany.exe控制;假如是类似CScript.exe(不运行脚本)或者ipconfig.exe这类运行完就结束的程序,你可以在\Windows\System32路径下找到,并双击运行,结果是一闪而过的,说明其执行完任务就自动退出了,这样srvany.exe就无法控制了,因为srvany启动这类程序的时候,它们可能已经在完成任务后自我结束了运行。
      从编程的方法解决可以给你几个思路:
      1、参考Windows 服务编程约定将应用程序改造成服务程序(如果这样实现的话,那么恭喜你,就不需要srvany.exe辅助了);
      2、在程序退出前使用死循环轮回执行任务(不推荐,可能有性能问题,一定要实现的话,可以加入sleep防止过高占用CPU);
      3、命令控制台程序可以使用类似getchar()这类等待输入的函数,将程序挂起(不推荐,因为执行到getchar()挂起程序这里,程序实际功能已经结束了,所以虽然持续运行着,但已经没有实际作用了);
      4、使用隐藏窗体,配合消息循环实现(这个可以考虑,虽然服务程序不应该用窗体编程的方式,但是要Hold住程序保持不退出,必须采取循环的方式)。
      暂时就想到这么多,仅供参考吧,本文前面的评论内容也可以看看,希望对你有所帮助:-)

    • 一般情况下,我目前认为的两种适合作为服务的类型:一是定时处理某个任务,比如自动检查并更新的程序或者自动检查许可证是否有效的程序;二是监听请求,接受请求,处理请求这一类程序,比如远程受控服务端,基本上套接字(Socket)网络C/S应用的比较多。
      总结一下第一类是主动类型的服务程序,第二类属于被动类型的服务程序。我觉得你的情况适用于第二类被动接受请求,处理请求的服务程序。可以做成网络服务端程序,然后监听远程(或者本地)客户端的对资源(数据库)操作的请求,接受到此类请求后,然后服务程序按照一定的协议操作资源并反馈结果,简单如下:
      server --listen-- 服务器监听
      client --request-- 客户端请求
      server --accept-- 服务端收到请求并建立会话(此处可以加上身份验证)
      server do something 服务端根据客户请求处理资源
      server --return result-- 服务端返回处理结果
      client --accept-- 客户端收到结果并进一步处理

      上述一系列操作可以封装到类似死循环的逻辑里再作为服务程序,这样服务程序就不会只接受一次请求而终止了,而是一直永远的接受来自客户端的请求,这样有效的服务程序算是成型了。
      当然如果客户端仅仅是本地程序的话,可以不拘泥于网络套接字编程方式,比如进程间会话、管道通信什么的也是可以考虑的,说到底就是个C/S架构的东东,和普通的C/S数据库(MySQL、SQL Server)一样,只不过我们为了额外做一些事情(比如访问控制、事务控制)而自己用服务程序方式新建立了个服务端,然后客户端与新建立的服务端通讯,然后由新服务端将数据处理后按要求再与数据库服务程序通信:client – server – database,这样server服务程序就代理了数据库的相关操作。
      可能啰嗦了点,仅供参考吧。

  8. 你好,最近在使用srvany.exe和instsrv.exe注册为服务,碰到一个问题。我将一个普通exe启动文件注册成了服务,开机能够自动启动,但是srvany.exe的默认启动路径为C:\winodws\system32,这样导致exe启动,但是不能正确加载,exe的路径是在D:\soft\bin目录下,不知该如何修改?

    • 检查一下注册表AppDirectory信息是否设置为D:\soft\bin。建议使用SrvanyUI配置由srvany.exe创建的自定义服务(初次使用请删除原来手动建立的srvany.exe服务项目,然后用本工具重新创建)。

      • 好像用这个UI工具的确就可以了,instsrv.exe没有作用么,之前我是借鉴了别人一个bat脚本来生成服务的,我现在也是想用脚本的方式来完成服务的注册,想集成到一个安装包中,不知高手是否方便告知一下QQ,方便我请教,在此先谢过

        • 抱歉,我在单位不方便使用QQ,你也可以使用邮箱与我联系。
          你用instsrv安装完srvany.exe后还需要对srvany进行注册表配置,具体请参考文章所述。
          不太清楚你是如何编写配置安装脚本的,如果你是使用NSIS进行安装脚本配置的话,首先通过ExecWait执行instsrv命令将srvany.exe安装为系统服务,然后参考下面的脚本实现配置部分:

          WriteRegStr HKEY_LOCAL_MACHINE "SYSTEMCurrentControlSetServices服务名称Parameters" "Application" "$INSTDIR你的程序.exe"
          WriteRegStr HKEY_LOCAL_MACHINE "SYSTEMCurrentControlSetServices服务名称Parameters" "AppDirectory" "$INSTDIR"
          WriteRegStr HKEY_LOCAL_MACHINE "SYSTEMCurrentControlSetServices服务名称Parameters" "AppParameters" ""

          特别需要注意的是注册表AppDirectory的配置,这个是你程序所在的目录。
          如果你的软件是面向大众的话,建议将srvany.exe与你的程序放在一起(同一个文件夹),避免不必要的麻烦。
          如果你需要独立脚本完成这项任务的话,下午如果有时间我会提供一个,敬请关注。

  9. 高手你好,又发现一个问题,特来请教
    当用Srvany.exe成功注册成服务并启动时,进程管理器中会出现3个进程,一个是Srvany.exe,一个是cmd.exe,一个就是注册为服务的exe,那这个cmd.exe是在运行什么,我结束它似乎也没有对服务产生影响,如果这个进程不起任何作用,那是否能在注册时就不开启这个进程呢?

    • 我猜测那个cmd.exe是你调用的命令行安装并启动srvany.exe自定义服务的程序,cmd.exe一般是随着命令行启动而出现的,至于你那个cmd.exe为什么不消失,我认为是通过cmd安装并启动srvany.exe的服务时需要一个过程,特别是在启动一个服务时,这时调用命令需要不停的查询服务状态,这也就是为什么cmd.exe进程会驻留内存中,一旦服务完全启动,cmd.exe自然会退出,因为其使命已经完成。
      你可以观察一下这三个进程出现时,是不是过一段时间cmd.exe会自动退出。

      • 我观察了下,cmd不会自动退出,一直存在,并且好像是保持静止状态,并且我用你的UISrvany工具也会出现这个进程,怎样能够让这个进程自动结束呢?

        • 我的SrvanyUI工具创建的基于srvany.exe的自定义服务是不会产生额外的cmd.exe进程的,我怀疑可能是你需要建成服务的程序自己创建的,你可以试着创建其他程序的基于srvany.exe的自定义服务,比如说记事本程序notepad.exe或者nslookup.exe,再观察是否会有cmd.exe,如果没有,则说明可能这个进程是你那个作为服务运行的程序自己产生的。

  10. 您好!照你的方法,我的bat文件也可以做成服务。有个问题请教,服务启停本质上是不是打开/关闭srvany.exe进程?
    如果我想通过服务直接启停bat文件,该如何做呢?
    请赐教,谢谢。

      • 感谢回复。
        我做了测试,我的bat脚本调用了python。停止服务可以停止srvany.exe进程,但是对调用的python“无能为力”。

        • 恩,你停止了srvany.exe的服务的话,srvany.exe和cmd.exe进程应该会停止,但是bat调用的Python将不会停止,如果bat仅仅是调用Python来处理脚本的话,建议直接写到srvany服务调用中去,附加参数以服务参数的形式给出。

          • 大神你好,我也是遇到了这个问题,srvany.exe安装的服务中调了一个bat,bat中调了一个exe,还有一个exe的参数,停止服务的时候,bat中调用的exe并没有关掉,请问服务参数要怎么写呢

  11. 按以上方法成功了!但注销系统后应用程序就停止了,重新登录系统也不能重启。一点缺陷,请问有什么办法可以解决?多谢

        • 服务默认是不显示窗体的,如果将窗体程序作为服务运行,将不符合操作系统服务的初衷,不推荐这样的做法,如果要强制显示窗体,请看原文“2012年2月27日更新”和“2012年7月23日更新”部分;其中部分摘录:控制面板 – 管理工具 – 服务(或者 开始 – 运行 – services.msc 确认)打开服务管理器,选择你刚刚安装并需要展示窗体的服务,然后右击选择属性,切换到 “登录” 选项卡,勾选上 “允许服务与桌面交互” 然后按确定保存,重启你的服务,看看窗体是否出现了。

请稍后...

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*