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

时间:2010-07-12 22:16:30

标签: .net process automation scheduling

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

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

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

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

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

在作为Windows服务运行时,有关如何设置此功能以便能够轻松进行xcopy更新的任何想法?这甚至可能吗?

5 个答案:

答案 0 :(得分:2)

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

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到服务器并运行批处理文件。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

你可以让你的Service Spawn成为一个子进程(exe)并等待它退出。

通过这种方式,您的应用程序可以轻松更新,因为它已加载,运行然后退出,只要您不需要更新服务,就可以轻松完成。

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

答案 3 :(得分:0)

如果您愿意停止服务,推送代码并启动服务,那么您有几个选择。

最好的是Powershell或MsBuild。

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

如果你真的需要这个服务才能保持运行但能够在运行之间更改代码,你需要一些Managed Extensibility Framework(MEF),它允许将DLL代码存储在某个地方并仅加载在运行时,所以可以在不重新启动的情况下对其进行修改。

答案 4 :(得分:0)

我最终使用了一些@ 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”。

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