如何进行 Windows 服务自我更新?
Posted
技术标签:
【中文标题】如何进行 Windows 服务自我更新?【英文标题】:how to have a windows service self update? 【发布时间】:2020-09-05 04:44:15 【问题描述】:我能找到的关于这个主题的所有解决方案都非常古老,而且似乎都没有回答我的问题......
我正在尝试创建一个可以自我更新(或通过某些外部触发器自动更新)的 Windows 服务。过去,我创建了一个与 InstallShield 一起安装的 Windows 服务,我们能够通过让服务将批处理脚本写入本地计算机然后运行批处理脚本以一种 hacky 方式更新自动更新服务,这将停止服务,用新文件覆盖服务可执行文件和其他文件,然后重新启动服务。这出人意料地奏效了。
但是,我已将服务更新为使用 InstallUtil.exe,并且此自动更新脚本不再起作用...我认为这与 InstallShield 处理服务安装的方式与 InstallUtil 的处理方式有关...但我只能猜测,因为我不完全了解每个人对注册表的作用。
由于我不能只覆盖文件并使用 InstallUtil 方法重新启动服务,我想我会编写一个运行 sc.exe 的批处理脚本来停止服务,完全卸载它,编写新文件,安装新的服务文件,然后启动它......不幸的是,我似乎无法让 sc.exe 从 Windows 服务自动运行,因为它需要管理员权限......我试图强制它自我提升为管理员使用这个 sn-p,但它似乎不能作为服务工作(如果我从命令行运行它而不是作为服务,它工作正常)
if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b)
有谁知道我如何使 Windows 服务自我更新?如果.NET Core中有一些我不知道的自我更新方法,我可以考虑更新到.NET Core Worker服务......任何想法都非常感谢......它真的不应该这么难完成...
作为参考,这是我目前使用的批处理脚本(忽略奇怪的变量,例如我正在动态替换其中一些,手动启动时效果很好,只是在服务尝试运行时不起作用) :
@echo off
setlocal enableextensions enabledelayedexpansion
::make sure to run whole script as admin (this restarts scripts as admin if not already in admin mode)
if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b)
pushd %networkDirectory%
::stop running service
for /F "tokens=3 delims=: " %%H in ('sc query %serviceName% ^| findstr " STATE"') do (
if /I "%%H" NEQ "STOPPED" (
net stop %serviceName%
if errorlevel 1 goto :stop
)
::delete existing service after stopping
sc delete %serviceName%
)
:: install updated service files
set "releaseDir=%networkDirectory%\Release"
set "programFilesCopyDir=%ProgramFiles%\_companyDirectory\%serviceName%\Release"
:: copy service Release dir to local system program files
xcopy "%releaseDir%" "%programFilesCopyDir%" /S /Y /Q
::execute the install
pushd "%programFilesCopyDir%"
CALL %serviceName%.exe --install
::start service
sc start %serviceName%
【问题讨论】:
这能回答你的问题吗? Best practice for writing a self-updating windows service 和 I want my C# Windows Service to automatically update itself 我有一点咨询和系统管理员经验:您是否 100% 肯定,您需要自动更新并且您可以这样做不会给生产系统带来问题吗?作为系统管理员,我会尽我所能阻止安装自动更新服务。 @Fildor,从技术上讲,它不会自动更新......我们只会在审核后推送更新,但它确实需要自我更新,因为该服务在 50 多台不同的机器上运行当我们有更新时手动更新它们是一个 PITA @eerick 你可以尝试使用 MSI/WIX,this 线程作为起点。 Clickonce也有这样的可能,看here。最后你可以试试 AutoUpdater.NET FWIW 我已经写了一个自我更新服务;它通过在应用程序域中运行真实代码来工作 - 它可以将较新的版本下拉到一个侧目录中,启动一个新的应用程序域,然后切换到那个(释放旧的),我从中学到的主要内容这是:不要这样做 - 只是更好地了解如何更新服务。有很多用于自动协调服务器更新的工具,包括服务。使用它们。也许是“木偶”。 【参考方案1】:对于其他试图完成此任务但偶然发现此问题的人...我最终找到了解决方案。我使用上面问题中发布的相同脚本,但我编写了代码来使用 Windows 任务计划程序设置计划任务。计划任务将上述脚本作为一次性计划任务运行。这就像一个魅力。
我使用这个 NuGet 包来编写我需要的任务计划程序代码: https://www.nuget.org/packages/TaskScheduler/2.8.20?_src=template
【讨论】:
以上是关于如何进行 Windows 服务自我更新?的主要内容,如果未能解决你的问题,请参考以下文章
用优化大师检测到系统漏洞:补丁名称KB950582,补丁描述WINDOES XP更新程序。
如何为 Windows 7 编写进度条以在任务栏上进行自我更新?