Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Service() - Function set for Handling Windows Services


  • Please log in to reply
15 replies to this topic
heresy
  • Members
  • 291 posts
  • Last active: Sep 26 2008 10:47 PM
  • Joined: 11 Mar 2008
Note : Remote does not supported at the moment though it can be easily modified.
Thanks Lexikos and his StructParser for helping me about structs.


[*:2ud6n77y]Service_List(State="", Type="", delimiter="`n") - Get List of Windows Service
State="" Get List of All Windows Service
State="Active" Get List of Active(Running) Windows Service
State="Inactive" Get List of Inactive(Stopped) Windows Service

Type="" Get List of WIN32 Service
Type="Driver" Get List of DRIVER Service
Type="All" Both[*:2ud6n77y]Service_Start(ServiceName)
[*:2ud6n77y]Service_Stop(ServiceName)
[*:2ud6n77y]Service_State(ServiceName)
- Return Values
SERVICE_STOPPED (1) : The service is not running.
SERVICE_START_PENDING (2) : The service is starting.
SERVICE_STOP_PENDING (3) : The service is stopping.
SERVICE_RUNNING (4) : The service is running.
SERVICE_CONTINUE_PENDING (5) : The service continue is pending.
SERVICE_PAUSE_PENDING (6) : The service pause is pending.
SERVICE_PAUSED (7) : The service is paused.[*:2ud6n77y]Service_Add(ServiceName, BinaryPath, StartType="")
ServiceName ServiceName to be added.
BinaryPath Binary(.exe) path to be added.
StartType="" Start by Demand
StartType="Anything Else" Start automatically[*:2ud6n77y]Service_Delete(ServiceName)

- Generic Return Values
1 : Success
0 : Failure
-4 : Service Not Found[/list]

Example
MsgBox % Service_List("Active") ;Get List of Running Win32 Service

if Service_State("Print Spooler")=4 ;if Print Spooler service is running
    Service_Stop("Print Spooler") ;stop
else if Service_State("Print Spooler")=1 ;if Print Spooler service is not running
    Service_Start("Print Spooler") ;start

MsgBox % Service_State("Print Spooler")
Download Service.ahk



or



Get Source (You need internal function _GetName_() as well)
/* Windows Service Control Functions
-heresy

- Return Values
     1 : Success
     0 : Failure
    -4 : Service Not Found

- State codes from Service_State() 
    SERVICE_STOPPED (1) : The service is not running.
    SERVICE_START_PENDING (2) : The service is starting.
    SERVICE_STOP_PENDING (3) : The service is stopping.
    SERVICE_RUNNING (4) : The service is running.
    SERVICE_CONTINUE_PENDING (5) : The service continue is pending.
    SERVICE_PAUSE_PENDING (6) : The service pause is pending.
    SERVICE_PAUSED (7) : The service is paused.
*/


Service_List(State="", Type="", delimiter="`n"){
    if !State
        ServiceState := 0x3 ;SERVICE_STATE_ALL (0x00000003)
    else if (State="Active")
        ServiceState := 0x1 ;SERVICE_ACTIVE (0x00000001)
    else if (State="Inactive")
        ServiceState := 0x2 ;SERVICE_INACTIVE (0x00000002)
    else
        ServiceState := 0x3
    
    if !Type
        ServiceType := 0x30 ;SERVICE_WIN32 (0x00000030)
    else if (Type="Driver")
        ServiceType := 0xB ;SERVICE_DRIVER (0x0000000B)
    else if (Type="All")
        ServiceType := 0x3B ;sum of both
    else
        ServiceType := 0x30
       
    SCM_HANDLE := DllCall("advapi32\OpenSCManagerA"
                        , "Int", 0
                        , "Int", 0
                        , "UInt", 0x4) ;SC_MANAGER_ENUMERATE_SERVICE (0x0004)    

    DllCall("advapi32\EnumServicesStatusA"
        , "UInt", SCM_HANDLE
        , "UInt", ServiceType
        , "UInt", ServiceState
        , "UInt", 0
        , "UInt", 0
        , "UIntP", bSize ;get required buffer size first
        , "UIntP", 0
        , "UIntP", 0)
    
    VarSetCapacity(ENUM_SERVICE_STATUS, bSize, 0) ;prepare struct
    
    DllCall("advapi32\EnumServicesStatusA" ;actual enumeration
        , "UInt", SCM_HANDLE
        , "UInt", ServiceType
        , "UInt", ServiceState
        , "UInt", &ENUM_SERVICE_STATUS
        , "UInt", bSize
        , "UIntP", 0
        , "UIntP", ServiceCount
        , "UIntP", 0)
    
    Loop, %ServiceCount%
        result .= DllCall("MulDiv"
                        , "Int", NumGet(ENUM_SERVICE_STATUS, (A_Index-1)*36+4)
                        , "Int", 1
                        , "Int", 1, "str") . delimiter

    DllCall("advapi32\CloseServiceHandle", "UInt", SCM_HANDLE)
    Return result
    
}

Service_Start(ServiceName)
{
    ServiceName := _GetName_(ServiceName) 

    SCM_HANDLE := DllCall("advapi32\OpenSCManagerA"
                        , "Int", 0 ;NULL for local
                        , "Int", 0
                        , "UInt", 0x1) ;SC_MANAGER_CONNECT (0x0001)    

    if !(SC_HANDLE := DllCall("advapi32\OpenServiceA"
                            , "UInt", SCM_HANDLE
                            , "Str", ServiceName
                            , "UInt", 0x10)) ;SERVICE_START (0x0010)
        result := -4 ;Service Not Found

    if !result
        result := DllCall("advapi32\StartServiceA"
                        , "UInt", SC_HANDLE
                        , "Int", 0
                        , "Int", 0)

    DllCall("advapi32\CloseServiceHandle", "UInt", SC_HANDLE)
    DllCall("advapi32\CloseServiceHandle", "UInt", SCM_HANDLE)
    return result
}

Service_Stop(ServiceName)
{
    ServiceName := _GetName_(ServiceName)

    SCM_HANDLE := DllCall("advapi32\OpenSCManagerA"
                        , "Int", 0 ;NULL for local
                        , "Int", 0
                        , "UInt", 0x1) ;SC_MANAGER_CONNECT (0x0001)    

    if !(SC_HANDLE := DllCall("advapi32\OpenServiceA"
                            , "UInt", SCM_HANDLE
                            , "Str", ServiceName
                            , "UInt", 0x20)) ;SERVICE_STOP (0x0020)
        result := -4 ;Service Not Found

    if !result
        result := DllCall("advapi32\ControlService"
                        , "UInt", SC_HANDLE
                        , "Int", 1
                        , "Str", "")

    DllCall("advapi32\CloseServiceHandle", "UInt", SC_HANDLE)
    DllCall("advapi32\CloseServiceHandle", "UInt", SCM_HANDLE)
    return result
}

Service_State(ServiceName)
{ ; Return Values
; SERVICE_STOPPED (1) : The service is not running.
; SERVICE_START_PENDING (2) : The service is starting.
; SERVICE_STOP_PENDING (3) : The service is stopping.
; SERVICE_RUNNING (4) : The service is running.
; SERVICE_CONTINUE_PENDING (5) : The service continue is pending.
; SERVICE_PAUSE_PENDING (6) : The service pause is pending.
; SERVICE_PAUSED (7) : The service is paused.
    ServiceName := _GetName_(ServiceName)

    SCM_HANDLE := DllCall("advapi32\OpenSCManagerA"
                        , "Int", 0 ;NULL for local
                        , "Int", 0
                        , "UInt", 0x1) ;SC_MANAGER_CONNECT (0x0001)
                            
    if !(SC_HANDLE := DllCall("advapi32\OpenServiceA"
                            , "UInt", SCM_HANDLE
                            , "Str", ServiceName
                            , "UInt", 0x4)) ;SERVICE_QUERY_STATUS (0x0004)
        result := -4 ;Service Not Found

    VarSetCapacity(SC_STATUS, 28, 0) ;SERVICE_STATUS Struct

    if !result
        result := !DllCall("advapi32\QueryServiceStatus"
                         , "UInt", SC_HANDLE
                         , "UInt", &SC_STATUS)
                         ? False : NumGet(SC_STATUS, 4) ;-1 or dwCurrentState

    DllCall("advapi32\CloseServiceHandle", "UInt", SC_HANDLE)
    DllCall("advapi32\CloseServiceHandle", "UInt", SCM_HANDLE)
    return result
}

Service_Add(ServiceName, BinaryPath, StartType=""){
    if !A_IsAdmin
        Return False

    SCM_HANDLE := DllCall("advapi32\OpenSCManagerA"
                        , "Int", 0
                        , "Int", 0
                        , "UInt", 0x2) ;SC_MANAGER_CREATE_SERVICE (0x0002)
    
    StartType := !StartType ? 0x3 : 0x2
    ;SERVICE_DEMAND_START(0x00000003) vs SERVICE_AUTO_START(0x00000002)
    
    SC_HANDLE := DllCall("advapi32\CreateServiceA"
                   , "UInt", SCM_HANDLE
                   , "Str", ServiceName
                   , "Str", ServiceName
                   , "UInt", 0xF01FF ;SERVICE_ALL_ACCESS (0xF01FF)
                   , "UInt", 0x110 ;SERVICE_WIN32_OWN_PROCESS(0x00000010) | SERVICE_INTERACTIVE_PROCESS(0x00000100)
    ;interactable service with desktop (requires local account)
    ;http://msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx
                   , "UInt", StartType
                   , "UInt", 0x1 ;SERVICE_ERROR_NORMAL(0x00000001)
                   , "Str", BinaryPath
                   , "Str", "" ;No Group
                   , "UInt", 0 ;No TagId
                   , "Str", "" ;No Dependencies
                   , "Int", 0 ;Use LocalSystem Account
                   , "Str", "")
    result := A_LastError ? SC_HANDLE "," A_LastError : 1
    DllCall("advapi32\CloseServiceHandle", "UInt", SC_HANDLE)
    DllCall("advapi32\CloseServiceHandle", "UInt", SCM_HANDLE)
    Return result
}

Service_Delete(ServiceName)
{
    if !A_IsAdmin ;Requires Administrator rights
        Return False
    ServiceName := _GetName_(ServiceName)    

    SCM_HANDLE := DllCall("advapi32\OpenSCManagerA"
                        , "Int", 0 ;NULL for local
                        , "Int", 0
                        , "UInt", 0x1) ;SC_MANAGER_CONNECT (0x0001)

    if !(SC_HANDLE := DllCall("advapi32\OpenServiceA"
                            , "UInt", SCM_HANDLE
                            , "Str", ServiceName
                            , "UInt", 0xF01FF)) ;SERVICE_ALL_ACCESS (0xF01FF)
        result := -4 ;Service Not Found

    if !result
        result := DllCall("advapi32\DeleteService", "Uint", SC_HANDLE)

    DllCall("advapi32\CloseServiceHandle", "UInt", SC_HANDLE)
    Return result    
}

_GetName_(DisplayName)
{ ;Internal, Gets Service Name from Display Name, 
    SCM_HANDLE := DllCall("advapi32\OpenSCManagerA", "Int", 0, "Int", 0, "UInt", 0x1) ;SC_MANAGER_CONNECT (0x0001)    

    DllCall("advapi32\GetServiceKeyNameA" ;Get Buffer Size
            , "Uint", SCM_HANDLE
            , "Str", DisplayName
            , "Int", 0
            , "UintP", Len)

    VarSetCapacity(Buffer, Len) ;Prepare Buffer

    DllCall("advapi32\GetServiceKeyNameA" ;Get Actual Service Name
        , "Uint", SCM_HANDLE
        , "Str", DisplayName
        , "Uint", &Buffer
        , "UintP", Len)

    Loop, % Len//2    
        Output .= Chr(NumGet(Buffer, A_Index-1, "Char"))

    return !Output ? DisplayName : Output
}

Easy WinAPI - Dive into Windows API World
Benchmark your AutoHotkey skills at PlayAHK.com

BoBo²
  • Guests
  • Last active:
  • Joined: --
Kinda coincidence! Desperately searched for something like this a few days ago!!
Thx mate :D

  • Guests
  • Last active:
  • Joined: --
<!-- m -->http://www.autohotke...topic16758.html<!-- m -->
<!-- m -->http://www.autohotke...topic21975.html<!-- m -->

heresy
  • Members
  • 291 posts
  • Last active: Sep 26 2008 10:47 PM
  • Joined: 11 Mar 2008
@ BoBo
glad it helped you!

@ Guest
i've already noticed those functions and that's why i've managed this function set. there was no service_list/add/delete etc(incoming).
Easy WinAPI - Dive into Windows API World
Benchmark your AutoHotkey skills at PlayAHK.com

Chavez
  • Members
  • 256 posts
  • Last active: Oct 13 2009 01:27 PM
  • Joined: 20 Aug 2008
This is EXACTLY what i needed. I'm implementing an application on my work and i needed it to run both logged- and not logged in.

However, i have a small problem with it. I tried making it an automatic service, but it simply adds it as a manual one. And the second problem is when i start it, it will start my application, which is good (note: the application is working entirely, no problems at all), but in the Windows Management Console it keeps saying 'starting...', after a small while it just closes my application again, stating that it didn't reply/crashed.

Is it possibly because i have a loop in my application?
-Chavez.

Chavez
  • Members
  • 256 posts
  • Last active: Oct 13 2009 01:27 PM
  • Joined: 20 Aug 2008
Thanks for the help everyone, I'll keep this in mind :x
-Chavez.

poo_noo
  • Members
  • 251 posts
  • Last active: Jan 28 2015 08:33 PM
  • Joined: 08 Dec 2006
Chavez
maybe this ? http://www.bitsum.co...php#makeservice
Paul O

Chavez
  • Members
  • 256 posts
  • Last active: Oct 13 2009 01:27 PM
  • Joined: 20 Aug 2008

Chavez
maybe this ? http://www.bitsum.co...php#makeservice


Not only is this "REMOVED due to abuse by malware authors", but it will neither help me because i have to install it in the entire company. I have made an in- and uninstaller, the program itself, and that's all i actually needed. The major problem still is that Windows does not see that the service has started successfully and still closes it automatically.
-Chavez.

shajul
  • Members
  • 571 posts
  • Last active: Aug 01 2015 03:45 PM
  • Joined: 15 Sep 2006
thanks

shajul
  • Members
  • 571 posts
  • Last active: Aug 01 2015 03:45 PM
  • Joined: 15 Sep 2006
Calling service_stop more than once via loop of service names crashes the script..
Any help is appreciated.

pdhawan
  • Members
  • 4 posts
  • Last active: Jul 28 2007 01:16 AM
  • Joined: 27 Jul 2006
thanks for making this.

I am having some difficulty. I can query the service status as to running or not. However, when I do a service start or stop, nothing happens.

Here is a sample of what I am doing.

MsgBox % Service_State("Livescribe Smartpen Service") ; this returns 4
ServiceName := _GetName_("Livescribe Smartpen Service") ; this returns PenCommService
MsgBox % Service_Stop("Livescribe Smartpen Service") ; this returns -4
MsgBox % Service_State("Livescribe Smartpen Service") ; this returns 4
MsgBox % Service_Start("Livescribe Smartpen Service") ; this returns -4
MsgBox % Service_State("Livescribe Smartpen Service") ; this returns 4

Any help is appreciated. I am running on Windows Vista Home Premium.

itaam
  • Guests
  • Last active:
  • Joined: --
Am I doing something wrong or the script doesn't run in Win7 64?

Ferry
  • Members
  • 37 posts
  • Last active: Mar 21 2014 10:12 AM
  • Joined: 18 May 2008

This is EXACTLY what i needed. I'm implementing an application on my work and i needed it to run both logged- and not logged in.

However, i have a small problem with it. I tried making it an automatic service, but it simply adds it as a manual one. And the second problem is when i start it, it will start my application, which is good (note: the application is working entirely, no problems at all), but in the Windows Management Console it keeps saying 'starting...', after a small while it just closes my application again, stating that it didn't reply/crashed.

Is it possibly because i have a loop in my application?


Unfortunatly it is not possible to start any (normal) executable as a windows service. For an executable to start as a service the executable needs to communicate with the Service Control Manager. However, a user named JHa already did this (more or less) as you can see in this topic: http://www.autohotke...ervice schandle

With this knowledge i created the following script as a Service startup script for starting and stopping any normal executable like (for example) Notepad.exe as a Windows Service.

Please be careful using this script and compile this only using AutoHotkey_L Unicode. Credits go to JHa.

/*

Script:	AHK Service
Author:	Ferry van Gelderen
Date:	12-5-2011

http://msdn.microsoft.com/en-us/library/bb540474%28VS.85%29.aspx

-i Computername* <- Install service
-r Computername* <- Start service
-s Computername* <- Stop service
-d Computername* <- Delete service

*Optional

Compile this script with AutoHotkey_L 32-bit or 64-bit Unicode

*/

#NoEnv
#SingleInstance Ignore
#Persistent
#NoTrayIcon

SendMode Input
SetWorkingDir %A_ScriptDir%
SetBatchLines -1

Version = 1.0
StartProgram = Notepad.exe						; Notepad.exe is used as an example for checking this using windows taskmanager. Enter any normal executable to start as a windows service

SERVICE_AUTO_START = 0x00000002
SERVICE_BOOT_START = 0x00000000
SERVICE_DEMAND_START = 0x00000003
SERVICE_DISABLED = 0x00000004
SERVICE_SYSTEM_START = 0x00000001

SERVICE_ERROR_CRITICAL = 0x00000003
SERVICE_ERROR_IGNORE = 0x00000000
SERVICE_ERROR_NORMAL = 0x00000001
SERVICE_ERROR_SEVERE = 0x00000002

SERVICE_CONTROL_CONTINUE = 0x00000003
SERVICE_CONTROL_INTERROGATE = 0x00000004
SERVICE_CONTROL_NETBINDADD = 0x00000007
SERVICE_CONTROL_NETBINDDISABLE = 0x0000000A
SERVICE_CONTROL_NETBINDENABLE = 0x00000009
SERVICE_CONTROL_NETBINDREMOVE = 0x00000008
SERVICE_CONTROL_PARAMCHANGE = 0x00000006
SERVICE_CONTROL_PAUSE = 0x00000002
SERVICE_CONTROL_STOP = 0x00000001

SERVICE_STOPPED = 0x00000001
SERVICE_START_PENDING = 0x00000002
SERVICE_STOP_PENDING = 0x00000003
SERVICE_RUNNING = 0x00000004
SERVICE_CONTINUE_PENDING = 0x00000005
SERVICE_PAUSE_PENDING = 0x00000006
SERVICE_PAUSED = 0x00000007
SERVICE_ACTIVE = 0x00000001
SERVICE_INACTIVE = 0x00000002
SERVICE_STATE_ALL = 0x00000003

SERVICE_ACCEPT_STOP = 0x00000001
SERVICE_ACCEPT_PAUSE_CONTINUE = 0x00000002
SERVICE_ACCEPT_SHUTDOWN = 0x00000004
SERVICE_ACCEPT_PARAMCHANGE = 0x00000008
SERVICE_ACCEPT_NETBINDCHANGE = 0x00000010
SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020
SERVICE_ACCEPT_POWEREVENT = 0x00000040
SERVICE_ACCEPT_SESSIONCHANGE = 0x00000080
SERVICE_ACCEPT_PRESHUTDOWN = 0x00000100

SERVICE_ADAPTER = 0x00000004
SERVICE_FILE_SYSTEM_DRIVER = 0x00000002
SERVICE_KERNEL_DRIVER = 0x00000001
SERVICE_RECOGNIZER_DRIVER = 0x00000008
SERVICE_WIN32_OWN_PROCESS = 0x00000010
SERVICE_WIN32_SHARE_PROCESS = 0x00000020

SERVICE_ALL_ACCESS = 0xF01FF
SERVICE_INTERROGATE = 0x0080
SERVICE_PAUSE_CONTINUE = 0x0040
SERVICE_QUERY_CONFIG = 0x0001
SERVICE_QUERY_STATUS = 0x0004
SERVICE_START = 0x0010
SERVICE_STOP = 0x0020

SERVICE_CONFIG_DESCRIPTION = 1
NO_ERROR = 0x0

SSP =
DesAccess = 0x2
DesiredAccess = 0xF003F
ServiceType := SERVICE_WIN32_OWN_PROCESS			; Change service type
StartType := SERVICE_AUTO_START						; Change service start type 
ErrorControl := SERVICE_ERROR_IGNORE
LoadOrderGroup =
TagId =
Dependencies =
ServiceStartName = 0								; Use 0 for service run as Local System
Password =											; Leave empty for service run as Local System

Description = AutoHotkey Service					; Change the service description
db_Name = AHK_Service								; Change the sevice name
Display_Name = AutoHotkey Service					; Change the service display name

StringTrimRight, s_NameValue, A_ScriptName, 4
p_NameValue = %A_WinDir%\%s_NameValue%.exe run		; Change the service location

If A_IsCompiled <> 1
	{
	MsgBox, Program is not compiled!
	ExitApp
	}

LinePar = %1%
m_Name = %2%

; ------------------------------------------------------------< Install Service >------------------------------------------------------------ 
If LinePar = -i
	{
	Open_SCManager(m_Name, db_Name, DesAccess)
	If Open_Service(sc_Handle, s_NameValue, SERVICE_INTERROGATE)
		ExitApp
	Else
		{
		Create_Service(sc_Handle, s_NameValue, Display_Name, DesiredAccess, ServiceType, StartType, ErrorControl, p_NameValue, LoadOrderGroup, TagId, Dependencies, ServiceStartName, Password)
		Description_Service(s_Handle, Description)
		Close_Service(sc_Handle, s_Handle)
		ExitApp
		}
	}

; ------------------------------------------------------------< Start Service >------------------------------------------------------------ 
If LinePar = -r
	{
	Open_SCManager(m_Name, db_Name, DesAccess)
	Open_Service(sc_Handle, s_NameValue, SERVICE_START)
	Start_Service(s_Handle)
	Close_Service(sc_Handle, s_Handle)
	ExitApp
	}

; ------------------------------------------------------------< Stop Service >------------------------------------------------------------ 
If LinePar = -s
	{
	Open_SCManager(m_Name, db_Name, DesAccess)
	Open_Service(sc_Handle, s_NameValue, SERVICE_STOP)
	Stop_Service(s_Handle)
	Close_Service(sc_Handle, s_Handle)
	ExitApp
	}

; ------------------------------------------------------------< Delete Service >------------------------------------------------------------ 
If LinePar = -d
	{
	Open_SCManager(m_Name, db_Name, DesAccess)
	Open_Service(sc_Handle, s_NameValue, SERVICE_ALL_ACCESS)
	Delete_Service(s_Handle)
	Close_Service(sc_Handle, s_Handle)	
	ExitApp
	}

; ------------------------------------------------------------< Run as Service >------------------------------------------------------------ 
If LinePar = run
	{
	VarSetCapacity(DispatchTable, 16, 0)		; Use for 32-bit Unicode compiler 
;	VarSetCapacity(DispatchTable, 32, 0)		; Use for 64-bit Unicode compiler
	SvcMainAddress := RegisterCallback("SvcMain")
	NumPut(&s_NameValue, DispatchTable, 0)
	NumPut(SvcMainAddress, DispatchTable, 4) 	; Use for 32-bit Unicode compiler
;	NumPut(SvcMainAddress, DispatchTable, 8)	; Use for 64-bit Unicode compiler
	cResult := DllCall("Advapi32\StartServiceCtrlDispatcher"
				, "UInt", &DispatchTable)
	KillResult := DllCall("User32.dll\KillTimer"
				, "UInt", 0
				, "UInt", UINT_PTR)
	ExitApp
	}

MsgBox, 64, %Description% %Version%, Usage %Description%:`n`n%s_NameValue%.exe -i Computername* `t <- Install service`n%s_NameValue%.exe -r Computername* `t <- Start service`n%s_NameValue%.exe -s Computername* `t <- Stop service`n%s_NameValue%.exe -d Computername* `t <- Delete service`n`n*Computername is optional.`n`nMake sure the file %A_WinDir%\%s_NameValue%.exe exists in on the (remote) machine running this service.
ExitApp

;-------------------------------------------------------------------------------------------------------------------------------------------------

SvcMain(dwArgc = 0, lpszArgv = 0)
	{
	Global
	Critical
	SvcCtrlHandlerAddress := RegisterCallback("SvcCtrlHandler")
	SvcStatusHandle := DllCall("Advapi32\RegisterServiceCtrlHandler"
				, "Str", s_NameValue
				, "UInt", SvcCtrlHandlerAddress)
	NumPut(SERVICE_WIN32_OWN_PROCESS, SvcStatus, 0)
	NumPut(0, SvcStatus, 16)
	ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000)
	hSvcStopEvent := DllCall("CreateEvent"
				, "UInt", 0   
				, "UInt", TRUE
				, "UInt", FALSE 
				, "UInt", 0)   
	If hSvcStopEvent = 0
		{
		ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0)
		Return
		}
    ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0)
	ProgAddr := RegisterCallback("UserProg")
	UINT_PTR := DllCall("User32.dll\SetTimer"
				, "UInt", 0
				, "UInt", Timer_1
				, "UInt", 1000					; Change timer in ms
				, "UInt", ProgAddr)
	Sleep, 1000 								; Sleep is needed to activate timer (UserProg)
	cResult := DllCall("WaitForSingleObject"
				, "UInt", hSvcStopEvent
				, "UInt", -1)
	ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0)
	Return   
	}

UserProg()
	{
	Global
	Critical
	Process, Exist, %StartProgram%
	If ErrorLevel = 0
		Run, %StartProgram%
	Return
	}

ReportSvcStatus(CurrentState, Win32ExitCode, WaitHint)
	{
	Global
	Static CheckPoint = 1
	NumPut(CurrentState, SvcStatus, 4)
	NumPut(Win32ExitCode, SvcStatus, 12)
	NumPut(WaitHint, SvcStatus, 24)
	If (CurrentState = SERVICE_START_PENDING)
		NumPut(0, SvcStatus, 8)
	Else
		NumPut(SERVICE_ACCEPT_STOP, SvcStatus, 8)
	If (CurrentState = SERVICE_RUNNING Or CurrentState = SERVICE_STOPPED)
		NumPut(0, SvcStatus, 20)
	Else
		NumPut(NumGet(SvcStatus, 20)+1, SvcStatus, 20)
	cResult := DllCall("Advapi32\SetServiceStatus"
				, "UInt", SvcStatusHandle
				, "UInt", &SvcStatus)
	CurState := NumGet(SvcStatus, 4)
	Return
	}

SvcCtrlHandler(dwCtrl)
	{
	Global
	Critical
	If (dwCtrl = SERVICE_CONTROL_STOP)
		{ 
		ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0)       
		CurrentState := NumGet(SvcStatus, 4)
		cResult := DllCall("SetEvent"
				, "UInt", hSvcStopEvent)
		ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0)
		Return
	    }   
	Return
	}

SvcReportEvent(ByRef szFunction)
	{
	Global
	hEventSource = DllCall("Advapi32/RegisterEventSource"
				, "UInt", 0
				, "Str", s_Name)
	If hEventSource <> 0
		{
		DllCall("Advapi32/ReportEvent"
				, "UInt", hEventSource
				, "UInt", EVENTLOG_ERROR_TYPE
				, "UInt", 0
				, "UInt", SVC_ERROR
				, "UInt", NULL
				, "UInt", 2
				, "UInt", 0
				, "UInt", lpszStrings
				, "UInt", NULL)
		DllCall("Advapi32/DeregisterEventSource"
				, "UInt", hEventSource)
	    }
	Return
	}

Open_SCManager(m_Name, db_Name, DesAccess)
	{
	Global sc_Handle
	sc_Handle := DllCall("Advapi32\OpenSCManager"
				,"Str", m_Name
				,"UInt", db_Name
				,"Uint", DesAccess)
	Return sc_Handle
	}

Create_Service(sc_Handle, s_Name, d_Name, DesiredAccess, ServiceType, StartType, ErrorControl, p_Name, LoadOrderGroup = 0, TagId = 0, Dependencies = "", ServiceStartName = 0, Password = "")
	{
	Global s_Handle
	s_Handle := DllCall("Advapi32\CreateService"
				,"UInt", sc_Handle
				,"Str", s_Name
				,"Str", d_Name
				,"UInt", DesiredAccess
				,"Uint", ServiceType
				,"UInt", StartType
				,"UInt", ErrorControl
				,"Str", p_Name
				,"UInt", LoadOrderGroup
				,"UInt", TagId
				,"Str", Dependencies
				,"UInt", ServiceStartName
				,"Str", Password)
	Return s_Handle
	}

Start_Service(s_Handle)
	{
	Global
	cResult := DllCall("Advapi32\StartService"
				, "Uint", s_Handle
				, "Uint", 0
				, "Str", "")
	Return cResult
	}

Stop_Service(s_Handle)
	{
	Global
	VarSetCapacity(@SSP, 36)
	cResult := DllCall("Advapi32\ControlService"
				, "Uint", s_Handle
				, "Uint", 0x1
				, "Uint", [email protected]) 
	Return cResult
	}

Delete_Service(s_Handle)
	{
	Global
	cResult := DllCall("Advapi32\DeleteService"
				, "Uint", s_Handle)
	Return cResult
	}

Description_Service(s_Handle, Description)
	{
	Global
	cResult := DllCall("Advapi32\ChangeServiceConfig2"
				, "UInt", s_Handle
				, "UInt", 1               
				, "Str*", Description)
	Return cResult
	}

Open_Service(sc_Handle, s_NameValue, DesAccess)
	{
	Global
	s_Handle := DllCall("Advapi32\OpenService"
				, "UInt", sc_Handle
				, "Str", s_NameValue
				, "UInt", DesAccess )
	Return s_Handle
	}
	
Close_Service(sc_Handle, s_Handle)
	{
	DllCall("Advapi32\CloseServiceHandle"
				, "Uint", s_Handle)
	DllCall("Advapi32\CloseServiceHandle"
				, "Uint", sc_Handle)
	Return
	}

It is possible to compile this script as 64-bit Unicode but you need to adjust 2 lines (see remarks in script). If you do not want to use this script you can also use a free program like ServiceEx.

I hope this will help you.

SoggyDog
  • Members
  • 803 posts
  • Last active: Mar 04 2013 06:27 AM
  • Joined: 02 May 2006

If you do not want to use this script you can also use a free program like ServiceEx.

Agreed;
ServiceEx works like a charm.

twiz
  • Members
  • 33 posts
  • Last active: Oct 08 2013 11:47 PM
  • Joined: 08 Nov 2011
For some reason the Service_Stop() function only stops a function once per script run. After the first run, it would not stop the service, and the returned result would be blank.
I asked about this in the #AHK IRC channel, and BamBam4275 took a look at it and fixed it up. Thanks again, BamBam4275! :)


Service_Stop() Function fixed by BamBam4275:
Service_Stop(ServiceName)
{
    ServiceName := _GetName_(ServiceName)

    SCM_HANDLE := DllCall("advapi32\OpenSCManagerA"
                        , "Int", 0 ;NULL for local
                        , "Int", 0
                        , "UInt", 0x1) ;SC_MANAGER_CONNECT (0x0001)

    if !(SC_HANDLE := DllCall("advapi32\OpenServiceA"
                            , "UInt", SCM_HANDLE
                            , "Str", ServiceName
                            , "UInt", 0x20)) ;SERVICE_STOP (0x0020)
        result := -4 ;Service Not Found

    VarSetCapacity(SC_STATUS, 28, 0)
    if !result
        result := DllCall("advapi32\ControlService"
                        , "UInt", SC_HANDLE
                        , "Int", 1
                        , "UInt", &SC_STATUS)

    DllCall("advapi32\CloseServiceHandle", "UInt", SC_HANDLE)
    DllCall("advapi32\CloseServiceHandle", "UInt", SCM_HANDLE)
    return result
}
Whole script:
/* Windows Service Control Functions
-heresy | Fixed by BamBam4275
http://www.autohotkey.com/forum/topic34984.html

- Return Values
     1 : Success
     0 : Failure
    -4 : Service Not Found

- State codes from Service_State()
    SERVICE_STOPPED (1) : The service is not running.
    SERVICE_START_PENDING (2) : The service is starting.
    SERVICE_STOP_PENDING (3) : The service is stopping.
    SERVICE_RUNNING (4) : The service is running.
    SERVICE_CONTINUE_PENDING (5) : The service continue is pending.
    SERVICE_PAUSE_PENDING (6) : The service pause is pending.
    SERVICE_PAUSED (7) : The service is paused.
*/

Service_List(State="", Type="", delimiter="`n"){
    if !State
        ServiceState := 0x3 ;SERVICE_STATE_ALL (0x00000003)
    else if (State="Active")
        ServiceState := 0x1 ;SERVICE_ACTIVE (0x00000001)
    else if (State="Inactive")
        ServiceState := 0x2 ;SERVICE_INACTIVE (0x00000002)
    else
        ServiceState := 0x3

    if !Type
        ServiceType := 0x30 ;SERVICE_WIN32 (0x00000030)
    else if (Type="Driver")
        ServiceType := 0xB ;SERVICE_DRIVER (0x0000000B)
    else if (Type="All")
        ServiceType := 0x3B ;sum of both
    else
        ServiceType := 0x30

    SCM_HANDLE := DllCall("advapi32\OpenSCManagerA"
                        , "Int", 0
                        , "Int", 0
                        , "UInt", 0x4) ;SC_MANAGER_ENUMERATE_SERVICE (0x0004)

    DllCall("advapi32\EnumServicesStatusA"
        , "UInt", SCM_HANDLE
        , "UInt", ServiceType
        , "UInt", ServiceState
        , "UInt", 0
        , "UInt", 0
        , "UIntP", bSize ;get required buffer size first
        , "UIntP", 0
        , "UIntP", 0)

    VarSetCapacity(ENUM_SERVICE_STATUS, bSize, 0) ;prepare struct

    DllCall("advapi32\EnumServicesStatusA" ;actual enumeration
        , "UInt", SCM_HANDLE
        , "UInt", ServiceType
        , "UInt", ServiceState
        , "UInt", &ENUM_SERVICE_STATUS
        , "UInt", bSize
        , "UIntP", 0
        , "UIntP", ServiceCount
        , "UIntP", 0)

    Loop, %ServiceCount%
        result .= DllCall("MulDiv"
                        , "Int", NumGet(ENUM_SERVICE_STATUS, (A_Index-1)*36+4)
                        , "Int", 1
                        , "Int", 1, "str") . delimiter

    DllCall("advapi32\CloseServiceHandle", "UInt", SCM_HANDLE)
    Return result

}

Service_Start(ServiceName)
{
    ServiceName := _GetName_(ServiceName)

    SCM_HANDLE := DllCall("advapi32\OpenSCManagerA"
                        , "Int", 0 ;NULL for local
                        , "Int", 0
                        , "UInt", 0x1) ;SC_MANAGER_CONNECT (0x0001)

    if !(SC_HANDLE := DllCall("advapi32\OpenServiceA"
                            , "UInt", SCM_HANDLE
                            , "Str", ServiceName
                            , "UInt", 0x10)) ;SERVICE_START (0x0010)
        result := -4 ;Service Not Found

    if !result
        result := DllCall("advapi32\StartServiceA"
                        , "UInt", SC_HANDLE
                        , "Int", 0
                        , "Int", 0)

    DllCall("advapi32\CloseServiceHandle", "UInt", SC_HANDLE)
    DllCall("advapi32\CloseServiceHandle", "UInt", SCM_HANDLE)
    return result
}

Service_Stop(ServiceName)
{
    ServiceName := _GetName_(ServiceName)

    SCM_HANDLE := DllCall("advapi32\OpenSCManagerA"
                        , "Int", 0 ;NULL for local
                        , "Int", 0
                        , "UInt", 0x1) ;SC_MANAGER_CONNECT (0x0001)

    if !(SC_HANDLE := DllCall("advapi32\OpenServiceA"
                            , "UInt", SCM_HANDLE
                            , "Str", ServiceName
                            , "UInt", 0x20)) ;SERVICE_STOP (0x0020)
        result := -4 ;Service Not Found

    VarSetCapacity(SC_STATUS, 28, 0)
    if !result
        result := DllCall("advapi32\ControlService"
                        , "UInt", SC_HANDLE
                        , "Int", 1
                        , "UInt", &SC_STATUS)

    DllCall("advapi32\CloseServiceHandle", "UInt", SC_HANDLE)
    DllCall("advapi32\CloseServiceHandle", "UInt", SCM_HANDLE)
    return result
}

Service_State(ServiceName)
{ ; Return Values
; SERVICE_STOPPED (1) : The service is not running.
; SERVICE_START_PENDING (2) : The service is starting.
; SERVICE_STOP_PENDING (3) : The service is stopping.
; SERVICE_RUNNING (4) : The service is running.
; SERVICE_CONTINUE_PENDING (5) : The service continue is pending.
; SERVICE_PAUSE_PENDING (6) : The service pause is pending.
; SERVICE_PAUSED (7) : The service is paused.
    ServiceName := _GetName_(ServiceName)

    SCM_HANDLE := DllCall("advapi32\OpenSCManagerA"
                        , "Int", 0 ;NULL for local
                        , "Int", 0
                        , "UInt", 0x1) ;SC_MANAGER_CONNECT (0x0001)

    if !(SC_HANDLE := DllCall("advapi32\OpenServiceA"
                            , "UInt", SCM_HANDLE
                            , "Str", ServiceName
                            , "UInt", 0x4)) ;SERVICE_QUERY_STATUS (0x0004)
        result := -4 ;Service Not Found

    VarSetCapacity(SC_STATUS, 28, 0) ;SERVICE_STATUS Struct

    if !result
        result := !DllCall("advapi32\QueryServiceStatus"
                         , "UInt", SC_HANDLE
                         , "UInt", &SC_STATUS)
                         ? False : NumGet(SC_STATUS, 4) ;-1 or dwCurrentState

    DllCall("advapi32\CloseServiceHandle", "UInt", SC_HANDLE)
    DllCall("advapi32\CloseServiceHandle", "UInt", SCM_HANDLE)
    return result
}

Service_Add(ServiceName, BinaryPath, StartType=""){
    if !A_IsAdmin
        Return False

    SCM_HANDLE := DllCall("advapi32\OpenSCManagerA"
                        , "Int", 0
                        , "Int", 0
                        , "UInt", 0x2) ;SC_MANAGER_CREATE_SERVICE (0x0002)

    StartType := !StartType ? 0x3 : 0x2
    ;SERVICE_DEMAND_START(0x00000003) vs SERVICE_AUTO_START(0x00000002)

    SC_HANDLE := DllCall("advapi32\CreateServiceA"
                   , "UInt", SCM_HANDLE
                   , "Str", ServiceName
                   , "Str", ServiceName
                   , "UInt", 0xF01FF ;SERVICE_ALL_ACCESS (0xF01FF)
                   , "UInt", 0x110 ;SERVICE_WIN32_OWN_PROCESS(0x00000010) | SERVICE_INTERACTIVE_PROCESS(0x00000100)
    ;interactable service with desktop (requires local account)
    ;http://msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx
                   , "UInt", StartType
                   , "UInt", 0x1 ;SERVICE_ERROR_NORMAL(0x00000001)
                   , "Str", BinaryPath
                   , "Str", "" ;No Group
                   , "UInt", 0 ;No TagId
                   , "Str", "" ;No Dependencies
                   , "Int", 0 ;Use LocalSystem Account
                   , "Str", "")
    result := A_LastError ? SC_HANDLE "," A_LastError : 1
    DllCall("advapi32\CloseServiceHandle", "UInt", SC_HANDLE)
    DllCall("advapi32\CloseServiceHandle", "UInt", SCM_HANDLE)
    Return result
}

Service_Delete(ServiceName)
{
    if !A_IsAdmin ;Requires Administrator rights
        Return False
    ServiceName := _GetName_(ServiceName)

    SCM_HANDLE := DllCall("advapi32\OpenSCManagerA"
                        , "Int", 0 ;NULL for local
                        , "Int", 0
                        , "UInt", 0x1) ;SC_MANAGER_CONNECT (0x0001)

    if !(SC_HANDLE := DllCall("advapi32\OpenServiceA"
                            , "UInt", SCM_HANDLE
                            , "Str", ServiceName
                            , "UInt", 0xF01FF)) ;SERVICE_ALL_ACCESS (0xF01FF)
        result := -4 ;Service Not Found

    if !result
        result := DllCall("advapi32\DeleteService", "Uint", SC_HANDLE)

    DllCall("advapi32\CloseServiceHandle", "UInt", SC_HANDLE)
    Return result
}

_GetName_(DisplayName)
{ ;Internal, Gets Service Name from Display Name,
    SCM_HANDLE := DllCall("advapi32\OpenSCManagerA", "Int", 0, "Int", 0, "UInt", 0x1) ;SC_MANAGER_CONNECT (0x0001)

    DllCall("advapi32\GetServiceKeyNameA" ;Get Buffer Size
            , "Uint", SCM_HANDLE
            , "Str", DisplayName
            , "Int", 0
            , "UintP", Len)

    VarSetCapacity(Buffer, Len) ;Prepare Buffer

    DllCall("advapi32\GetServiceKeyNameA" ;Get Actual Service Name
        , "Uint", SCM_HANDLE
        , "Str", DisplayName
        , "Uint", &Buffer
        , "UintP", Len)

    Loop, % Len//2
        Output .= Chr(NumGet(Buffer, A_Index-1, "Char"))

    return !Output ? DisplayName : Output
}