What's the easiest programmatic way to restart a service on a remote Windows system? Language or method doesn't matter as long as it doesn't require human interaction.
What's the easiest programmatic way to restart a service on a remote Windows system? Language or method doesn't matter as long as it doesn't require human interaction.
As of Windows XP, you can use sc.exe to interact with local and remote services. Schedule a task to run a batch file similar to this:
sc \\server stop service sc \\server start service
Make sure the task runs under a user account privileged on the target server.
psservice.exe from the Sysinternals PSTools would also be doing the job:
psservice \\server restart service
DESCRIPTION: SC is a command line program used for communicating with the NT Service Controller and services. USAGE: sc [command] [service name] ...
The option <server> has the form "\\ServerName"
Further help on commands can be obtained by typing: "sc [command]"
Commands:
query-----------Queries the status for a service, or
enumerates the status for types of services.
queryex---------Queries the extended status for a service, or
enumerates the status for types of services.
start-----------Starts a service.
pause-----------Sends a PAUSE control request to a service.
interrogate-----Sends an INTERROGATE control request to a service.
continue--------Sends a CONTINUE control request to a service.
stop------------Sends a STOP request to a service.
config----------Changes the configuration of a service (persistant).
description-----Changes the description of a service.
failure---------Changes the actions taken by a service upon failure.
qc--------------Queries the configuration information for a service.
qdescription----Queries the description for a service.
qfailure--------Queries the actions taken by a service upon failure.
delete----------Deletes a service (from the registry).
create----------Creates a service. (adds it to the registry).
control---------Sends a control to a service.
sdshow----------Displays a service's security descriptor.
sdset-----------Sets a service's security descriptor.
GetDisplayName--Gets the DisplayName for a service.
GetKeyName------Gets the ServiceKeyName for a service.
EnumDepend------Enumerates Service Dependencies.
The following commands don't require a service name:
sc <server> <command> <option>
boot------------(ok | bad) Indicates whether the last boot should
be saved as the last-known-good boot configuration
Lock------------Locks the Service Database
QueryLock-------Queries the LockStatus for the SCManager Database
EXAMPLE: sc start MyService
If it doesn't require human interaction which means there will be no UI that invokes this operation and I assume it would restart at some set interval? If you have access to machine, you could just set a scheduled task to execute a batch file using good old NET STOP and NET START
net stop "DNS Client"
net start "DNS client"
or if you want to get a little more sophisticated, you could try Powershell
look at sysinternals for a variety of tools to help you achieve that goal. psService for example would restart a service on a remote machine.
I recommend the method given by doofledorfer.
If you really want to do it via a direct API call, then look at the OpenSCManager function. Below are sample functions to take a machine name and service, and stop or start them.
function ServiceStart(sMachine, sService : string) : boolean; //start service, return TRUE if successful
var schm, schs : SC_Handle;
ss : TServiceStatus;
psTemp : PChar;
dwChkP : DWord;
begin
ss.dwCurrentState := 0;
schm := OpenSCManager(PChar(sMachine),Nil,SC_MANAGER_CONNECT); //connect to the service control manager
if(schm > 0)then begin // if successful...
schs := OpenService( schm,PChar(sService),SERVICE_START or SERVICE_QUERY_STATUS); // open service handle, start and query status
if(schs > 0)then begin // if successful...
psTemp := nil;
if (StartService(schs,0,psTemp)) and (QueryServiceStatus(schs,ss)) then
while(SERVICE_RUNNING <> ss.dwCurrentState)do begin
dwChkP := ss.dwCheckPoint; //dwCheckPoint contains a value incremented periodically to report progress of a long operation. Store it.
Sleep(ss.dwWaitHint); //Sleep for recommended time before checking status again
if(not QueryServiceStatus(schs,ss))then
break; //couldn't check status
if(ss.dwCheckPoint < dwChkP)then
Break; //if QueryServiceStatus didn't work for some reason, avoid infinite loop
end; //while not running
CloseServiceHandle(schs);
end; //if able to get service handle
CloseServiceHandle(schm);
end; //if able to get svc mgr handle
Result := SERVICE_RUNNING = ss.dwCurrentState; //if we were able to start it, return true
end;
function ServiceStop(sMachine, sService : string) : boolean; //stop service, return TRUE if successful
var schm, schs : SC_Handle;
ss : TServiceStatus;
dwChkP : DWord;
begin
schm := OpenSCManager(PChar(sMachine),nil,SC_MANAGER_CONNECT);
if(schm > 0)then begin
schs := OpenService(schm,PChar(sService),SERVICE_STOP or SERVICE_QUERY_STATUS);
if(schs > 0)then begin
if (ControlService(schs,SERVICE_CONTROL_STOP,ss)) and (QueryServiceStatus(schs,ss)) then
while(SERVICE_STOPPED <> ss.dwCurrentState) do begin
dwChkP := ss.dwCheckPoint;
Sleep(ss.dwWaitHint);
if(not QueryServiceStatus(schs,ss))then
Break;
if(ss.dwCheckPoint < dwChkP)then
Break;
end; //while
CloseServiceHandle(schs);
end; //if able to get svc handle
CloseServiceHandle(schm);
end; //if able to get svc mgr handle
Result := SERVICE_STOPPED = ss.dwCurrentState;
end;
Thus your service is restarted taking care all dependencies.
This is what I do when I have restart a service remotely with different account
Open a CMD with different login
runas /noprofile /user:DOMAIN\USERNAME cmd
Use SC to stop and start
sc \\SERVERNAME query Tomcat8
sc \\SERVERNAME stop Tomcat8
sc \\SERVERNAME start Tomcat8
If you attempting to do this on a server on different domain you will need to a little bit more than what has been suggested by most answers so far, this is what I use to accomplish this:
#Configuration
$servername = "ABC",
$serviceAccountUsername = "XYZ",
$serviceAccountPassword = "XXX"
#Establish connection
try {
if (-not ([System.IO.Directory]::Exists('\\' + $servername))) {
net use \\$servername /user:$serviceAccountUsername $serviceAccountPassword
}
}
catch {
#May already exists, if so just continue
Write-Output $_.Exception.Message
}
#Restart Service
sc.exe \\$servername stop "ServiceNameHere"
sc.exe \\$servername start "ServiceNameHere"