如何让Windows服务自我更新?

eer*_*ick 6 c# windows-services batch-file auto-update

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

我正在尝试创建一个可以自我更新(或通过某些外部触发器自动更新)的 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)
Run Code Online (Sandbox Code Playgroud)

有谁知道如何让 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%
Run Code Online (Sandbox Code Playgroud)

eer*_*ick 5

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

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