构建一个应用程序以在服务器上定期执行任务

发布于 2024-09-10 06:20:01 字数 476 浏览 5 评论 0原文

我正在寻找有关我正在构建的这个小系统的整体架构的一些指导。

目前,我有一个通过 xcopy 部署(和更新)到一些服务器的应用程序。这对于更新代码很有效,但对于更新代码的执行周期却不太有效,因为它被设置为 Windows 计划任务每​​小时运行一次。 xcopy 替换效果很好,因为我可以从本地计算机运行更新,并将新的 exe 文件推送到所有服务器。接下来的一个小时,任务计划程序将运行新的 exe。

我想改变它以这种方式工作。

我的应用程序作为 Windows 服务运行,并使用 System.Threading.Timer 等待给定的持续时间,然后执行代码。这样,过程的一部分可以检查数据库,并在必要时减少给定服务器的执行周期。

那里的问题是,由于 .exe 将作为服务运行,因此不允许通过 xcopy 轻松更新,因为该文件将一直在使用中。

关于我应该如何设置它以便能够在作为 Windows 服务运行时进行简单的 xcopy 更新有什么想法吗?这可能吗?

I'm looking for some guidance on the overall architecture of this little system I'm building.

Currently, I have an app that is deployed (and updated) via xcopy to a few servers. This works well for updating the code, but it does not work well for updating the period of the code's execution, since it is setup as a windows scheduled task to run every hour. The xcopy replace works well, because I can run an update from my local machine, and push the new exe file to all the servers. And the next hour, the task scheduler will run the new exe.

I'd like to change it to work this way.

My app runs as a Windows Service and uses System.Threading.Timer to wait a given duration, and then execute the code. This way, part of the process could check the database and if necessary reduce the period of execution for a given server.

The issue there, is that since the .exe would be running as a service, it would not allow for easy updaing via xcopy since the file will be in use all the time.

Any thoughts on how I should set this up to be able to do easy xcopy updates, while running as a windows service? Is that even possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

苍暮颜 2024-09-17 06:20:01

您可以停止服务,然后复制文件,然后从批处理文件启动服务:

SET SOURCEDIR=\\coastappsdev\wwwroot\ClearTrac\Setup\03_Staging\ClearTracAutoSend\bin
SET SERVICE_HOME=C:\INETPUB\WWWROOT\ClearTracAutoSend
SET SERVICE_EXE=ClearTracAutoSend.exe
SET INSTALL_UTIL_HOME=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727


:STOP THE SERVICE:
SC \\targetServer STOP ClearTracAutoSend

:COPY THE FILES:
MD %SERVICE_HOME%
XCOPY %SOURCEDIR%\*.* %SERVICE_HOME%\*.* /E /R /Y

set PATH=%PATH%;%INSTALL_UTIL_HOME%

cd %SERVICE_HOME%

echo Uninstalling AutoSend Service...
installutil /u %SERVICE_EXE%

cd %SERVICE_HOME%

echo installing AutoSend Service...
installutil /i %SERVICE_EXE%

:START THE SERVICE:
SC \\targetServer ClearTracAutoSend

pause

这可能不是远程的最佳解决方案,我不知道如何远程运行 installutil。我们通过 RDP 连接到服务器并运行批处理文件。

You can stop the service, then copy the files, then start the service from a batch file:

SET SOURCEDIR=\\coastappsdev\wwwroot\ClearTrac\Setup\03_Staging\ClearTracAutoSend\bin
SET SERVICE_HOME=C:\INETPUB\WWWROOT\ClearTracAutoSend
SET SERVICE_EXE=ClearTracAutoSend.exe
SET INSTALL_UTIL_HOME=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727


:STOP THE SERVICE:
SC \\targetServer STOP ClearTracAutoSend

:COPY THE FILES:
MD %SERVICE_HOME%
XCOPY %SOURCEDIR%\*.* %SERVICE_HOME%\*.* /E /R /Y

set PATH=%PATH%;%INSTALL_UTIL_HOME%

cd %SERVICE_HOME%

echo Uninstalling AutoSend Service...
installutil /u %SERVICE_EXE%

cd %SERVICE_HOME%

echo installing AutoSend Service...
installutil /i %SERVICE_EXE%

:START THE SERVICE:
SC \\targetServer ClearTracAutoSend

pause

This might not be the best solution for remote, I don't know how to run installutil remotely. We RDP to the server and run the batch file.

放飞的风筝 2024-09-17 06:20:01

如何将更新代码从仅检查下一次迭代时间的服务移出到它自己的程序集中。在每次运行之前动态加载它,然后卸载它。我还想知道 Quartz.net 对您是否有用。

How about moving the updating code out of the service that simply checks the time for the next iteration into it's own assembly. Load that dynamically before each run and then unload it. I'm also wondering if Quartz.net is useful for you.

梦醒时光 2024-09-17 06:20:01

您可以让您的服务生成一个子进程(exe)并等待其退出。

这样您的应用程序就可以轻松更新,因为它会被加载、运行然后退出,并且只要您不需要更新您的服务,一切都很容易。

如果想要更棘手,您可以将其设置为程序集(dll),即通过将 dll 加载到内存然后执行它来加载内存,或者您可以设置它运行的 ShadowCopy 目录。

You could just have your Service Spawn a sub process(exe) and wait for that to exit.

This way your application could be updated easily because it is loaded, runs and then exits, and as long as you don't need to update your service it's all easy.

If want to be more tricky, you could set it up as an assembly(dll), that is either memory loaded via loading the dll into memory and then executing it, or you could setup a ShadowCopy directory that it runs from.

木有鱼丸 2024-09-17 06:20:01

如果您愿意停止服务、推送代码和启动服务,您有几种选择。

最好的是 Powershell 或 MsBuild。

如果您担心时间,只需将服务设置为在启动时运行一次(或 startTime + 某个时间间隔),然后每小时运行一次。

如果您确实需要此服务保持运行但能够在运行之间更改代码,那么您将需要一些 托管扩展性框架(MEF)允许将 DLL 代码存储在某处并仅在运行时加载,因此无需重新启动即可对其进行修改。

If you are open to stopping the service, pushing the code, and starting the service, you have a few options.

The best would be Powershell or MsBuild.

If you are concerned about timing, just set the service to run once when its started (or startTime + some interval) and then every hour.

If you really need this service to just stay running but be able to change the code between runs, you'll need something some the Managed Extensibility Framework (MEF) which allows the DLL code to be stored somewhere and loaded only during runtime, so it can be modified without a restart.

霞映澄塘 2024-09-17 06:20:01

我最终使用了一些 @Decker97 的解决方案,再加上一些 powershell 魔法:)

function global:new-process()
{
    param ([string]$computer, [string]$commandline=$(throw "Command line required."))

    $path = "\\$computer\root\cimv2:Win32_Process"
    $mc = new-object System.Management.ManagementClass $path

    $cmdargs = $commandline,$null,$null,0

    $ret = $mc.InvokeMethod("Create", $cmdargs)
    if ($ret -eq 0) {
        write-host "Created Process ID: $($cmdargs[3])"
    }
    else {
        write-host "Error $ret creating process."
    }

    $mc.Dispose()
}

$serverNames = Get-Content C:\temp\servers.txt

foreach ($server in $serverNames) 
{   
    write-host Updating $server

    c:\windows\system32\sc.exe \\$server STOP Service

    $source = "C:\Projects\Service\bin\Debug"
    $dest = "\\" + $server + "\C$\Program Files\TargetFolder\TargetFolder"
    ROBOCOPY.exe $source $dest /MIR /W:5 /R:1

    new-process $server 'c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Installutil.exe /i  /LogFile=install.out "C:\Program Files\TargetFolder\TargetFolder\serviceExecutable.exe"'

    c:\windows\system32\sc.exe  \\$server START Service
}

该脚本使用服务控制来尝试停止服务。

然后它使用 robocopy 将文件复制到服务器。

然后使用 WMI 和 Powershell 在服务器上远程调用“installutil”。

然后使用服务控制来启动服务。

I ended up using a bit of @Decker97's solution, coupled with some powershell magic :)

function global:new-process()
{
    param ([string]$computer, [string]$commandline=$(throw "Command line required."))

    $path = "\\$computer\root\cimv2:Win32_Process"
    $mc = new-object System.Management.ManagementClass $path

    $cmdargs = $commandline,$null,$null,0

    $ret = $mc.InvokeMethod("Create", $cmdargs)
    if ($ret -eq 0) {
        write-host "Created Process ID: $($cmdargs[3])"
    }
    else {
        write-host "Error $ret creating process."
    }

    $mc.Dispose()
}

$serverNames = Get-Content C:\temp\servers.txt

foreach ($server in $serverNames) 
{   
    write-host Updating $server

    c:\windows\system32\sc.exe \\$server STOP Service

    $source = "C:\Projects\Service\bin\Debug"
    $dest = "\\" + $server + "\C$\Program Files\TargetFolder\TargetFolder"
    ROBOCOPY.exe $source $dest /MIR /W:5 /R:1

    new-process $server 'c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Installutil.exe /i  /LogFile=install.out "C:\Program Files\TargetFolder\TargetFolder\serviceExecutable.exe"'

    c:\windows\system32\sc.exe  \\$server START Service
}

The script uses service control to try to stop the service.

Then it copies the files to the server with robocopy.

Then use WMI and Powershell to invoke "installutil" remotly on the server.

Then use service control to start up the service.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文