How to upgrade a windows service

Below is an example of my config, install works fine but if I replace \BuildMachine\Output\MyService.exe with a newer version DSC fails with file in use errors. What is the correct way to upgrade a windows service? Thanks.

    Configuration ServiceTestConfiguration {
        Import-DscResource -ModuleName PSDesiredStateConfiguration
        Import-DscResource -ModuleName xPSDesiredStateConfiguration

        Node localhost
            File EnsureLatestServiceExist {
                Ensure = 'Present'
                Type = 'File'
                Checksum = 'ModifiedDate'
                SourcePath = '\\BuildMachine\Output\MyService.exe'
                DestinationPath = 'c:\MyService\MyService.exe'

            xService EnsureServiceStarted {
                Ensure = 'Present'
                DependsOn = '[File]EnsureLatestServiceExist'
                Name = 'MyService'
                DisplayName = 'My Service'
                Description = 'My Service'
                Path = 'c:\MyService\MyService.exe'
                StartupType = 'Automatic'
                State = 'Running'

The service has to be stopped. Honestly, you’d probably have to write a dedicated resource to manage the stop-replace-start sequence.

So I assume there is not a resource Microsoft, community, or otherwise that exists and can do this?

To be blunt: service installs in many ways put you at the mercy of the service developer when it comes to how easy it is to deploy or upgrade something. There’s not a “simple” tool on this planet that lets you install error free any random service be it DSC, SCCM, Alteris, or otherwise.

Writing a dedicated resource for DSC isn’t hard. The logic behind pushing software, updating software, etc … that can be hard … and has been for decades.

The best thing you can do, IMO, is try to deploy from a simple PS script. If you can get hat to work quietly/repeatedly, you can then modularize what you’re doing into DSC very easily, possibly with the script resource:

script Installmyservice {
 testScript = {check to see if its needed here}
 setscript  = {install goes here}
 getscript  = {what the reporting server gets back}

This is no different than if you had to do a silent deploy in SCCM: you first fuddle with your script to get it to work, then package that in SCCM. In this case, you are just going to turn it into a DSC module like Don mentioned, or if it’s simple enough just put the logic into the setscript block.

I am also the service developer, I built the service with .NET. I have not built an installer yet for the service at this point because I was thinking of using DSC exclusively for deployment.

I understand I can write custom script and code to do this and as a developer that is often my first instinct, is to write my own code to do everything. This just seemed like such a common scenario I would have expected there to be a tried and true way of doing it. I was trying to go against my instinct and reuse what already existed.

Given that it is no community or official Microsoft way of doing this I plan on doing the following.

  1. Write a custom resource that checks for diffs between two directories and kills\stops specific services if there is.
  2. use the built in file resource to copy files now that my first step has killed the service. I might not use the built in file resource since it does not delete extra files :frowning: )
  3. use the Microsoft xService to ensure the service is installed and running.
  4. Wrap this into composite\nested configuration that can be reused for all of my services.

This should work for both upgrade and install scenarios, and yes I know to make sure I use the DependsOn since order is not supported.

Thanks for the suggestions.