Jump to content


Photo

[WinServ] Start, Stop or Query a windows service (WinAPI)


  • Please log in to reply
18 replies to this topic

#1 Hardeep

Hardeep
  • Members
  • 87 posts

Posted 11 August 2007 - 04:40 PM

WinServ function can be used to start, stop or query(running status) a windows service on local or a remote computer. Dialogs provide visual feedback when starting/stopping a service or when an error occurs. Usage documentation is included in the library.

Download WinServ.ahk v1.0 (This file can be directly copied to the library.)

Posted Image

Example Usage:
Caution: Executing the following code will start/stop the specified services on your system.

;Start the Task Scheduler service by using its Service Name
WinServ("Schedule", True) ;Returns True if started successfully.

;Stop the Task Scheduler service by using its Display Name
WinServ("Task Scheduler", False) ;Returns True if stopped successfully.

;Start the Windows Time service silently
WinServ("Windows time", True, True) ;No popups

;Start the Task Scheduler service on remote computer name ZOMBIE
WinServ("Schedule", True, False, "ZOMBIE") ;Returns True if started successfully.

;Check if the WebClient service is running
If WinServ("WebClient")
{	MsgBox, WebClient is up & running
	;Do Something
}

;Toggle the DNS Client service
WinServ("DNS Client", WinServ("DNS Client") ? False : True)


#2 n-l-i-d

n-l-i-d
  • Guests

Posted 11 August 2007 - 10:22 PM

Very nice! 8)

#3 corrupt

corrupt
  • Members
  • 2558 posts

Posted 12 August 2007 - 02:52 AM

Cool 8) . Thanks :)

#4 Hardeep

Hardeep
  • Members
  • 87 posts

Posted 12 August 2007 - 08:00 PM

Thanks guys! Any feedback is highly appreciated.

Will share some more useful functions soon...

#5 PhiLho

PhiLho
  • Fellows
  • 6850 posts

Posted 11 September 2007 - 12:37 PM

I really appreciated this function!
I come back from holidays, my boss ask me to automatically install a Tomcat Java application, which needs to stop and start the Apache Tomcat service.
I search the forum... and here is your script!
Very handy.

The only problem is that you use the Progress command unconditionally, just to display some messages. It ruins my larger script which has a global progress bar (do this, start service, do that).
I suggest to use a GUI instead: more work, but it would better fit as function.

#6 Hardeep

Hardeep
  • Members
  • 87 posts

Posted 12 September 2007 - 06:34 PM

The only problem is that you use the Progress command unconditionally, just to display some messages. It ruins my larger script which has a global progress bar (do this, start service, do that).
I suggest to use a GUI instead: more work, but it would better fit as function.


Thanks for bringing it to my notice. I have changed the Progress command to use 10 (max value) as the window number. I hope this will help avoid any progress window conflicts since I highly doubt a user would be displaying 10 progress windows at the same time.

I completely agree that using a GUI for this purpose would be more elegant and will implement it when I get time...right now I am too busy with my work.

#7 WhoAmIAgain?

WhoAmIAgain?
  • Guests

Posted 14 March 2009 - 07:56 PM

Thanks for this function, I have a antivirus that may work great but it uses 3 processes and a good chunk of my memory. Using this function I made a quick .exe that turns on everything it needs to run, or in 1 click jump through all the hoops it takes to disable the thing.


Why does Avira demand a 10 MB process just to check for updates once a day? *shakes his head*

#8 Gauss

Gauss
  • Members
  • 203 posts

Posted 23 December 2009 - 05:46 PM

Thanks Hardeep
Very useful, is it possible to set the service status to disabled and manual too?

Edit:

I found it out
run, sc config Service_Name start= demand
run, net start Service_Name

* auto--a service automatically started at boot time, even if no user logs on
* boot--a device driver loaded by the boot loader
* demand--a service that must be manually started (the default)
* disabled--a service that can't be started
* system--a service started during kernel initialization



The only thing is that it displays command prompt window, any idea how to do the same without having to see that window?

#9 jasonwills

jasonwills
  • Guests

Posted 04 February 2010 - 11:20 PM

This is a great function - thankyou for it.

i have used the following code:

^!I::
If WinServ("ServiceName")
{
WinServ("ServiceName", False, True)
}
Else
{
WinServ("ServiceName", True, True)
}

this works great - however, i would like at the press of Ctrl + Alt+ I to toggle multiple services not just "ServiceName" anyone know of an easy way of doing this, thanks for any help in advance.

Jason

#10 Deep-Silence

Deep-Silence
  • Members
  • 87 posts

Posted 10 February 2010 - 09:14 PM

Try this code to hide the commandline window

Run, %comspec% /c "net start Service_Name",, Hide

Or 

RunWait, %comspec% /c "net start Service_Name",, Hide




Thanks Hardeep
Very useful, is it possible to set the service status to disabled and manual too?

Edit:

I found it out

run, sc config Service_Name start= demand
run, net start Service_Name

* auto--a service automatically started at boot time, even if no user logs on
* boot--a device driver loaded by the boot loader
* demand--a service that must be manually started (the default)
* disabled--a service that can't be started
* system--a service started during kernel initialization



The only thing is that it displays command prompt window, any idea how to do the same without having to see that window?



#11 Deep-Silence

Deep-Silence
  • Members
  • 87 posts

Posted 11 February 2010 - 12:57 PM

Thanks guys! Any feedback is highly appreciated.

Will share some more useful functions soon...



Thanks for your nice function.
Would be nice if you could add some code to config the services.

run, sc config Service_Name start= demand


Thanks, Deep-Silence

#12 Aero98

Aero98
  • Members
  • 112 posts

Posted 25 August 2010 - 02:33 PM

I use this code a lot for stopping and starting our SQL service for some automated backup routines, works 100% no errors, love it. Thanks for sharing.

#13 hmlnarik

hmlnarik
  • Guests

Posted 17 October 2010 - 11:44 AM

Thanks a lot for the code which I found very useful!

When using 64-bit version of AutoHotKey, it unfortunatelly does not work. There are two issues: 64-bit AHK seems to use wide-strings internally so all ANSI DLL calls should be replaced by their wide equivalents. Further, the original script counts on getting values via NumGet that by default works with 32-bit values. 64-bit version of AHK however works with 64-bit numbers thus it spoils result codes, hence result type must be specified explicitly in NumGet calls.

Here is my fix, feel free to use it if you find it handy.

/* WinServ.ahk
Version			: 1.0-x64
Author			: Hardeep Singh <http://swankyleo.googlepages.com> (modification for 64-bit version by Hynek Mlnarik)
Forum Topic	: http://www.autohotkey.com/forum/viewtopic.php?t=21975
License			: You may use this code freely and without any restriction. If you find it useful, do post your feedback at the
					  above mentioned forum topic.
===============================================================================
Function			: WinServ
Description	: This function can be used to start, stop or query(running status) a windows service on local or a remote
					  computer. Dialogs provide visual feedback when starting/stopping a service or when an error occurs.

~PARAMETERS~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ServiceName	: Specify either the Service Name or the Display Name of the service.

Task				: (Optional) Specify one of the following:
					  True - Starts the service (Returns True if service is started successfully).
					  False - Stops the service (Returns True if service is stopped successfully).
					  NULL(Default) - Query service status (Returns True if service is running).

Silent			: (Optional) Specify one of the following:
					  False(Default) - Show popup dialog for the task being performed or when an error occurs.
					  True - Suppress all popup dialogs including error messages.

Computer		: (Optional) Connect to the service control manager on the specified computer.
					  NULL(Default) - Connect to the service control manager on the local computer.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Return Value	: Returns TRUE or FALSE depending on the task performed.
Notes			: Starting a service which is dependent on other services will also start those services, if not already running.
					  Stopping a service which is dependent on other services will not stop those services.
===============================================================================
*/

WinServ(ServiceName, Task="", Silent=False, Computer="")
{	Global schSCManager, schService
	Static SERVICE_QUERY_STATUS=0x4, SERVICE_START=0x10, SERVICE_STOP=0x20, SC_STATUS_PROCESS_INFO=0, SERVICE_CONTROL_STOP=0x1
	Static SERVICE_STOPPED=0x1, SERVICE_START_PENDING=0x2, SERVICE_STOP_PENDING=0x3, SERVICE_RUNNING=0x4
	VarSetCapacity(@SSP, 36), VarSetCapacity(BytesNeeded, 4), VarSetCapacity(SvcName ,256)

	If Task not in ,0,1
		Return WinServ_ErrMsg("Parameters", ServiceName, Task, False, ErrorLevel:="Invalid Task specified!")
	If !schSCManager := DllCall("Advapi32\OpenSCManagerW", "Str", Computer, "Uint", 0, "Uint", 0)
		Return WinServ_ErrMsg("OpenSCManager", ServiceName, Task, Silent)
	ServiceName := DllCall("Advapi32\GetServiceKeyNameW", "Uint", schSCManager, "Uint", &ServiceName, "Str", SvcName, "UintP", 256) ? SvcName : ServiceName
	If ErrorLevel
		Return WinServ_ErrMsg("GetServiceKeyName", ServiceName, Task, Silent)

	If !schService := DllCall("Advapi32\OpenServiceW", "Uint", schSCManager, "Uint", &ServiceName, "Uint", SERVICE_QUERY_STATUS|SERVICE_START|SERVICE_STOP)
		Return WinServ_ErrMsg("OpenService", ServiceName, Task, Silent)
	ServiceName := DllCall("Advapi32\GetServiceDisplayNameW", "Uint", schSCManager, "Uint", &ServiceName, "Str", SvcName, "UintP", 256) ? SvcName : ServiceName

	Progress, % Task = "" || Silent ? "10:Off" : "10:ZH0 FM10 FS10 B2 H65 W200 ZX2 ZY5", %ServiceName%, % Task ? "Starting service..." : "Stopping service..."
	If (Task = True)
	{	If !DllCall("Advapi32\StartServiceW", "Uint", schService, "Uint", 0, "Uint", 0)
			Return WinServ_ErrMsg("StartService", ServiceName, Task, Silent)
	}	else
	If (Task = False)
	{	If !DllCall("Advapi32\ControlService", "Uint", schService, "Uint", SERVICE_CONTROL_STOP, "Uint", &@SSP)
			Return WinServ_ErrMsg("StopService", ServiceName, Task, Silent)
	}
	If !DllCall("Advapi32\QueryServiceStatusEx", "Uint", schService, "Uint", SC_STATUS_PROCESS_INFO, "Uint", &@SSP, "Uint", 36, "Uint", &BytesNeeded)
		Return WinServ_ErrMsg("QueryService", ServiceName, Task, Silent)
	If Task =
		Return WinServ_ErrMsg(0,0,0,True)+(NumGet(@SSP, 4, "Uint") = SERVICE_RUNNING)
	StartTickCount := A_TickCount
	OldCheckPoint := NumGet(@SSP, 20, "Uint")
	Loop
	{	If (NumGet(@SSP, 4, "Uint") != (Task ? SERVICE_START_PENDING : SERVICE_STOP_PENDING))
			Break
		WaitTime := NumGet(@SSP, 24, "Uint")/10
		Sleep % WaitTime := WaitTime < 1000 ? 1000 : WaitTime > 10000 ? 10000 : WaitTime
		If !DllCall("Advapi32\QueryServiceStatusEx", "Uint", schService, "Uint", SC_STATUS_PROCESS_INFO, "Uint", &@SSP, "Uint", 36, "Uint", &BytesNeeded)
			Return WinServ_ErrMsg("QueryService", ServiceName, Task, Silent)
		If (NumGet(@SSP, 20) > OldCheckPoint)
		{	StartTickCount := A_TickCount
			OldCheckPoint := NumGet(@SSP, 20)
		}	else
		If (A_TickCount-StartTickCount > NumGet(@SSP, 24))
			Break
	}

	If (NumGet(@SSP, 4, "Uint") != (Task ? SERVICE_RUNNING : SERVICE_STOPPED))
		Return WinServ_ErrMsg(Task ? "StartService" : "StopService", ServiceName, Task, Silent, DllCall("SetLastError", "Uint", NumGet(@SSP, 12)))
	Return WinServ_ErrMsg(0,0,0,True)+1
}

;===============================================================================
;Function		: WinServ_ErrMsg
;Description	: This function is used internally by WinServ function.
;===============================================================================
WinServ_ErrMsg(Title, ServiceName, Task="", Silent=False, Dummy="")
{	Global schSCManager, schService
	Progress, 10:Off
	If !Silent
	{	If !ErrorLevel
			VarSetCapacity(LastErrMsg, 1024), DllCall("FormatMessage", "Uint", 0x1000, "Uint", 0, "Uint", LastErrNum:=A_LastError != 123 ? A_LastError : 1060, "Uint", 0, "Str", LastErrMsg, "Uint", 1024, "Uint", 0) ;FORMAT_MESSAGE_FROM_SYSTEM=0x1000
		MsgBox, 262160, WinServ.%Title%: %ServiceName%, % "Could not " (Task = True ? "start {" : Task = False ? "stop {" : "query {") ServiceName "} service.`n`n" (!ErrorLevel ? "Error " LastErrNum ": " LastErrMsg : "Error: " ErrorLevel)
	}	DllCall("Advapi32\CloseServiceHandle", "Uint", schService), DllCall("Advapi32\CloseServiceHandle", "Uint", schSCManager)
	Return False
}


#14 fragman

fragman
  • Members
  • 1591 posts

Posted 17 October 2010 - 02:16 PM

Does anyone know how to enumerate the installed services and query description etc. ?

#15 pajenn

pajenn
  • Members
  • 384 posts

Posted 02 February 2011 - 07:00 PM

thanks for the update. works for me on a 32-bit system as well after the original script stopped working after I switched to the unicode version of AHK.

Thanks a lot for the code which I found very useful!

When using 64-bit version of AutoHotKey, it unfortunatelly does not work. There are two issues: 64-bit AHK seems to use wide-strings internally so all ANSI DLL calls should be replaced by their wide equivalents. Further, the original script counts on getting values via NumGet that by default works with 32-bit values. 64-bit version of AHK however works with 64-bit numbers thus it spoils result codes, hence result type must be specified explicitly in NumGet calls.

Here is my fix, feel free to use it if you find it handy.

/* WinServ.ahk
Version			: 1.0-x64
Author			: Hardeep Singh <http://swankyleo.googlepages.com> (modification for 64-bit version by Hynek Mlnarik)
Forum Topic	: http://www.autohotkey.com/forum/viewtopic.php?t=21975
License			: You may use this code freely and without any restriction. If you find it useful, do post your feedback at the
					  above mentioned forum topic.
===============================================================================
Function			: WinServ
Description	: This function can be used to start, stop or query(running status) a windows service on local or a remote
					  computer. Dialogs provide visual feedback when starting/stopping a service or when an error occurs.

~PARAMETERS~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ServiceName	: Specify either the Service Name or the Display Name of the service.

Task				: (Optional) Specify one of the following:
					  True - Starts the service (Returns True if service is started successfully).
					  False - Stops the service (Returns True if service is stopped successfully).
					  NULL(Default) - Query service status (Returns True if service is running).

Silent			: (Optional) Specify one of the following:
					  False(Default) - Show popup dialog for the task being performed or when an error occurs.
					  True - Suppress all popup dialogs including error messages.

Computer		: (Optional) Connect to the service control manager on the specified computer.
					  NULL(Default) - Connect to the service control manager on the local computer.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Return Value	: Returns TRUE or FALSE depending on the task performed.
Notes			: Starting a service which is dependent on other services will also start those services, if not already running.
					  Stopping a service which is dependent on other services will not stop those services.
===============================================================================
*/

WinServ(ServiceName, Task="", Silent=False, Computer="")
{	Global schSCManager, schService
	Static SERVICE_QUERY_STATUS=0x4, SERVICE_START=0x10, SERVICE_STOP=0x20, SC_STATUS_PROCESS_INFO=0, SERVICE_CONTROL_STOP=0x1
	Static SERVICE_STOPPED=0x1, SERVICE_START_PENDING=0x2, SERVICE_STOP_PENDING=0x3, SERVICE_RUNNING=0x4
	VarSetCapacity(@SSP, 36), VarSetCapacity(BytesNeeded, 4), VarSetCapacity(SvcName ,256)

	If Task not in ,0,1
		Return WinServ_ErrMsg("Parameters", ServiceName, Task, False, ErrorLevel:="Invalid Task specified!")
	If !schSCManager := DllCall("Advapi32\OpenSCManagerW", "Str", Computer, "Uint", 0, "Uint", 0)
		Return WinServ_ErrMsg("OpenSCManager", ServiceName, Task, Silent)
	ServiceName := DllCall("Advapi32\GetServiceKeyNameW", "Uint", schSCManager, "Uint", &ServiceName, "Str", SvcName, "UintP", 256) ? SvcName : ServiceName
	If ErrorLevel
		Return WinServ_ErrMsg("GetServiceKeyName", ServiceName, Task, Silent)

	If !schService := DllCall("Advapi32\OpenServiceW", "Uint", schSCManager, "Uint", &ServiceName, "Uint", SERVICE_QUERY_STATUS|SERVICE_START|SERVICE_STOP)
		Return WinServ_ErrMsg("OpenService", ServiceName, Task, Silent)
	ServiceName := DllCall("Advapi32\GetServiceDisplayNameW", "Uint", schSCManager, "Uint", &ServiceName, "Str", SvcName, "UintP", 256) ? SvcName : ServiceName

	Progress, % Task = "" || Silent ? "10:Off" : "10:ZH0 FM10 FS10 B2 H65 W200 ZX2 ZY5", %ServiceName%, % Task ? "Starting service..." : "Stopping service..."
	If (Task = True)
	{	If !DllCall("Advapi32\StartServiceW", "Uint", schService, "Uint", 0, "Uint", 0)
			Return WinServ_ErrMsg("StartService", ServiceName, Task, Silent)
	}	else
	If (Task = False)
	{	If !DllCall("Advapi32\ControlService", "Uint", schService, "Uint", SERVICE_CONTROL_STOP, "Uint", &@SSP)
			Return WinServ_ErrMsg("StopService", ServiceName, Task, Silent)
	}
	If !DllCall("Advapi32\QueryServiceStatusEx", "Uint", schService, "Uint", SC_STATUS_PROCESS_INFO, "Uint", &@SSP, "Uint", 36, "Uint", &BytesNeeded)
		Return WinServ_ErrMsg("QueryService", ServiceName, Task, Silent)
	If Task =
		Return WinServ_ErrMsg(0,0,0,True)+(NumGet(@SSP, 4, "Uint") = SERVICE_RUNNING)
	StartTickCount := A_TickCount
	OldCheckPoint := NumGet(@SSP, 20, "Uint")
	Loop
	{	If (NumGet(@SSP, 4, "Uint") != (Task ? SERVICE_START_PENDING : SERVICE_STOP_PENDING))
			Break
		WaitTime := NumGet(@SSP, 24, "Uint")/10
		Sleep % WaitTime := WaitTime < 1000 ? 1000 : WaitTime > 10000 ? 10000 : WaitTime
		If !DllCall("Advapi32\QueryServiceStatusEx", "Uint", schService, "Uint", SC_STATUS_PROCESS_INFO, "Uint", &@SSP, "Uint", 36, "Uint", &BytesNeeded)
			Return WinServ_ErrMsg("QueryService", ServiceName, Task, Silent)
		If (NumGet(@SSP, 20) > OldCheckPoint)
		{	StartTickCount := A_TickCount
			OldCheckPoint := NumGet(@SSP, 20)
		}	else
		If (A_TickCount-StartTickCount > NumGet(@SSP, 24))
			Break
	}

	If (NumGet(@SSP, 4, "Uint") != (Task ? SERVICE_RUNNING : SERVICE_STOPPED))
		Return WinServ_ErrMsg(Task ? "StartService" : "StopService", ServiceName, Task, Silent, DllCall("SetLastError", "Uint", NumGet(@SSP, 12)))
	Return WinServ_ErrMsg(0,0,0,True)+1
}

;===============================================================================
;Function		: WinServ_ErrMsg
;Description	: This function is used internally by WinServ function.
;===============================================================================
WinServ_ErrMsg(Title, ServiceName, Task="", Silent=False, Dummy="")
{	Global schSCManager, schService
	Progress, 10:Off
	If !Silent
	{	If !ErrorLevel
			VarSetCapacity(LastErrMsg, 1024), DllCall("FormatMessage", "Uint", 0x1000, "Uint", 0, "Uint", LastErrNum:=A_LastError != 123 ? A_LastError : 1060, "Uint", 0, "Str", LastErrMsg, "Uint", 1024, "Uint", 0) ;FORMAT_MESSAGE_FROM_SYSTEM=0x1000
		MsgBox, 262160, WinServ.%Title%: %ServiceName%, % "Could not " (Task = True ? "start {" : Task = False ? "stop {" : "query {") ServiceName "} service.`n`n" (!ErrorLevel ? "Error " LastErrNum ": " LastErrMsg : "Error: " ErrorLevel)
	}	DllCall("Advapi32\CloseServiceHandle", "Uint", schService), DllCall("Advapi32\CloseServiceHandle", "Uint", schSCManager)
	Return False
}