46

我当前的项目涉及部署作为 Windows 服务运行的升级的 .exe 文件。为了用新版本覆盖现有的 .exe,我目前需要:

  1. 停止服务
  2. 卸载服务
  3. 重新启动系统(因此 Windows 释放它对文件的保留)
  4. 部署新的 .exe
  5. 重新安装服务
  6. 启动升级服务。

我想避免重新启动,以便这可以是完全脚本化/自动升级。

有什么办法可以避免重启?也许是一个命令行工具会迫使 Windows 放弃它对旧 .exe 的死控制?

4

10 回答 10

78
sc delete "service name"

将删除服务。我发现sc 实用程序比寻找 installutil 更容易找到。如果您还没有停止服务,请记住停止服务。

于 2008-11-19T13:47:39.387 回答
15

我遇到了和你一样的问题。我有一个系统服务,我想卸载它,然后作为更新的一部分重新安装。在某些系统上,如果不重新启动,这将无法工作。问题是对 DeleteService() 的调用会返回 ok,但对 CreateService() 的以下调用会告诉我该服务仍然存在,但标记为删除(错误代码 1072)。注册表会反映这一点,因为子项仍然存在(在 HKLM\System\CurrentControlSet\Services 下),但“DeleteFlag”设置为 1。从那时起,只有重新启动才能解决此问题。

一些不起作用的东西:

  • 使用“sc delete”:它和我有同样的问题。调用会返回正常,但服务并没有真正消失,仍然在注册表中,DeleteFlag = 1。
  • 删除注册表中的键。服务管理器似乎在内存中保留了一个数据库,而注册表只是它的一个副本,用于下次启动。
  • 添加等待循环、等待 .exe 文件准备好被覆盖、终止进程等。
  • 关闭服务的句柄。哪个??

但这是有效的:

我在 stackoverflow 上的一些文章中注意到 net.exe 也具有启动/停止功能(我只知道 sc.exe 实用程序)。奇怪的是,“net stop svcname”加上“sc delete svcname”起作用了!所以 net.exe 必须做一些我不做的事情。

但是 net.exe 不包含对 ControlService() 的导入,那么它如何停止服务呢?我发现 net.exe 生成 net1.exe,但 net1.exe 也不导入 ControlService()。我使用了很棒的 AP​​I 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。)

于 2012-07-09T16:15:26.190 回答
14

您是否无法使用以下命令在更新之前停止服务(并在更新后重新启动)?

net stop <service name>
net start <service name>

每当我测试/部署服务时,只要服务停止,我就可以上传文件而无需重新安装。我不确定您遇到的问题是否有所不同。

于 2008-11-18T18:10:36.563 回答
3

如果在 .net 中(我不确定它是否适用于所有 Windows 服务)

  • 停止服务(这可能是您遇到问题的原因。)
  • InstallUtil -u [可执行文件的名称]
  • Installutil -i [可执行文件的名称]
  • 再次启动服务...

除非我更改服务的公共接口,否则我经常部署我的服务的升级版本,甚至没有卸载/重新安装......我所做的就是停止服务,替换文件并再次重新启动服务......

于 2008-11-18T18:28:30.833 回答
3

正如 StingyJack 和 mcbala 所指出的,并参考 Mike L 的评论,我的经验是,在 Windows 2000 机器上,当卸载/重新安装 .Net 服务时,“installutil /u”确实需要重新启动,即使该服务是之前停了。另一方面,“sc /delete”不需要重新启动 - 它会立即删除服务(只要它停止)。

实际上,我经常想知道“installutil / u”是否有充分的理由需要重新启动......“sc / delete”实际上是在做错什么/让某些东西挂起吗?

于 2009-03-11T17:31:37.780 回答
2

乔纳森和查尔斯都是对的……你必须先停止服务,然后卸载/重新安装。将他们的两个答案结合起来可以制作完美的批处理文件或 PowerShell 脚本。

我将提到一个通过艰难的方式学到的警告——Windows 2000 Server(也可能是客户端操作系统)无论如何都需要在重新安装之前重新启动。必须有一个注册表项在重新启动框之前未完全清除。Windows Server 2003、Windows XP 和更高版本的操作系统不会遭受这种痛苦。

于 2008-11-18T18:41:19.950 回答
2

(所以 Windows 发布它保留在文件上)

相反,在服务停止后立即执行 Ctrl+Alt+Del 并终止服务的 .exe。比,您可以在不重新启动的情况下卸载该服务。这过去发生在我身上,它解决了您需要重新启动的部分。

于 2008-11-19T13:25:55.717 回答
2

如果需要手动删除服务:

  1. 运行 Regedit 或 regedt32。
  2. 在以下项下找到您的服务的注册表项:HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services
  3. 删除注册表项

在服务中更新列表之前,您必须重新启动

于 2010-09-22T15:46:37.060 回答
0

我正在使用与 .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 版本而异。

于 2014-04-17T06:48:29.580 回答
0

我的批处理文件停止和删除服务

@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
于 2020-01-09T17:52:53.847 回答