Install Windows Service with Interacted with Desktop



	Private Sub ProjectInstaller_AfterInstall(ByVal sender As Object, ByVal e As System.Configuration.Install.InstallEventArgs) Handles MyBase.AfterInstall

		'Our code goes in this event because it is the only one that will do

		'a proper job of letting the user know that an error has occurred,

		'if one indeed occurs. Installation will be rolled back if an error occurs.



		Dim iSCManagerHandle As Integer

		Dim iSCManagerLockHandle As Integer

		Dim iServiceHandle As Integer

		Dim bChangeServiceConfig As Boolean

		Dim bChangeServiceConfig2 As Boolean

		Dim ServiceDescription As modAPI.SERVICE_DESCRIPTION

		Dim ServiceFailureActions As modAPI.SERVICE_FAILURE_ACTIONS

		Dim ScActions(2) As modAPI.SC_ACTION	 'There should be one element for each

		'action. The Services snap-in shows 3 possible actions.



		Dim bCloseService As Boolean

		Dim bUnlockSCManager As Boolean

		Dim bCloseSCManager As Boolean



		Dim iScActionsPointer As New IntPtr



		Try

			'Obtain a handle to the Service Control Manager, with appropriate rights.

			'This handle is used to open the relevant service.

			iSCManagerHandle = modAPI.OpenSCManager(vbNullString, vbNullString, _

			modAPI.ServiceControlManagerType.SC_MANAGER_ALL_ACCESS)



			'Check that it's open. If not throw an exception.

			If iSCManagerHandle < 1 Then

				Throw New Exception("Unable to open the Services Manager.")

			End If



			'Lock the Service Control Manager database.

			iSCManagerLockHandle = modAPI.LockServiceDatabase(iSCManagerHandle)



			'Check that it's locked. If not throw an exception.

			If iSCManagerLockHandle < 1 Then

				Throw New Exception("Unable to lock the Services Manager.")

			End If



			'Obtain a handle to the relevant service, with appropriate rights.

			'This handle is sent along to change the settings. The second parameter

			'should contain the name you assign to the service.

			iServiceHandle = modAPI.OpenService(iSCManagerHandle, "ServiceTest", _

			modAPI.ACCESS_TYPE.SERVICE_ALL_ACCESS)



			'Check that it's open. If not throw an exception.

			If iServiceHandle < 1 Then

				Throw New Exception("Unable to open the Service for modification.")

			End If



			'Call ChangeServiceConfig to update the ServiceType to SERVICE_INTERACTIVE_PROCESS.

			'Very important is that you do not leave out or change the other relevant

			'ServiceType settings. The call will return False if you do.

			'Also, only services that use the LocalSystem account can be set to

			'SERVICE_INTERACTIVE_PROCESS.

			bChangeServiceConfig = modAPI.ChangeServiceConfig(iServiceHandle, _

			modAPI.ServiceType.SERVICE_WIN32_OWN_PROCESS + modAPI.ServiceType.SERVICE_INTERACTIVE_PROCESS, _

			SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, vbNullString, vbNullString, _

			vbNullString, vbNullString, vbNullString, vbNullString, vbNullString)



			'If the call is unsuccessful, throw an exception.

			If Not bChangeServiceConfig Then

				Throw New Exception("Unable to change the Service settings.")

			End If



			'To change the description, create an instance of the SERVICE_DESCRIPTION

			'structure and set the lpDescription member to your desired description.

			ServiceDescription.lpDescription = "This is my custom description for my Windows Service Application!"



			'Call ChangeServiceConfig2 with SERVICE_CONFIG_DESCRIPTION in the second

			'parameter and the SERVICE_DESCRIPTION instance in the third parameter

			'to update the description.

			bChangeServiceConfig2 = modAPI.ChangeServiceConfig2(iServiceHandle, _

			modAPI.InfoLevel.SERVICE_CONFIG_DESCRIPTION, ServiceDescription)



			'If the update of the description is unsuccessful it is up to you to

			'throw an exception or not. The fact that the description did not update

			'should not impact the functionality of your service.

			If Not bChangeServiceConfig2 Then

				Throw New Exception("Unable to set the Service description.")

			End If



			'To change the Service Failure Actions, create an instance of the

			'SERVICE_FAILURE_ACTIONS structure and set the members to your

			'desired values. See MSDN for detailed descriptions.

			ServiceFailureActions.dwResetPeriod = 600

			ServiceFailureActions.lpRebootMsg = "Service failed to start! Rebooting..."

			ServiceFailureActions.lpCommand = "SomeCommand.exe Param1 Param2"

			ServiceFailureActions.cActions = ScActions.Length



			'The lpsaActions member of SERVICE_FAILURE_ACTIONS is a pointer to an

			'array of SC_ACTION structures. This complicates matters a little,

			'and although it took me a week to figure it out, the solution

			'is quite simple.



			'First order of business is to populate our array of SC_ACTION structures

			'with appropriate values.

			ScActions(0).Delay = 20000

			ScActions(0).SCActionType = modAPI.SC_ACTION_TYPE.SC_ACTION_RESTART

			ScActions(1).Delay = 20000

			ScActions(1).SCActionType = modAPI.SC_ACTION_TYPE.SC_ACTION_RUN_COMMAND

			ScActions(2).Delay = 20000

			ScActions(2).SCActionType = modAPI.SC_ACTION_TYPE.SC_ACTION_REBOOT



			'Once that's done, we need to obtain a pointer to a memory location

			'that we can assign to lpsaActions in SERVICE_FAILURE_ACTIONS.

			'We use 'Marshal.SizeOf(New modAPI.SC_ACTION) * 3' because we pass 

			'3 actions to our service. If you have less actions change the * 3 accordingly.

			iScActionsPointer = Marshal.AllocHGlobal(Marshal.SizeOf(New modAPI.SC_ACTION) * 3)



			'Once we have obtained the pointer for the memory location we need to

			'fill the memory with our structure. We use the CopyMemory API function

			'for this. Please have a look at it's declaration in modAPI.

			modAPI.CopyMemory(iScActionsPointer, ScActions, Marshal.SizeOf(New modAPI.SC_ACTION) * 3)



			'We set the lpsaActions member of SERVICE_FAILURE_ACTIONS to the integer

			'value of our pointer.

			ServiceFailureActions.lpsaActions = iScActionsPointer.ToInt32



			'We call bChangeServiceConfig2 with the relevant parameters.

			bChangeServiceConfig2 = modAPI.ChangeServiceConfig2(iServiceHandle, _

			modAPI.InfoLevel.SERVICE_CONFIG_FAILURE_ACTIONS, ServiceFailureActions)



			'If the update of the failure actions are unsuccessful it is up to you to

			'throw an exception or not. The fact that the failure actions did not update

			'should not impact the functionality of your service.

			If Not bChangeServiceConfig2 Then

				Throw New Exception("Unable to set the Service failure actions.")

			End If

		Catch ex As Exception

			Throw ex

		Finally

			'Once you are done you should close/release the handles to the service

			'and the Service Control Manager, as well as free the memory that held

			'the array of SC_ACTION structures.



			Marshal.FreeHGlobal(iScActionsPointer)

			If iServiceHandle > 0 Then

				bCloseService = modAPI.CloseServiceHandle(iServiceHandle)

			End If



			bUnlockSCManager = modAPI.UnlockServiceDatabase(iSCManagerLockHandle)



			If iSCManagerHandle > 0 Then

				bCloseSCManager = modAPI.CloseServiceHandle(iSCManagerHandle)

			End If

		End Try



		'When installation is done go check out your handy work using Computer Management!

	End Sub



 
發佈了29 篇原創文章 · 獲贊 379 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章