如何进行Windows服务自我更新?



我能找到的关于这个主题的所有解决方案都非常古老,似乎没有一个能回答我的问题......

我正在尝试创建一个可以自我更新(或通过某些外部触发器自动更新(的 Windows 服务。 过去,我创建了一个与 InstallShield 一起安装的 Windows 服务,我们能够通过让服务将批处理脚本写入本地计算机然后运行批处理脚本来以黑客方式更新自动更新服务,这将停止服务,用新文件覆盖服务可执行文件和其他文件, ,然后重新启动服务。 这出人意料地奏效了。

但是,我已经更新了服务以使用 InstallUtil.exe并且此自动更新脚本不再有效...我认为这与 InstallShield 处理服务安装的方式与 InstallUtil 如何执行此操作有关......但我只能猜测,因为我不完全了解每个人对注册表做了什么。

由于我不能只覆盖文件并使用 InstallUtil 方法重新启动服务,我想我会编写一个运行 sc.exe 的批处理脚本来停止服务,完全卸载它,写入新文件,安装新的服务文件,然后启动它......不幸的是,我似乎无法让 sc.exe 自动从 Windows 服务运行,因为它需要管理员权限......我试图使用此代码段强制它自我提升为管理员,但它似乎不能作为服务工作(如果我从命令行而不是作为服务运行它,它可以正常工作(

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%

对于其他试图实现这一目标的人,偶然发现这一点......我最终找到了解决方案。 我使用上面问题中发布的相同脚本,但我编写了代码来使用 Windows 任务计划程序设置计划任务。 计划任务将上述脚本作为一次性计划任务运行。 这就像一个魅力。

我使用此 NuGet 包编写了我需要的任务计划程序代码: https://www.nuget.org/packages/TaskScheduler/2.8.20?_src=template

最新更新