Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Silently update a Windows service

I have built a Windows service, now I want it to auto-update. I have read about a creating a second service to do that or different program , cant use click one, what about myBuild? Does anyone know it? What is the best way? Can I just change assemblies?

like image 286
guyl Avatar asked Jan 04 '11 13:01

guyl


2 Answers

If you want your service to run while you are performing an update, here is what I had done before to achieve this:

  1. Put your updateble logic into a separate DLL.
  2. Create an AppDomain within your service.
  3. Create file monitor that fires an event whenever you copy that file (you can use MSFT Ent Lib Updates)
  4. Unload the old dll while blocking (queue) the threads that execute stuff from that dll
  5. Load in the new dll file into the app domain.
  6. Let your threads know to continue processing.
like image 199
dexter Avatar answered Oct 08 '22 08:10

dexter


  1. Download the new exe and any additional assembly's.
  2. Rename your existing assembly's.
  3. Copy in your new assembly's.
  4. Restart Service. You can build the service restart function into your main service exe.
  5. When service starts check for renamed files from step 2 and delete them to clean up.

To restart your service do

System.Diagnostics.Process.Start
    (System.Reflection.Assembly.GetEntryAssembly().Location)

Then in your service do

    private const string _mutexId = "MyUniqueId";
    private static Mutex _mutex;
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main()
    {
        try
        {
            bool alreadyRunning = false;
            try
            {
                Mutex.OpenExisting(_mutexId);
                alreadyRunning = true;
            }
            catch (WaitHandleCannotBeOpenedException)
            {
                alreadyRunning = false;
            }
            catch
            {
                alreadyRunning = true;                   
            }
            if (alreadyRunning)
            {
                using (ServiceController sc = new ServiceController("MyServiceName"))
                {
                    sc.Stop();
                    sc.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 0, 120));
                    sc.Start();
                }
                return;
            }
        }
        catch
        {
        }
        _mutex = new Mutex(true, _mutexId);

        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new MyService() 
        };
        // Load the service into memory.
        ServiceBase.Run(ServicesToRun);
        _mutex.Close();
    }
like image 20
Kevin Avatar answered Oct 08 '22 07:10

Kevin