Stop + Uninstall a service with Custom Action

I have an application that installs and starts a service during its usage.
I need to stop and uninstall this service as part of the uninstallation process (before actually uninstalling the file(s) in the MyApp folder as they will be in use by the running service)

I can stop and remove the service with the attached code.
How would I go about doing this?

With a custom action as part of my Setup project in Visual Studio can I trigger this pre uninstall?

Coding in VB.NET VS2008
Dim sc As New ServiceController()
        sc.ServiceName = "svrctrl"
        sc.Stop()
        Dim svrctrl As New ProcessStartInfo
        nssm.FileName = "C:\Program Files\MyApp\svrctrl.exe"
        nssm.Arguments = "remove ServiceName"
        nssm.CreateNoWindow = False
        nssm.WindowStyle = ProcessWindowStyle.Hidden
        nssm.WorkingDirectory = "C:\Program Files\MyApp\"
        Process.Start(svrctrl)

Open in new window

LVL 1
madlanAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Meir RivkinFull stack Software EngineerCommented:
yes, in your custom action code simply override the following:

Protected Overloads Overrides Sub OnBeforeUninstall(ByVal savedState As IDictionary)
''put your code here
    MyBase.OnBeforeUninstall(savedState)
End Sub
0
Meir RivkinFull stack Software EngineerCommented:
check this following class i wrote for start/stop services.
u can explicitly call Start/Stop/Restart with the service name
for example:
Services.ServiceRestarter.Restart("mysql")

or using "using" keyword, for example:
 Using (New Services.ServiceRestarter("MySql"))
            ''do some stuff while service is down
        End Using

in the ctor the service is stopped and upon OnDispose() the service is back on again.
it's perfect when u wish to perform procedures which requires stop then start the service.
Imports System
Imports System.Diagnostics

Namespace Services
    Public Class ServiceRestarter
        Implements IDisposable
#Region "Internal"
        Private _service As String = String.Empty
#End Region

#Region "Ctor"
        ''' <summary>
        ''' Initializes a new instance of the <see cref="ServiceRestarter"/> class.
        ''' </summary>
        ''' <param name="service">The service.</param>
        Public Sub New(ByVal service As String)
            _service = service
            ServiceRestarter.[Stop](_service)
        End Sub

#End Region

#Region "Methods"

#Region "Static"
        ''' <summary>
        ''' Restarts the specified service.
        ''' </summary>
        ''' <param name="service">The service.</param>
        Public Shared Sub Restart(ByVal service As String)
            ServiceRestarter.[Stop](service)
            ServiceRestarter.Start(service)
        End Sub

        ''' <summary>
        ''' Starts the specified service.
        ''' </summary>
        ''' <param name="service">The service.</param>
        Public Shared Sub Start(ByVal service As String)
            Console.WriteLine("Start Service {0}", service)
            Dim proc As Process = Process.Start("net", String.Format("start {0}", service))
            proc.WaitForExit()
            Select Case proc.ExitCode
                Case 2
                    Console.WriteLine("service {0} is already running.", service)
                    Exit Select
                Case 0
                    Console.WriteLine("service {0} was started.", service)
                    Exit Select
                Case Else
                    Throw New ApplicationException(String.Format("start service {0} return with exitCode: {1}", service, proc.ExitCode))
            End Select
        End Sub

        ''' <summary>
        ''' Stops the specified service.
        ''' </summary>
        ''' <param name="service">The service.</param>
        Public Shared Sub [Stop](ByVal service As String)
            Dim proc As Process = Process.Start("net", String.Format("stop {0}", service))
            proc.WaitForExit()
            Select Case proc.ExitCode
                Case 2
                    Console.WriteLine("service {0} is already stopped.", service)
                    Exit Select
                Case 0
                    Console.WriteLine("service {0} was stopped.", service)
                    Exit Select
                Case Else
                    Throw New ApplicationException(String.Format("stop service {0} return with exitCode: {1}", service, proc.ExitCode))
            End Select
        End Sub

#End Region

#End Region

#Region "IDisposable Members"

        ''' <summary>
        ''' Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        ''' </summary>
        Public Sub Dispose() Implements IDisposable.Dispose
            ServiceRestarter.Start(_service)
        End Sub

#End Region
    End Class
End Namespace

Open in new window

0
madlanAuthor Commented:
I've added a VB Class library to the project (add / new project) with the attached code.
How do I get OnBeforeUninstall to reference the innstall project rather than the class it's in?

(sub 'OnBeforeUninstall' cannot be declared 'Overrides' because it does not override a sub in a base class.)

I've referenced the output of the uninstall class to the uninstall custom action.

My Solution is structured:

Solution
------ Actual program (Forms application)
------ Uninstall (VB Class)
------ Installer (Install wizard project)
Public Class Uninstall
    Protected Overloads Overrides Sub OnBeforeUninstall(ByVal savedState As IDictionary)
        ''put your code here
        MyBase.OnBeforeUninstall(savedState)
    End Sub
End Class

Open in new window

0
Cloud Class® Course: C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

Meir RivkinFull stack Software EngineerCommented:
why would u separate the uninstall code from your custom action code?
override OnBeforeUninstall should be placed in your custom action code as well.
0
Meir RivkinFull stack Software EngineerCommented:
check the following custom action class.
it must inherits from class Installer (from System.Configuration.Install) and have the RunInstaller attribute.
Imports System
Imports System.ComponentModel
Imports System.Configuration.Install
Imports System.IO
Imports System.Text
Imports System.Diagnostics

Namespace Common.Containers
    <RunInstaller(True)> _
    Public Class UpdateCustomInstaller
        Inherits Installer
      
        Shared Sub New()
        End Sub


        Protected Overloads Overrides Sub OnBeforeUninstall(ByVal savedState As System.Collections.IDictionary)
            MyBase.OnCommitted(savedState)
        End Sub

    End Class
End Namespace

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Meir RivkinFull stack Software EngineerCommented:
sorry man, i understand how u got mixed up cause i pasted the function signature all wrong in my first post.

0
madlanAuthor Commented:
Ahh I see - thanks sedgwick.
One question, having the resulting .dll in the installation folder is a bit messy, can this code not be embeded in the MSI?
0
Meir RivkinFull stack Software EngineerCommented:
why is it messy?
having this code not embedded in the msi means that it could be in a different exe (or dll) which the msi invokes, is that what u mean?
0
madlanAuthor Commented:
My application has very few files in its program folder, less the better.
I thought the code had to be in it's own dll\exe? for custom actions?
0
Meir RivkinFull stack Software EngineerCommented:
the custom action is coded in a dll which being referenced from the setup deployment project.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.