我当前的项目涉及部署作为 Windows 服务运行的升级的 .exe 文件。为了用新版本覆盖现有的 .exe,我目前需要:
- 停止服务
- 卸载服务
- 重新启动系统(因此 Windows 释放它对文件的保留)
- 部署新的 .exe
- 重新安装服务
- 启动升级服务。
我想避免重新启动,以便这可以是完全脚本化/自动升级。
有什么办法可以避免重启?也许是一个命令行工具会迫使 Windows 放弃它对旧 .exe 的死控制?
我当前的项目涉及部署作为 Windows 服务运行的升级的 .exe 文件。为了用新版本覆盖现有的 .exe,我目前需要:
我想避免重新启动,以便这可以是完全脚本化/自动升级。
有什么办法可以避免重启?也许是一个命令行工具会迫使 Windows 放弃它对旧 .exe 的死控制?
sc delete "service name"
将删除服务。我发现sc 实用程序比寻找 installutil 更容易找到。如果您还没有停止服务,请记住停止服务。
我遇到了和你一样的问题。我有一个系统服务,我想卸载它,然后作为更新的一部分重新安装。在某些系统上,如果不重新启动,这将无法工作。问题是对 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()(它的名称中至少有“服务”!)。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 服务)
除非我更改服务的公共接口,否则我经常部署我的服务的升级版本,甚至没有卸载/重新安装......我所做的就是停止服务,替换文件并再次重新启动服务......
正如 StingyJack 和 mcbala 所指出的,并参考 Mike L 的评论,我的经验是,在 Windows 2000 机器上,当卸载/重新安装 .Net 服务时,“installutil /u”确实需要重新启动,即使该服务是之前停了。另一方面,“sc /delete”不需要重新启动 - 它会立即删除服务(只要它停止)。
实际上,我经常想知道“installutil / u”是否有充分的理由需要重新启动......“sc / delete”实际上是在做错什么/让某些东西挂起吗?
乔纳森和查尔斯都是对的……你必须先停止服务,然后卸载/重新安装。将他们的两个答案结合起来可以制作完美的批处理文件或 PowerShell 脚本。
我将提到一个通过艰难的方式学到的警告——Windows 2000 Server(也可能是客户端操作系统)无论如何都需要在重新安装之前重新启动。必须有一个注册表项在重新启动框之前未完全清除。Windows Server 2003、Windows XP 和更高版本的操作系统不会遭受这种痛苦。
(所以 Windows 发布它保留在文件上)
相反,在服务停止后立即执行 Ctrl+Alt+Del 并终止服务的 .exe。比,您可以在不重新启动的情况下卸载该服务。这过去发生在我身上,它解决了您需要重新启动的部分。
如果需要手动删除服务:
在服务中更新列表之前,您必须重新启动
我正在使用与 .NET Framework 一起打包的 InstallUtil.exe。
卸载的用法是:InstallUtil '\path\to\assembly\with\the\installer\classes' /u 例如:installutil MyService.HostService.exe /u
该/u
开关代表卸载,没有它,实用程序将执行服务的正常安装。如果该实用程序正在运行,该实用程序将停止该服务,并且我从未遇到过 Windows 锁定服务文件的问题。您可以在MSDN上阅读有关 InstallUtil 的其他选项的信息。
PS:如果您的路径变量中没有 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 版本而异。
我的批处理文件停止和删除服务
@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