Stop a service if started, else close with a hotkey?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
DeepMind
Posts: 271
Joined: 19 Jul 2016, 14:47

Stop a service if started, else close with a hotkey?

23 Oct 2016, 13:31

stop a windows service if it's started, else close it? so I got this from here, but not sure if that works in latest autohotkey version, :

Code: Select all

RunWait,sc stop "AdobeARMservice" ;Stop AdobeARM service.
If (ErrorLevel = 0){
	MsgBox Success!
}
MsgBox %Errorlevel%
RunWait,sc start "AdobeARMservice" ;Start AdobeARM service.
If (ErrorLevel = 0){
	MsgBox Success!
}
return
currently maybe I couldn't test this, so I''m posting if anybody had any suggestion
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Stop a service if started, else close with a hotkey?

23 Oct 2016, 13:55

It uses the Command lines SC.exe which interacts with Services.
I don't see why it shouldn't work.
Although this only restarts a service while showing you annoying MsgBoxes.
In order to check if a Service is running you can use Process,Exist.
Recommends AHK Studio
Jochen
Posts: 48
Joined: 17 Apr 2016, 11:25

Re: Stop a service if started, else close with a hotkey?

20 Jul 2017, 04:59

If I try this with another service, I only recieve the message "1060", but the service is still running.

For stopping a service I am using:

Code: Select all

If !(A_IsAdmin)     ;- if you're NOT 'admin'
   {
   Run, *RunAs %comspec% /c net stop "FillInHere_MyService", , hide
   }
If (A_IsAdmin)       ;- I'm 'admin' so it works
   Run, %comspec% /c net stop "FillInHere_MyService", , hide
return
If you wanna start a service instead, use "start" instead of "stop".

But I am looking for a function that detects if a service is running or not.
I have been looking down and fro but could not find it (or perhaps did not understand ;-))
I found in former days there existed a function "GetServiceState"...?

If someone could help with that, would be great!
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: Stop a service if started, else close with a hotkey?

20 Jul 2017, 08:26

Tried to update the function for AHK1.1+ / x64 compatibility.
Please test for correct behavior under x64, since I have no access to such machine.
Enjoy!

[EDIT]
Code updated:
- fixed var type UIntP instead of PtrP
- added display of ErrorLevel in case of failure, for a more useful result.

Code: Select all

; by tonne at  https://autohotkey.com/board/topic/14159-check-state-of-windows-service/
; updated by Drugwash, 2017.07.20
/*
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

READ_CONTROL=0x20000
SC_MANAGER_ALL_ACCESS=0xF003F
SERVICE_CONTROL_INTERROGATE = 0x00000004

typedef struct _SERVICE_STATUS
{
DWORD dwServiceType;
DWORD dwCurrentState;
DWORD dwControlsAccepted;
DWORD dwWin32ExitCode;
DWORD dwServiceSpecificExitCode;
DWORD dwCheckPoint;
DWORD dwWaitHint;
} SERVICE_STATUS, *LPSERVICE_STATUS;
*/
; [EXAMPLE]
#NoEnv
#KeyHistory, 0
ListLines, Off
SetBatchLines -1
SetControlDelay, -1
SetWinDelay, -1
DetectHiddenWindows, On
StringCaseSense, Off
SetFormat, Integer, D
;updates()
AW := A_IsUnicode ? "W" : "A", A_CharSize := 2**(A_IsUnicode=TRUE)	; found in my updates.ahk

states := "stopped|pending start|pending stop|running|pending continuation|pending pause|paused"
StringSplit, s, states, |
sName1 := "LanmanWorkstation", sName2 := "Workstation2"
msg1 := (i := GetServiceState(sName1)) ? s%i% : "nonexistant (error " ErrorLevel ")"
msg2 := (i := GetServiceState(sName2)) ? s%i% : "nonexistant (error " ErrorLevel ")"
MsgBox % "Service '" sName1 "' is " msg1 ".`nService '" sName2 "' is " msg2 "."
; [/EXAMPLE]
;================================================================
GetServiceState(dspName)
;================================================================
{
Global Ptr, AW, A_CharSize
; open service manager with sufficient rights
if !hSCM := DllCall("advapi32\OpenSCManager" AW, Ptr, 0, Ptr, 0, "UInt", 0x2003F, Ptr)
	return 0, ErrorLevel := DllCall("GetLastError", "UInt")
; open the service
if !hSvc := DllCall("advapi32\OpenService" AW, Ptr, hSCM, "Str", dspName, "UInt", 0x000201FF, Ptr)
	{
	r := DllCall("GetLastError", "UInt")
	; try to find the service name from the display name
	DllCall("advapi32\GetServiceKeyName" AW, Ptr, hSCM, "Str", dspName, Ptr, 0, "UIntP", dwLen)
	VarSetCapacity(svcName, A_CharSize*(++dwLen), 0)
	DllCall("advapi32\GetServiceKeyName" AW, Ptr, hSCM, "Str", dspName, "Str", svcName, "UIntP", dwLen)
	if !hSvc := DllCall("advapi32\OpenService" AW, Ptr, hSCM, "Str", svcName, "UInt", 0x000201FF, Ptr)
		{
		DllCall("advapi32\CloseServiceHandle", Ptr, hSCM)
		return 0, ErrorLevel := DllCall("GetLastError", "UInt")
		}
	}
VarSetCapacity(serviceStatus,32,0)				; accomodate x64 alignment
DllCall("advapi32\ControlService", Ptr, hSvc, "UInt", 0x4, Ptr, &serviceStatus)
dwCurrentState := NumGet(serviceStatus, 4)
DllCall("advapi32\CloseServiceHandle", Ptr, hSvc)		; close the service
DllCall("advapi32\CloseServiceHandle", Ptr, hSCM)	; close the service manager
return dwCurrentState
}
Last edited by Drugwash on 21 Jul 2017, 04:54, edited 1 time in total.
Part of my AHK work can be found here.
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Stop a service if started, else close with a hotkey?

20 Jul 2017, 08:51

Drugwash wrote:Tried to update the function for AHK1.1+ / x64 compatibility.
Please test for correct behavior under x64, since I have no access to such machine.
Enjoy!
Spoiler
Ran flawlessly. Win7Pro/AHK 1.1.25x :thumbsup: Thx for your effort. Much appreciated!
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: Stop a service if started, else close with a hotkey?

20 Jul 2017, 08:59

Great, thanks for reporting back. :)
Part of my AHK work can be found here.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Stop a service if started, else close with a hotkey?

20 Jul 2017, 09:01

@Drugwash
From my unfinshed Services Class (x86 / x64)

Code: Select all

GetServiceKeyName(hSCManager, DisplayName)
{
	DllCall("advapi32\GetServiceKeyName", "ptr", hSCManager, "str", DisplayName, "ptr", 0, "uint*", size)
	size := VarSetCapacity(ServiceName, size * (A_IsUnicode ? 2 : 1), 0) + 1
	if !(DllCall("advapi32\GetServiceKeyName", "ptr", hSCManager, "str", DisplayName, "str", ServiceName, "uint*", size))
		throw Exception("GetServiceKeyName failed: " A_LastError, -1)
	return ServiceName
}
W and A suffix should not be needed since it's handled internally
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: Stop a service if started, else close with a hotkey?

20 Jul 2017, 09:10

This may be true in some situations but not in others, and I'm referring to any possible library that some API is being called from. Therefore I set myself a rule to always use the AW variable - which is always present in my updates.ahk supplement required for compatibility between AHK Basic and later versions - just to be on the safe side. Of course anybody may tweak the code as desired. ;)

Oh and I may be wrong but doesn't the size calculated by your formula miss and ending NULL in Unicode version, or is that handled internally too?
Part of my AHK work can be found here.
Jochen
Posts: 48
Joined: 17 Apr 2016, 11:25

Re: Stop a service if started, else close with a hotkey?

21 Jul 2017, 01:06

Hm, I cannot get it running...
Instead of
sName1 := "LanmanWorkstation", sName2 := "Workstation2"
I fill in my service like
sName1 := "CodeMeter Runtime Server", sName2 := "Workstation2"
but I do not get any result.
Or does the service name has to appear anywher else?
With "service" I mean the services mentioned at services.msc.
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: Stop a service if started, else close with a hotkey?

21 Jul 2017, 04:13

The examples are meant to show how an existing and an unexisting service would appear in results.
Workstation2 is nonexistant as far as I know so it should always appear like that. It's safe to ignore it.
About your particular service I don't know. Try to modify the calls as following, there should be an error code when function fails:

Code: Select all

msg1 := (i := GetServiceState(sName1)) ? s%i% : "nonexistant (error " ErrorLevel ")"
msg2 := (i := GetServiceState(sName2)) ? s%i% : "nonexistant (error " ErrorLevel ")"
Error 123 stands for ERROR_INVALID_NAME, that means service name may be wrong.
Error 1060 stands for ERROR_SERVICE_DOES_NOT_EXIST, meaning that service is not installed.

I've edited the function in the post above to include the enhancement and fix a potential issue on x64 systems, you may want to update your code.
Also, do you have admin rights when you calll the function? What OS version you're running it on?
Part of my AHK work can be found here.
Jochen
Posts: 48
Joined: 17 Apr 2016, 11:25

Re: Stop a service if started, else close with a hotkey?

23 Jul 2017, 11:27

Ok,
I guess I am doing something wrong:

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

; by tonne at  https://autohotkey.com/board/topic/14159-check-state-of-windows-service/
; updated by Drugwash, 2017.07.20
/*
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

READ_CONTROL=0x20000
SC_MANAGER_ALL_ACCESS=0xF003F
SERVICE_CONTROL_INTERROGATE = 0x00000004

typedef struct _SERVICE_STATUS
{
DWORD dwServiceType;
DWORD dwCurrentState;
DWORD dwControlsAccepted;
DWORD dwWin32ExitCode;
DWORD dwServiceSpecificExitCode;
DWORD dwCheckPoint;
DWORD dwWaitHint;
} SERVICE_STATUS, *LPSERVICE_STATUS;
*/
; [EXAMPLE]
#NoEnv
#KeyHistory, 0
ListLines, Off
SetBatchLines -1
SetControlDelay, -1
SetWinDelay, -1
DetectHiddenWindows, On
StringCaseSense, Off
SetFormat, Integer, D
;updates()
AW := A_IsUnicode ? "W" : "A", A_CharSize := 2**(A_IsUnicode=TRUE)	; found in my updates.ahk

states := "stopped|pending start|pending stop|running|pending continuation|pending pause|paused"
StringSplit, s, states, |
sName1 := "PlugPlay", sName2 := "Workstation2"
msg1 := (i := GetServiceState(sName1)) ? s%i% : "nonexistant"
msg2 := (i := GetServiceState(sName2)) ? s%i% : "nonexistant"
MsgBox % "Service '" sName1 "' is " msg1 ".`nService '" sName2 "' is " msg2 "."
; [/EXAMPLE]
;================================================================
GetServiceState(dspName)
;================================================================
{
Global Ptr, PtrP, AW, A_CharSize
; open service manager with sufficient rights
if !hSCM := DllCall("advapi32\OpenSCManager" AW, Ptr, 0, Ptr, 0, "UInt", 0x2003F, Ptr)
	return 0, ErrorLevel := DllCall("GetLastError", "UInt")
; open the service
if !hSvc := DllCall("advapi32\OpenService" AW, Ptr, hSCM, "Str", dspName, "UInt", 0x000201FF, Ptr)
	{
	r := DllCall("GetLastError", "UInt")
	; try to find the service name from the display name
	DllCall("advapi32\GetServiceKeyName" AW, Ptr, hSCM, "Str", dspName, Ptr, 0, PtrP, dwLen)
	VarSetCapacity(svcName, A_CharSize*(++dwLen), 0)
	DllCall("advapi32\GetServiceKeyName" AW, Ptr, hSCM, "Str", dspName, "Str", svcName, PtrP, dwLen)
	if !hSvc := DllCall("advapi32\OpenService" AW, Ptr, hSCM, "Str", svcName, "UInt", 0x000201FF, Ptr)
		{
		DllCall("advapi32\CloseServiceHandle", Ptr, hSCM)
		return 0, ErrorLevel := DllCall("GetLastError", "UInt")
		}
	}
VarSetCapacity(serviceStatus,32,0)				; accomodate x64 alignment
DllCall("advapi32\ControlService", Ptr, hSvc, "UInt", 0x4, Ptr, &serviceStatus)
dwCurrentState := NumGet(serviceStatus, 4)
DllCall("advapi32\CloseServiceHandle", Ptr, hSvc)		; close the service
DllCall("advapi32\CloseServiceHandle", Ptr, hSCM)	; close the service manager
return dwCurrentState
}
For Service I used "PlugPlay", this service everyone should have.
If I call the script, but it tells me the service would be inexistant.
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: Stop a service if started, else close with a hotkey?

23 Jul 2017, 14:13

I just tested the code exactly as you posted it above and it returned Service 'PlugPlay' is running. That's on XP x86 with AHK 1.1.25 Unicode.
You did not update the code as I mentioned above, as to return any error code in case of failure. Please do that, try again and then post the relevant info.

So I'm asking again:
- do you have admin rights on the account you're running the script in?
- what OS version are you running? (as in 'Win 7 x86' or 'Win10 x64' or whatever)
- what AHK version are you running the script with? (as in AHK 1.1 x86 ANSI or AHK 2.0 x64 Unicode or whatever)
- what error code(s) do you get when the script returns?
Part of my AHK work can be found here.
Jochen
Posts: 48
Joined: 17 Apr 2016, 11:25

Re: Stop a service if started, else close with a hotkey?

23 Jul 2017, 14:25

My fault,
I did not run ahk.script with admin rights - Please excuse me.
Shall we delete the last posts regarding this?
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: Stop a service if started, else close with a hotkey?

23 Jul 2017, 17:58

So I take it it does work now. That's good. No need for apologies, things tend to slip our mind every now and then.
We should leave everything as is, for others to learn if they hit the same issue.
Part of my AHK work can be found here.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Araphen, DaveT1, Descolada, KolaBorat and 178 guests