Stopping a service.

jochem4207jochem4207 Posts: 47
edited January 8, 2014 5:39AM in Deployment Manager
With predeploy and the code below i'm stopping a custom build service.
$service = Get-Service $ServiceName -ErrorAction SilentlyContinue 
$fullPath = Resolve-Path $ServiceExecutable 
if ($service) 
{ 
	Write-Host "The service will be stopped" 
	Stop-Service $ServiceName -Force 
	$svc = Get-Service $ServiceName
	$svc.WaitForStatus('Stopped')
}

The problem is that about 4 of the 7 releases it says:
2014-01-08 10:26:35 +01:00 ERROR  Unable to copy the package to the specified directory 'somedir/someplugin.exe'. One or more files in the directory may be locked by another process. You could use a PreDeploy.ps1 script to stop any processes that may be locking the file. Error details follow.

2014-01-08 10:26:35 +01:00 ERROR  Caused by:
2014-01-08 10:26:35 +01:00 ERROR  -The process cannot access the file 'Some dll in the service' because it is being used by another process.

On stackoverflow I got the tip of using windows tools to looking into what holds the file.
But that is not making me anything wiser atm.

I also tried to add a 5 second sleep after the service stop command.
  	Write-Host "Five second sleep"
	Start-Sleep -s 5

I've tried about 6-7 releases now and the problem doesn't occur anymore. But is this just a delay windows has in stopping the service? It doesn't feel like a solid fix. It doesn't feel that I fix the problem but more that I fix a symptom.

Does the redgate team has experience with this issue?

Comments

  • The $svc.WaitForStatus('Stopped') line will stop the service and wait for it to stop, i.e. releasing all the locks on the files it uses.

    I agree with the SO post that you should work out what's locking it -- virus scanners, windows search indexing, etc... are all good candidates given that it looks like the service should definitely have stopped.

    I'm glad that it's working now, and it may be that you've fixed the issue.

    For reference, we do a couple of things internally when we deploy services:

    1) We explicitly uninstall the old service and then re-install the new one using the Microsoft tool Installutil. This means any changes to the service's configuration, e.g. command line arguments etc, get applied. Here's the Deploy.ps1 script we use for this (internal reference https://github.com/red-gate/CORE-Websit ... Deploy.ps1):
    $ErrorActionPreference = "Stop"
    
    $Assembly = "RedGate.Internal.DownloadsToHubspot.Service"
    
    Write-Host "`nChecking if the service already exists...`n"
    
    if (Get-Service $Assembly -ErrorAction SilentlyContinue)
    {
        Write-Host "`nStopping and removing existing service...`n"
    
        & ".\InstallUtil" @("/u", "$Assembly.exe") | Write-Host
        
        if ($global:lastExitCode -ne 0) { exit 1 }
    }
    
    Write-Host "`nInstalling the new service...`n"
    
    & ".\InstallUtil" "$Assembly.exe" | Write-Host
    
    if ($global:lastExitCode -ne 0) { exit 1 }
    
    Write-Host "`nStarting the new service...`n"
    
    Start-Service $Assembly
    
    if ($global:lastExitCode -ne 0) { exit 1 }
    
    Write-Host "`nSettings the failure options of the new service...`n"
    
    & "sc.exe" @("failure", "$Assembly", "reset=", "INFINITE", "actions=", "restart/300000") | Write-Host
    
    if ($global:lastExitCode -ne 0) { exit 1 }
    


    2) When we test our TeamCity plugin we have a MS-DOS batch file to copy a file to our test server (we don't use Deployment Manager for this; internal reference https://rg-source01.red-gate.com/svn/Re ... deploy.bat). We explicitly stop the service and wait for it to stop, which is exactly what you're doing by calling $svc.WaitForStatus('Stopped'):
    copy RedGateSQLServer.zip \\%TARGETSERVER%\c$\TeamCity-Config\plugins
    
    sc \\%TARGETSERVER% stop TeamCity
    
    :wait
    sc \\%TARGETSERVER% query TeamCity | find "STOPPED"
    IF ERRORLEVEL 1 GOTO wait
    
    sc \\%TARGETSERVER% start TeamCity
    
Sign In or Register to comment.