如何在不重新启动的情况下卸载 Windows 服务并删除其文件

Posted

技术标签:

【中文标题】如何在不重新启动的情况下卸载 Windows 服务并删除其文件【英文标题】:How to uninstall a windows service and delete its files without rebooting 【发布时间】:2010-09-22 21:53:08 【问题描述】:

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

    停止服务 卸载服务 重新启动系统(以便 Windows 释放它对文件的保留) 部署新的 .exe 重新安装服务 启动升级后的服务。

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

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

【问题讨论】:

感谢大家的帮助!我发现我的问题的根源是 WMI 对 .exe 的句柄。请参阅我的新问题:***.com/questions/302315/… 仅供参考,如果您打开了服务管理器,则需要在重新安装服务之前关闭,否则您将收到“服务已标记为删除”错误。 在my experience“[SC] CreateService FAILED 1072: 指定的服务已被标记为删除”取决于被卸载的服务是否没有先停止。我试图在服务管理工具打开的情况下重现该错误,但无法重现。 【参考方案1】:

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

@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

【讨论】:

【参考方案2】:

我正在使用 .NET Framework 打包的 InstallUtil.exe。

卸载的用法是:InstallUtil '\path\to\assembly\with\the\installer\classes' /u 例如:installutil MyService.HostService.exe /u

/u 开关代表卸载,没有它,util 将执行服务的正常安装。如果该实用程序正在运行,该实用程序将停止该服务,并且我从未遇到过 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版本而异。

【讨论】:

【参考方案3】:
sc delete "service name"

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

【讨论】:

sc 删除“服务名称” 是的......最终ms会像*nix一样转到“--”。一次一步 =) 在我的例子中,命令是 sc delete "serviceName" 注意你必须以管理员身份执行命令行 I have found sc delete 在卸载它时不会停止正在运行的服务,而是将其标记为删除,这也是其文档中描述的内容。【参考方案4】:

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

一些不起作用的东西:

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

但这是有效的:

我在 *** 上的一些文章中注意到 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()(它的名称中至少包含“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。)

【讨论】:

如何可靠地模拟“标记为删除”状态?我为模拟它所做的只是使用普通服务 API 打开服务的句柄。打开手柄,此方法不起作用。当手柄关闭时,服务自动消失。 谢谢!我正在寻找“net stop”和“sc stop”之间的区别 很好的分析!【参考方案5】:

是否需要手动删除服务:

    运行 Regedit 或 regedt32。 在以下键下找到您的服务的注册表键条目: HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services 删除注册表项

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

【讨论】:

【参考方案6】:

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

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

【讨论】:

+1 用于限定条件“(只要它停止)”。这与我的经验一致——尽管是在 Windows 7 上。【参考方案7】:

(因此 Windows 发布它保留在 文件)

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

【讨论】:

【参考方案8】:

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

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

【讨论】:

【参考方案9】:

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

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

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

【讨论】:

就我而言,由于某些权限问题,我无法这样做【参考方案10】:

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

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

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

【讨论】:

这一直是我的经验 - 我只是通过停止服务并替换 .EXE 来不断更新服务。反正这只是一个普通的过程。 这里一样 - 为我工作了几个月的一套 Windows 服务(在 Windows 7 上运行)的开发。

以上是关于如何在不重新启动的情况下卸载 Windows 服务并删除其文件的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在不重新启动服务器的情况下在远程 weblogic 上重新部署应用程序?

如何在不重新启动服务器的情况下停止 Jenkins 上不可阻挡的僵尸作业?

是否可以在不重新启动 JSF 中的服务器的情况下更新应用程序?

Gatsby + Contentful - 如何在不重新启动服务器的情况下在本地重做 GraphQL 查询(npm run dev)?

如何在不重新启动的情况下更新机器人状态中的“bot.users.size”

如何在不重新启动树莓派本身的情况下重新启动 ALSA?