timtos
timtos

Reputation: 2305

DSC: How to stop and start a windows service

I want to do a very simple thing with DSC (Desired State Configuration):

Stop a windows service, deploy files and finally start the service again. Thus I had the following:

Service ServicesStop
{
    Name = "TheTestService"
    State = "Stopped"
}

File CopyDeploymentBits
{  
  Ensure = "Present"
  Type = "Directory"
  Recurse = $true
  SourcePath = $applicationPath
  DestinationPath = $deployOutputPath
}

Service ServicesStart
{
    Name = "TheTestService"
    StartupType = "Automatic"
    State = "Running"
}

But unfortunately this is not working as it is not allowed to have the same name (Name = "TheTestService") in a configuration twice (Why? In this case it would totally make sense) as a workaround I tried something like this

Configuration MyTestConfig {
    Node $env:COMPUTERNAME {
        Service ServicesStop
        {
            Name = "TheTestService"
            State = "Stopped"
        }

        File CopyDeploymentBits
        {  
          Ensure = "Present"
          Type = "Directory"
          Recurse = $true
          SourcePath = $applicationPath
          DestinationPath = $deployOutputPath
        }
    }
}

Configuration MyTestConfig2 {
    Node $env:COMPUTERNAME {
        Service ServicesStart
        {
            Name = "TheTestService"
            StartupType = "Automatic"
            State = "Running"
        }
    }
}

MyTestConfig
MyTestConfig2

Looks insane - but it works!

Unfortunately, I am not using plain DSC I am using it with Microsoft Release Management and here, it seems that the 'MyTestConfig2' is not executed anymore (or something else goes wrong that is not mentioned in the logs).

How can I realize this simple scenario with dsc within the context of release management? Or is there even a better way to do something like this?

Upvotes: 3

Views: 6471

Answers (3)

Joerg Hochwald
Joerg Hochwald

Reputation: 21

At least for me the following works best:

# Configure the Service 1st
Service Servicewuauserv {
    Name = 'wuauserv'
    BuiltInAccount = 'LocalSystem'
    State = 'Running'
}

And then:

# Ensure it is running
ServiceSet wuauserv {
     Name = 'wuauserv'
     BuiltInAccount = 'LocalSystem'
     State = 'Running'
}

Yep, makes it more complex, but the split seems to work best with some services.

Upvotes: 0

timtos
timtos

Reputation: 2305

Afer Daniel Mann's post I came up with this minimal solution:

[DscResource()]
class InstallStopCopyStartServiceResource {
    [DscProperty(Key)]
    [string]$ServiceName

    [DscProperty(Mandatory)]
    [string] $SourcePath

    [DscProperty(Mandatory)]
    [string] $DestinationPath

    [void] Set()
    {
        $needsInstallation = $false;

        $testService = Get-Service | Where-Object {$_.Name -eq $this.ServiceName}
        if ($testService -eq $null) 
        {
            $needsInstallation = $true;
        } elseif ($testService.Status -eq "Running") 
        {
            Stop-Service $this.ServiceName
        } 

        # Due to stupid Copy-Item behavior we first delete all old files
        # (https://social.technet.microsoft.com/Forums/office/en-US/20b9d259-90d9-4e51-a125-c0f3dafb498c/copyitem-not-overwriting-exising-files-but-creating-additional-subfolder?forum=winserverpowershell)
        Remove-Item -Path $this.DestinationPath -Recurse -Force -ErrorAction SilentlyContinue

        # Copy files
        Copy-Item -Path $this.SourcePath -Destination $this.DestinationPath -Recurse -Force

        if ($needsInstallation -eq $true) 
        {
            # Install service
            $param = 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\installUtil ' + $this.DestinationPath  + '\service.exe'
            Invoke-Expression $param
        }

        # Start the service
        Start-Service $this.ServiceName

        # Configure service
        Set-Service $this.ServiceName -StartupType "Automatic"
    }

    [bool] Test()
    {
        # Always perform all steps
        return $false
    }

    [InstallStopCopyStartServiceResource] Get()
    {
        return $this
    }

}

Upvotes: 0

Nana Lakshmanan
Nana Lakshmanan

Reputation: 739

The simplest way is to create a service resource that takes both Name and State as key. Feel free to extend this simple service resource (I will try to get to it when I find time) https://github.com/nanalakshmanan/nServiceManager

Upvotes: 2

Related Questions