我的当前项目涉及部署一个作为Windows服务运行的升级版.exe文件。为了用新版本覆盖现有的.exe文件,我目前需要执行以下步骤:
- 停止服务
- 卸载服务
- 重新启动系统(这样Windows才会释放对该文件的控制)
- 部署新的.exe文件
- 重新安装服务
- 启动升级后的服务。
我想避免重启,以便进行完全脚本化/自动化的升级。
有没有办法避免重启?也许有一种命令行工具可以强制Windows放弃对旧的.exe文件的控制吗?
我的当前项目涉及部署一个作为Windows服务运行的升级版.exe文件。为了用新版本覆盖现有的.exe文件,我目前需要执行以下步骤:
我想避免重启,以便进行完全脚本化/自动化的升级。
有没有办法避免重启?也许有一种命令行工具可以强制Windows放弃对旧的.exe文件的控制吗?
sc delete "service name"
将会删除一个服务。我发现比起寻找installutil,sc实用工具更易于定位。记得先停止该服务,如果你还没有这么做。
sc delete
命令在卸载服务时并不能停止正在运行的服务,而是标记该服务待删除,这也符合其文档所描述的。请参考链接:https://dev59.com/63HYa4cB1Zd3GeqPM44n#16293612。 - J0e3gan我遇到了与你类似的问题。我有一个系统服务,想要在更新时将其卸载并重新安装。但在某些系统上,如果不重启可能无法正常工作。问题在于DeleteService()的调用会返回ok,但CreateService()的后续调用会告诉我该服务仍然存在,但已标记为删除(错误代码1072)。注册表也会反映这一点,因为子键仍然存在(位于HKLM\System\CurrentControlSet\Services下),但“DeleteFlag”设置为1。从那时起,只有重启才能解决这个问题。
以下是一些无效的尝试:
但以下方法有效:
我在stackoverflow上看到一些文章提到net.exe也有启动/停止功能(我只知道sc.exe实用程序)。奇怪的是,“net stop svcname”加上“sc delete svcname”起作用了!所以net.exe一定做了我没做的事情。
但是,net.exe不包含ControlService()的导入,那么它如何停止该服务呢?我发现,net.exe会生成net1.exe,但net1.exe也没有导入ControlService()。我使用了一个很棒的API Monitor实用程序(http://www.rohitab.com/apimonitor)来查看net1.exe正在做什么,但它从未调用过任何看起来有希望的东西。
但是我发现它从NETAPI32.DLL中导入了NetServiceControl()函数(它的名称中至少包含“Service”)。MSDN表示该函数已经过时。尽管如此,我在LMSvc.h中找到了原型,并在此处找到了一些参数描述:http://cyberkinetica.homeunix.net/os2tk45/srvfpgr/369_L2_NetServiceControlorN.html。当您加载NETAPI32.DLL并使用NetServiceControl(NULL, service_name, 3, 0, 0)
(3表示SERVICE_CTRL_UNINSTALL,用于停止)之后,服务将被停止。然后可以删除并重新安装而无需DeleteFlag或重新启动!
所以这不是删除问题,而是正确停止服务的问题。 NetServiceControl()可以解决问题。抱歉发帖较长,但我认为它可能会对有类似问题的人有所帮助。(仅供参考,我使用的是Win7 SP1 x64。)
您是否无法使用以下命令在更新之前停止服务(并在更新后重新启动)?
net stop <service name>
net start <service name>
每当我测试/部署服务时,只要服务被停止,我就可以上传文件而无需重新安装。我不确定你遇到的问题是否不同。
如果在 .net 中(我不确定它是否适用于所有的windows服务)
除非我改变了服务的公共接口,否则我通常会升级我的服务版本而不需要卸载/重新安装...我所做的只是停止服务,替换文件,然后重新启动服务...
乔纳森和查尔斯都是正确的...您必须先停止服务,然后卸载/重新安装。将他们两个人的答案结合起来可以制作出完美的批处理文件或PowerShell脚本。
我要提醒大家一个艰难的教训——Windows 2000 Server(可能也包括客户端操作系统)在重新安装之前无论如何都需要重新启动。这里必须有一个注册表键没有完全清除,直到重启后才能清除。Windows Server 2003、Windows XP及更高版本的操作系统不会遇到这种问题。
(所以Windows释放对文件的控制)
相反,在服务停止后立即按Ctrl+Alt+Del并终止服务的.exe。然后,您可以在无需重新启动计算机的情况下卸载该服务。我曾经遇到过这种情况,这解决了您需要重新启动计算机的部分。
如果需要手动删除服务:
在服务中更新列表之前,您需要重新启动计算机。
停止和删除服务的批处理文件
@echo off
title Service Uninstaller
color 0A
set blank=
set service=blank
:start
echo.&echo.&echo.
SET /P service=Enter the name of the service you want to uninstall:
IF "%service%"=="" (ECHO Nothing is entered
GoTo :start)
cls
echo.&echo.&echo We will delete the service: %service%
ping -n 5 -w 1 127.0.0.1>nul
::net stop %service%
ping -n 2 -w 1 127.0.0.1>nul
sc delete %service%
pause
:end
我正在使用.NET Framework附带的InstallUtil.exe。
卸载的用法是:InstallUtil '\path\to\assembly\with\the\installer\classes' /u,例如:installutil MyService.HostService.exe /u
/u
开关表示卸载,没有它,该工具将执行服务的正常安装。如果服务正在运行,则实用程序会停止该服务,我从未遇到过Windows锁定服务文件的问题。您可以在MSDN上阅读有关InstallUtil的其他选项。
P.S.:如果您的路径变量中没有installutil,请使用完整路径,例如:C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe "C:\MyServiceFolder\MyService.HostService.exe" /u
或者如果您需要64位版本,则可以在'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\'中找到它。路径中的版本号因.NET版本而异。