Solved

Problem installing service with vb 2005

Posted on 2008-10-02
8
307 Views
Last Modified: 2013-11-07
I have code that will install and uninstall my service, however, if the service is installed, then uninstalled, it cannot be installed again unless my application is restarted. My code is below if you can find the problem.

Code to install:
      Dim c As New SvcInstaller.ServiceInstaller()
        If c.InstallService("C:\myservice.exe", "ServiceName", "Service description") = True Then
            MessageBox.Show("Success!")
        Else
            MessageBox.Show("Error!")
        End If

Code to uninstall:
 Dim c As New SvcInstaller.ServiceInstaller()
       
        c.UnInstallService("ServiceName")
Imports System
Imports System.Runtime.InteropServices
Namespace SvcInstaller
    Class ServiceInstaller
 
        <DllImport("advapi32.dll")> _
        Public Shared Function OpenSCManager(ByVal lpMachineName As String, ByVal lpSCDB As String, ByVal scParameter As Integer) As IntPtr
        End Function
        <DllImport("Advapi32.dll")> _
        Public Shared Function CreateService(ByVal SC_HANDLE As IntPtr, ByVal lpSvcName As String, ByVal lpDisplayName As String, ByVal dwDesiredAccess As Integer, ByVal dwServiceType As Integer, ByVal dwStartType As Integer, _
         ByVal dwErrorControl As Integer, ByVal lpPathName As String, ByVal lpLoadOrderGroup As String, ByVal lpdwTagId As Integer, ByVal lpDependencies As String, ByVal lpServiceStartName As String, _
         ByVal lpPassword As String) As IntPtr
        End Function
        <DllImport("advapi32.dll")> _
        Public Shared Sub CloseServiceHandle(ByVal SCHANDLE As IntPtr)
        End Sub
        <DllImport("advapi32.dll")> _
        Public Shared Function StartService(ByVal SVHANDLE As IntPtr, ByVal dwNumServiceArgs As Integer, ByVal lpServiceArgVectors As String) As Integer
        End Function
        <DllImport("advapi32.dll", SetLastError:=True)> _
        Public Shared Function OpenService(ByVal SCHANDLE As IntPtr, ByVal lpSvcName As String, ByVal dwNumServiceArgs As Integer) As IntPtr
        End Function
        <DllImport("advapi32.dll")> _
        Public Shared Function DeleteService(ByVal SVHANDLE As IntPtr) As Integer
        End Function
        <DllImport("kernel32.dll")> _
        Public Shared Function GetLastError() As Integer
        End Function
 
        Public Function InstallService(ByVal svcPath As String, ByVal svcName As String, ByVal svcDispName As String) As Boolean
            Dim SC_MANAGER_CREATE_SERVICE As Integer = &H2
            Dim SERVICE_WIN32_OWN_PROCESS As Integer = &H10
            Dim SERVICE_ERROR_NORMAL As Integer = &H1
            Dim STANDARD_RIGHTS_REQUIRED As Integer = &HF0000
            Dim SERVICE_QUERY_CONFIG As Integer = &H1
            Dim SERVICE_CHANGE_CONFIG As Integer = &H2
            Dim SERVICE_QUERY_STATUS As Integer = &H4
            Dim SERVICE_ENUMERATE_DEPENDENTS As Integer = &H8
            Dim SERVICE_START As Integer = &H10
            Dim SERVICE_STOP As Integer = &H20
            Dim SERVICE_PAUSE_CONTINUE As Integer = &H40
            Dim SERVICE_INTERROGATE As Integer = &H80
            Dim SERVICE_USER_DEFINED_CONTROL As Integer = &H100
            Dim SERVICE_ALL_ACCESS As Integer = (STANDARD_RIGHTS_REQUIRED Or SERVICE_QUERY_CONFIG Or SERVICE_CHANGE_CONFIG Or SERVICE_QUERY_STATUS Or SERVICE_ENUMERATE_DEPENDENTS Or SERVICE_START Or SERVICE_STOP Or SERVICE_PAUSE_CONTINUE Or SERVICE_INTERROGATE Or SERVICE_USER_DEFINED_CONTROL)
            Dim SERVICE_AUTO_START As Integer = &H2
            Try
                Dim sc_handle As IntPtr = OpenSCManager(Nothing, Nothing, SC_MANAGER_CREATE_SERVICE)
                If sc_handle.ToInt32() <> 0 Then
                    Dim sv_handle As IntPtr = CreateService(sc_handle, svcName, svcDispName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, _
                     SERVICE_ERROR_NORMAL, svcPath, Nothing, 0, Nothing, Nothing, _
                     Nothing)
                    If sv_handle.ToInt32() = 0 Then
                        CloseServiceHandle(sc_handle)
                        Return False
                    Else
                        Dim i As Integer = StartService(sv_handle, 0, Nothing)
                        If i = 0 Then
                            Return False
                        End If
                        CloseServiceHandle(sc_handle)
                        Return True
                    End If
                Else
                    Return False
                End If
            Catch e As Exception
                Throw e
            End Try
        End Function
       
        Public Function UnInstallService(ByVal svcName As String) As Boolean
            Dim GENERIC_WRITE As Integer = &H40000000
            Dim sc_hndl As IntPtr = OpenSCManager(Nothing, Nothing, GENERIC_WRITE)
            If sc_hndl.ToInt32() <> 0 Then
                Dim DELETE As Integer = &H10000
                Dim svc_hndl As IntPtr = OpenService(sc_hndl, svcName, DELETE)
                If svc_hndl.ToInt32() <> 0 Then
                    Dim i As Integer = DeleteService(svc_hndl)
                    If i <> 0 Then
                        CloseServiceHandle(sc_hndl)
                        Return True
                    Else
                        CloseServiceHandle(sc_hndl)
                        Return False
                    End If
                Else
                    Return False
                End If
            Else
                Return False
            End If
        End Function
    End Class
End Namespace

Open in new window

0
Comment
Question by:andy148
  • 5
  • 3
8 Comments
 
LVL 25

Expert Comment

by:SStory
ID: 22651182
I can't understand you question. You said it can't be reinstalled unless the application is restarted.
Do you mean the service itself by the application? Is there another application that works with this service?

If you mean the latter, is there some library that both the application and service share?  If so perhaps that is causing this problem.
0
 

Author Comment

by:andy148
ID: 22661951
I have 2 applications. 1 of them is a regular windows application, the other is a service. the windows application gives the user an option to install and start the service. The user can also stop and uninstall the service. But if they want to install the service again, after it has been installed and uninstalled, the windows application must be restarted. Also, the application and the service do not share any 3rd party dlls, other than Windows dlls. Hope that helps :)
0
 
LVL 25

Expert Comment

by:SStory
ID: 22671415
OK.  Does the windows application talk to the service somehow?  What requires the windows app to be restarted? Are you saying the service does something and it by itself doesn't work when reinstalled until the win app closes?  Or are you saying the win app installs it and then communicates with it and has trouble after uninstall reinstall?  Or is the Windows app just a simple service installation/removal app?

Are you sure that:
CloseServiceHandle(sc_hndl)

Gets called and a handle isn't left open?  This could cause the problem if it isn't.
0
Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

 
LVL 25

Expert Comment

by:SStory
ID: 22671439
http://msdn.microsoft.com/en-us/library/ms682562(VS.85).aspx

Mentions that the delete is only marked for deletion and
"not removed until all open handles to the service have been closed by calls to the CloseServiceHandle function, and the service is not running"

I don't see you stopping the service.  Docs say to use:  ControlService() to stop it
http://msdn.microsoft.com/en-us/library/ms682108(VS.85).aspx
0
 

Author Comment

by:andy148
ID: 22682127
I tried placing CloseServiceHandle(sc_hndl) everywhere I possibly could to make sure it got called. Also, before I uninstall the service, I use NET STOP.
0
 
LVL 25

Accepted Solution

by:
SStory earned 500 total points
ID: 22682638
andy148, I honestly don't know. I feel that it is keeping a handle open or an object reference. I don't see any of those so I assume a handle and restarting the app releases it.

I assume the Service is a DotNet Service and thus when you uninstall it, but before you close the app, is the process for that services still running?
0
 

Author Comment

by:andy148
ID: 22691738
I found the problem. It was a handle left open, but it was in the install service instead of the uninstall service. Here is the corrected code in case anyone else reads this. Thanks for your help!
Imports System
Imports System.Runtime.InteropServices
Class SvcInstaller
 
    <DllImport("advapi32.dll")> _
    Public Shared Function OpenSCManager(ByVal lpMachineName As String, ByVal lpSCDB As String, ByVal scParameter As Integer) As IntPtr
    End Function
    <DllImport("Advapi32.dll")> _
    Public Shared Function CreateService(ByVal SC_HANDLE As IntPtr, ByVal lpSvcName As String, ByVal lpDisplayName As String, ByVal dwDesiredAccess As Integer, ByVal dwServiceType As Integer, ByVal dwStartType As Integer, _
     ByVal dwErrorControl As Integer, ByVal lpPathName As String, ByVal lpLoadOrderGroup As String, ByVal lpdwTagId As Integer, ByVal lpDependencies As String, ByVal lpServiceStartName As String, _
     ByVal lpPassword As String) As IntPtr
    End Function
    <DllImport("advapi32.dll")> _
    Public Shared Sub CloseServiceHandle(ByVal SCHANDLE As IntPtr)
    End Sub
    <DllImport("advapi32.dll")> _
    Public Shared Function StartService(ByVal SVHANDLE As IntPtr, ByVal dwNumServiceArgs As Integer, ByVal lpServiceArgVectors As String) As Integer
    End Function
    <DllImport("advapi32.dll", SetLastError:=True)> _
    Public Shared Function OpenService(ByVal SCHANDLE As IntPtr, ByVal lpSvcName As String, ByVal dwNumServiceArgs As Integer) As IntPtr
    End Function
    <DllImport("advapi32.dll")> _
    Public Shared Function DeleteService(ByVal SVHANDLE As IntPtr) As Integer
    End Function
    <DllImport("kernel32.dll")> _
    Public Shared Function GetLastError() As Integer
    End Function
 
    Public Shared Function InstallService(ByVal svcPath As String, ByVal svcName As String, ByVal svcDispName As String) As Boolean
        Dim SC_MANAGER_CREATE_SERVICE As Integer = &H2
        Dim SERVICE_WIN32_OWN_PROCESS As Integer = &H10
        Dim SERVICE_ERROR_NORMAL As Integer = &H1
        Dim STANDARD_RIGHTS_REQUIRED As Integer = &HF0000
        Dim SERVICE_QUERY_CONFIG As Integer = &H1
        Dim SERVICE_CHANGE_CONFIG As Integer = &H2
        Dim SERVICE_QUERY_STATUS As Integer = &H4
        Dim SERVICE_ENUMERATE_DEPENDENTS As Integer = &H8
        Dim SERVICE_START As Integer = &H10
        Dim SERVICE_STOP As Integer = &H20
        Dim SERVICE_PAUSE_CONTINUE As Integer = &H40
        Dim SERVICE_INTERROGATE As Integer = &H80
        Dim SERVICE_USER_DEFINED_CONTROL As Integer = &H100
        Dim SERVICE_ALL_ACCESS As Integer = (STANDARD_RIGHTS_REQUIRED Or SERVICE_QUERY_CONFIG Or SERVICE_CHANGE_CONFIG Or SERVICE_QUERY_STATUS Or SERVICE_ENUMERATE_DEPENDENTS Or SERVICE_START Or SERVICE_STOP Or SERVICE_PAUSE_CONTINUE Or SERVICE_INTERROGATE Or SERVICE_USER_DEFINED_CONTROL)
        Dim SERVICE_AUTO_START As Integer = &H2
        Try
            Dim sc_handle As IntPtr = OpenSCManager(Nothing, Nothing, SC_MANAGER_CREATE_SERVICE)
            If sc_handle.ToInt32() <> 0 Then
                Dim sv_handle As IntPtr = CreateService(sc_handle, svcName, svcDispName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, _
                 SERVICE_ERROR_NORMAL, svcPath, Nothing, 0, Nothing, Nothing, _
                 Nothing)
                If sv_handle.ToInt32() = 0 Then
                    CloseServiceHandle(sc_handle)
                    Return False
                Else
                    Dim i As Integer = StartService(sv_handle, 0, Nothing)
                    If i = 0 Then
                        Return False
                    End If
                    CloseServiceHandle(sc_handle)
                    CloseServiceHandle(sv_handle)
                    Return True
                End If
            Else
                Return False
            End If
            CloseServiceHandle(sc_handle)
        Catch e As Exception
            Throw e
        End Try
    End Function
 
    Public Shared Function UnInstallService(ByVal svcName As String) As Boolean
        Dim GENERIC_WRITE As Integer = &H40000000
        Dim sc_hndl As IntPtr = OpenSCManager(Nothing, Nothing, GENERIC_WRITE)
        If sc_hndl.ToInt32() <> 0 Then
            Dim DELETE As Integer = &H10000
            Dim svc_hndl As IntPtr = OpenService(sc_hndl, svcName, DELETE)
            If svc_hndl.ToInt32() <> 0 Then
                Dim i As Integer = DeleteService(svc_hndl)
                If i <> 0 Then
                    CloseServiceHandle(svc_hndl)
                    CloseServiceHandle(sc_hndl)
                    Return True
                Else
                    CloseServiceHandle(sc_hndl)
                    CloseServiceHandle(svc_hndl)
                    Return False
                End If
            Else
                Return False
            End If
            Else
                Return False
        End If
    End Function
End Class

Open in new window

0
 
LVL 25

Expert Comment

by:SStory
ID: 22698930
You are welcome!  I'm glad you got it fixed!
0

Featured Post

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Parsing a CSV file is a task that we are confronted with regularly, and although there are a vast number of means to do this, as a newbie, the field can be confusing and the tools can seem complex. A simple solution to parsing a customized CSV fi…
Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

820 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question