How to stop Windows service programmatically - c#

About programming Windows services: how to stop my windows service?
Here is a very simplified example code(C#):
// Here is my service class (MyTestService.cs).
public class MyTestService:ServiceBase{
// Constructor.
public MyTestService(){
this.ServiceName = "My Test Service";
return;
}
};
// My application class (ApplicationClass.cs).
public static class ApplicationClass{
// Here is main Main() method.
public static void Main(){
// 1. Creating a service instance
// and running it using ServiceBase.
MyTestService service = new MyTestService();
ServiceBase.Run(service);
// 2. Performing a test shutdown of a service.
service.Stop();
Environment.Exit(0);
return;
};
};
So: I've just created "My Test Service" started it and stopped. But when I'm looking into my Services.msc - "My Test Service" is continues to running and stops ONLY when I click a "Stop" link. Why? - why service.Stop() command does nothing?
ServiceController.Stop() also does nothing!
How can I stop my service from Main() method?

The Stop-function sends a stop-signal. It does not wait till the signal is received and processed.
You will have to wait till the Stop-signal has done it's work. You can do that by calling WaitForStatus:
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped);
See for more info: http://msdn.microsoft.com/nl-nl/library/system.serviceprocess.servicecontroller.waitforstatus(v=vs.71).aspx
Environment.Exit is a nasty one. DO NOT USE IT! It aborts your application the hard way, without performing any cleanup in finally blocks, without calling finalizer methods by the GC, it terminates all other forground threads, etc. I can imagine that your application is aborted before the stop-signal even left your application.

I am using following functions in my project
public static ServiceController GetService(string serviceName)
{
ServiceController[] services = ServiceController.GetServices();
return services.FirstOrDefault(_ => Contracts.Extensions.CompareStrings(_.ServiceName, serviceName));
}
public static bool IsServiceRunning(string serviceName)
{
ServiceControllerStatus status;
uint counter = 0;
do
{
ServiceController service = GetService(serviceName);
if (service == null)
{
return false;
}
Thread.Sleep(100);
status = service.Status;
} while (!(status == ServiceControllerStatus.Stopped ||
status == ServiceControllerStatus.Running) &&
(++counter < 30));
return status == ServiceControllerStatus.Running;
}
public static bool IsServiceInstalled(string serviceName)
{
return GetService(serviceName) != null;
}
public static void StartService(string serviceName)
{
ServiceController controller = GetService(serviceName);
if (controller == null)
{
return;
}
controller.Start();
controller.WaitForStatus(ServiceControllerStatus.Running);
}
public static void StopService(string serviceName)
{
ServiceController controller = GetService(serviceName);
if (controller == null)
{
return;
}
controller.Stop();
controller.WaitForStatus(ServiceControllerStatus.Stopped);
}

In your code example service.Stop() and ServiceController.Stop() commands does nothing because they are not called while service is running since ServiceBase.Run(service) is blocking operation and it returns only on stop of the service.

Related

Only one usage of each socket address (protocol/network address/port) is normally permitted when AppPool is recycled

I have a .net Core application hosted on IIS.
The application initializes WebSocketServer, by adding a wrapper class as a HostedService.
The hosted service execute the Start() method seen below on its StartAsync() and the Destroy() method on its StopAsync() method.
The problem that whenever the related application pool is recycled - the error in the title appears ("Only one usage of each socket address (protocol/network address/port) is normally permitted"). It happens because there is a new working process that starts-up and trying to use the ports of the socket before there is a shutdown of the current Working process which still use the socket with the same ports.
I'm trying to find a way of avoiding that situation, programmatically or by configuration.
Here is my code of the HostedService:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Diagnostics;
using System.Linq;
using System.Net.WebSockets;
using WebSocketSharp.Server;
namespace XXXX
{
public class WebsocketServerWrapper
{
// Thats an websocket server , he will host our service as web socket service.
private static WebSocketServer wss;
private static readonly object LockObject = new object();
public static IConfiguration Config { get; set; }
public static bool IsCreated()
{
return wss != null;
}
public static bool HasChannels()
{
if(IsCreated())
{
return wss.WebSocketServices.Paths.Any();
}
return false;
}
public static bool IsListening()
{
if (wss != null)
{
return wss.IsListening;
}
return false;
}
public static void AddChannel(string channel)
{
if (wss.WebSocketServices.Paths.Any((path) => path == channel) == false)
{
wss.AddWebSocketService(channel,() => new <class that treats the socket behaviour itself>(Config));
}
}
public static bool Start()
{
wss.Start();
if (IsListening())
{
return true;
}
else
{
return false;
}
}
public static bool Destroy()
{
var isDestroyed = false;
if(IsCreated())
{
removeWebSocketServices();
wss.Stop();
wss = null;
isDestroyed = true;
}
return isDestroyed;
}
internal static void removeWebSocketServices()
{
var channels = wss?.WebSocketServices?.Paths?.ToList() ?? null;
if (channels != null)
{
channels.ForEach(channel => { wss.RemoveWebSocketService(channel); channel = null; });
}
}
public static bool CreateWSSServer()
{
bool isCreationSucceeded = false;
if(!IsCreated())
{
lock(LockObject)
{
try
{
var wssUrl = Config.GetValue<string>(<WebsocketServerUrl adress>);
wss = new WebSocketServer($"ws://{wssUrl}");
isCreationSucceeded = true;
}
catch (WebSocketException wse)
{
Debug.WriteLine(wse);
return isCreationSucceeded;
}
catch (Exception e)
{
Debug.WriteLine(e);
return isCreationSucceeded;
}
}
}
isCreationSucceeded = true;
return isCreationSucceeded;
}
}
}
I found a solution to that scenario (edited it in the question) - it turns out that the scenario of the server starts-up with new worker process before the "old" worker process shutdown is not rare - there is a parameter in the application pool under Recycling => Disable Overlapped Recycle - if it set to true (it is false by default), then the startup with new Working process will occur only after the current worker process will shut-down

TopShelf Service Not Executing

I'm trying to get a TopShelf service to execute.At the moment I have just some test code to see if I could get the service to install.So far I have been able to get the services Start() and execute when in debug mode.From there I install the service, eg ConsoleApp.exe Install.The Service will show in Services, however when I start the service, it doesn't do anything, eg at the moment I have it creating a txt file on my desktop, which it does when using Visual Studio, however when I start the service from services, it wont.
Here is what I have so far.
First I create the Service Class
class FooService
{
public void Start()
{
string DESKTOP = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string Foo = "foo.txt";
string fullPath = System.IO.Path.Combine(DESKTOP, Foo);
using (System.IO.StreamWriter sw = new StreamWriter(fullPath))
{
sw.WriteLine("Hello World");
}
}
public void Stop()
{
Console.WriteLine("Service Stopped");
}
}
As you can see, I'm just creating a txt file on the desktop (which works in VS).From there I configure the service.
internal static class ConfigureService
{
internal static void Config(string serviceName, string serviceDescription)
{
if (string.IsNullOrEmpty(serviceName) | string.IsNullOrEmpty(serviceDescription))
{
return;
}
HostFactory.Run(Config =>
{
Config.Service<FooService>(service =>
{
service.ConstructUsing(s => new FooService());
service.WhenStarted(s => s.Start()); // start event.
service.WhenStopped(s => s.Stop()); // stop event.
});
// Create Event.
Config.RunAsLocalSystem(); // user.
Config.SetServiceName(serviceName); // service name.
Config.SetDescription(serviceDescription); // service description.
});
}
}
And finally I execute it with the following;
// Entry Point.
static void Main()
{
ConfigureService.Config("Foo Service", "some discription....Idk");
Console.ReadLine();
}
When starting the service, it says it Running however the file text file isn't appearing on the desktop.

C# how can I check that is asp.net webapi running

I have an asp.net webapi which sometimes crashes, or it does not give a response. I am trying to solve this problem. However, I temporarily reset the IIS until the problem is solved.
My IIS reset console application;
class Program
{
static void Main(string[] args)
{
while (true)
{
Thread.Sleep(500);
if (CheckConnection() == false)
{
System.Diagnostics.Process.Start(#"C:\Windows\System32\iisreset.exe");
Console.WriteLine("Restarting");
Thread.Sleep(30000);
}
}
}
public static bool CheckConnection(string webApiAddress = null)
{
try
{
using (var client = new WebClient())
{
using (var stream = client.OpenRead("http://localhost:8885/"))
{
return true;
}
}
}
catch
{
return false;
}
}
}
I check per 500 milliseconds. Sometimes my reset application, resets the IIS, probably my asp.net web api crashing. But I am not sure about WebClient.OpenRead() method is best check method.
Thank you for best practice

Avoid multiple web service access. How to achieve that?

I am trying to implement a simple Windows 8 C# XAML application where there are two calls made to access single web service one from project to load and display data and other to display notification.
Since there are two calls made for same web service I want that if one call is already made to the service the other call should wait and use the same response from the first call.
How can i achieve this kind of functionality? I have not added any code since there is no code that i have written for this. I am just trying to think first and then will I code.
Please let me know I can get some help for this kind of project structure?
You can do this by caching the Task that's currently downloading and not starting the download again if there is a cached Task:
private volatile Task<string> m_cachedWebServiceTask;
async Task<string> AccessWebServiceAsync()
{
var task = m_cachedWebServiceTask;
if (task == null)
task = m_cachedWebServiceTask = DownloadFromWebServiceAsync();
try
{
return await task;
}
finally
{
m_cachedWebServiceTask = null;
}
}
Note that this code has a race condition: if you call AccessWebServiceAsync() twice at the same time, there is a small chance DownloadFromWebServiceAsync() will be called twice too. But since this in only an optimization, I think that shouldn't be a problem. If it is a problem for you, you would need to guard the access to the field by a lock.
As I had the feeling that this problem needs further attention and it's solution could still be optimized, I decided to post another approach. The OP is mostly a problem about leveraging the following 3 scopes of requirements: user experience within the application, the application's internal requirements and the web service's loading with multiple requests.
The application needs to make an initial request to load the data.
When he asks for it, the user expects to get the results with the latest updates.
On the other side, it makes no initiate a large series of calls to the web service within a very short moment of time.
So, managing what happens in this very short moment of time it's actually the solution to the problem.
On the client side, the Service1Client class:
public partial class Service1Client
{
// default time buffer value
int _timeBuffer = 100;
// a time buffer used for returning the same response
public int TimeBuffer
{
get { return _timeBuffer; }
set { _timeBuffer = value; }
}
// the start and end time of the web service request
static DateTime _start, _end;
// a volatile static variable to store the response in the buffering time
volatile static string _response;
// used for blocking other threads until the current thread finishes it's job
object _locker = new object();
public async Task<string> GetResponseData()
{
return await Task.Factory.StartNew<string>(() =>
{
lock (_locker)
{
if (DateTime.Now >= _end.AddMilliseconds(TimeBuffer))
{
_start = DateTime.Now;
var async = GetDataAsync();
_response = async.Result;
_end = DateTime.Now;
}
}
return _response;
});
}
}
The console application used for testing:
class Program
{
static void Main(string[] args)
{
while (true)
{
var client = new ServiceReference1.Service1Client();
client.TimeBuffer = 150;
Console.WriteLine(client.GetResponseData().Result);
if (Console.ReadKey().Key == ConsoleKey.Enter)
break;
}
}
}
As a remark, note that, for the reason of a clear sample, I decided to change the returned type of the GetDate WCF service's method from DateTime to string.
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData();
}
public class Service1 : IService1
{
public string GetData()
{
System.Threading.Thread.Sleep(5000);
return DateTime.Now.ToString();
}
}
For your scenario, a feasible idea would be to extend the service class.
The IService1 interface definition:
[ServiceContract]
public interface IService1
{
[OperationContract]
DateTime GetData();
}
The Service1 class definition:
public class Service1 : IService1
{
public DateTime GetData()
{
System.Threading.Thread.Sleep(5000);
return DateTime.Now;
}
}
On the client side, extend the Service1Client class definition and add a new method:
public partial class Service1Client
{
static bool _isOpen;
static DateTime? _cachedResponse;
object _locker = new object();
public DateTime GetResponseData()
{
if (!_isOpen)
{
if (!_cachedResponse.HasValue)
{
lock (_locker)
{
_isOpen = true;
_cachedResponse = GetData();
_isOpen = false;
}
return _cachedResponse.Value;
}
else
{
Task.Factory.StartNew<DateTime>(() =>
{
lock (_locker)
{
_isOpen = true;
_cachedResponse = GetData();
_isOpen = false;
}
return _cachedResponse.Value;
});
}
}
return _cachedResponse.Value;
}
}
Test it:
class Program
{
static void Main(string[] args)
{
while (true)
{
var client = new ServiceReference1.Service1Client();
Console.WriteLine(client.GetResponseData());
if (Console.ReadKey().Key == ConsoleKey.Enter)
break;
}
}
}

How can I restart a windows service programmatically in .NET

How can I restart a windows service programmatically in .NET?
Also, I need to do an operation when the service restart is completed.
This article uses the ServiceController class to write methods for Starting, Stopping, and Restarting Windows services; it might be worth taking a look at.
Snippet from the article (the "Restart Service" method):
public static void RestartService(string serviceName, int timeoutMilliseconds)
{
ServiceController service = new ServiceController(serviceName);
try
{
int millisec1 = Environment.TickCount;
TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
// count the rest of the timeout
int millisec2 = Environment.TickCount;
timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds - (millisec2-millisec1));
service.Start();
service.WaitForStatus(ServiceControllerStatus.Running, timeout);
}
catch
{
// ...
}
}
Take a look at the ServiceController class.
To perform the operation that needs to be done when the service is restarted, I guess you should do that in the Service yourself (if it is your own service).
If you do not have access to the source of the service, then perhaps you can use the WaitForStatus method of the ServiceController.
An example using by ServiceController Class
private void RestartWindowsService(string serviceName)
{
ServiceController serviceController = new ServiceController(serviceName);
try
{
if ((serviceController.Status.Equals(ServiceControllerStatus.Running)) || (serviceController.Status.Equals(ServiceControllerStatus.StartPending)))
{
serviceController.Stop();
}
serviceController.WaitForStatus(ServiceControllerStatus.Stopped);
serviceController.Start();
serviceController.WaitForStatus(ServiceControllerStatus.Running);
}
catch
{
ShowMsg(AppTexts.Information, AppTexts.SystematicError, MessageBox.Icon.WARNING);
}
}
You could also call the net command to do this. Example:
System.Diagnostics.Process.Start("net", "stop IISAdmin");
System.Diagnostics.Process.Start("net", "start IISAdmin");
This answer is based on #Donut Answer (the most up-voted answer of this question), but with some modifications.
Disposing of ServiceController class after each use, because it implements IDisposable interface.
Reduce the parameters of the method: there is no need to the serviceName parameter being passed for each method, we can set it in the constructor, and each other method will use that service name.
This is also more OOP-friendly.
Handle the catch exception in a way that this class could be used as a component.
Remove the timeoutMilliseconds parameter from each method.
Add two new methods StartOrRestart and StopServiceIfRunning, which could be considered as a wrapper for other basic methods, The purpose of those methods are only to avoid exceptions, as described in the comment.
Here is the class
public class WindowsServiceController
{
private readonly string serviceName;
public WindowsServiceController(string serviceName)
{
this.serviceName = serviceName;
}
// this method will throw an exception if the service is NOT in Running status.
public void RestartService()
{
using (ServiceController service = new ServiceController(serviceName))
{
try
{
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped);
service.Start();
service.WaitForStatus(ServiceControllerStatus.Running);
}
catch (Exception ex)
{
throw new Exception($"Can not restart the Windows Service {serviceName}", ex);
}
}
}
// this method will throw an exception if the service is NOT in Running status.
public void StopService()
{
using (ServiceController service = new ServiceController(serviceName))
{
try
{
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped);
}
catch (Exception ex)
{
throw new Exception($"Can not Stop the Windows Service [{serviceName}]", ex);
}
}
}
// this method will throw an exception if the service is NOT in Stopped status.
public void StartService()
{
using (ServiceController service = new ServiceController(serviceName))
{
try
{
service.Start();
service.WaitForStatus(ServiceControllerStatus.Running);
}
catch (Exception ex)
{
throw new Exception($"Can not Start the Windows Service [{serviceName}]", ex);
}
}
}
// if service running then restart the service if the service is stopped then start it.
// this method will not throw an exception.
public void StartOrRestart()
{
if (IsRunningStatus)
RestartService();
else if (IsStoppedStatus)
StartService();
}
// stop the service if it is running. if it is already stopped then do nothing.
// this method will not throw an exception if the service is in Stopped status.
public void StopServiceIfRunning()
{
using (ServiceController service = new ServiceController(serviceName))
{
try
{
if (!IsRunningStatus)
return;
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped);
}
catch (Exception ex)
{
throw new Exception($"Can not Stop the Windows Service [{serviceName}]", ex);
}
}
}
public bool IsRunningStatus => Status == ServiceControllerStatus.Running;
public bool IsStoppedStatus => Status == ServiceControllerStatus.Stopped;
public ServiceControllerStatus Status
{
get
{
using (ServiceController service = new ServiceController(serviceName))
{
return service.Status;
}
}
}
}
If you are using .NET Core you have to download System.ServiceProcess package
And this will work only on WINDOWS
How about
var theController = new System.ServiceProcess.ServiceController("IISAdmin");
theController.Stop();
theController.Start();
Don't forget to add the System.ServiceProcess.dll to your project for this to work.
See this article.
Here is a snippet from the article.
//[QUICK CODE] FOR THE IMPATIENT
using System;
using System.Collections.Generic;
using System.Text;
// ADD "using System.ServiceProcess;" after you add the
// Reference to the System.ServiceProcess in the solution Explorer
using System.ServiceProcess;
namespace Using_ServiceController{
class Program{
static void Main(string[] args){
ServiceController myService = new ServiceController();
myService.ServiceName = "ImapiService";
string svcStatus = myService.Status.ToString();
if (svcStatus == "Running"){
myService.Stop();
}else if(svcStatus == "Stopped"){
myService.Start();
}else{
myService.Stop();
}
}
}
}
I needed somethin more complex, because sometimes services with depencies couldnt be restarted and just throw exception or service could be set to "disabled" and so on.
So this is what i did:
(It checks if service does exist, if its "Disabled" it will set service to "Auto" and when it couldnt restart service it will use taskkill command to kill service through PID and then start it again (You need to be carefull with dependent services with this cause you will need to start/restart them too).
And it just returns true/false if restart was sucessfull
Tested on WIN10 only.
PS: working on version which detect dependent services when using taskkill and restart them too
//Get windows service status
public static string GetServiceStatus(string NameOfService)
{
ServiceController sc = new ServiceController(NameOfService);
switch (sc.Status)
{
case ServiceControllerStatus.Running:
return "Running";
case ServiceControllerStatus.Stopped:
return "Stopped";
case ServiceControllerStatus.Paused:
return "Paused";
case ServiceControllerStatus.StopPending:
return "Stopping";
case ServiceControllerStatus.StartPending:
return "Starting";
default:
return "Status Changing";
}
}
//finds if service exists in OS
public static bool DoesServiceExist(string serviceName)
{
return ServiceController.GetServices().Any(serviceController => serviceController.ServiceName.Equals(serviceName));
}
//finds startup type of service
public static string GetStartupType(string serviceName)
{
ManagementObject objManage = new ManagementObject("Win32_Service.Name='"+serviceName+"'");
objManage.Get();
string status1 = objManage["StartMode"].ToString();
return status1;
}
//restart service through PID
public static bool RestartServiceByPID(string NameOfService)
{
LogWriter log = new LogWriter("TaskKilling: " + NameOfService);
string strCmdText = "/C taskkill /f /fi \"SERVICES eq " + NameOfService + "\"";
Process.Start("CMD.exe", strCmdText);
using(ServiceController ScvController = new ServiceController(NameOfService))
{
ScvController.WaitForStatus(ServiceControllerStatus.Stopped);
if (GetServiceStatus(NameOfService) == "Stopped")
{
ScvController.Start();
ScvController.WaitForStatus(ServiceControllerStatus.Running);
if (GetServiceStatus(NameOfService) == "Running")
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
}
//Restart windows service
public static bool RestartWindowsService(string NameOfService)
{
try
{
//check if service exists
if(DoesServiceExist(NameOfService) == false)
{
MessageBox.Show("Service " + NameOfService + " was not found.");
return false;
}
else
{
//if it does it check startup type and if it is disabled it will set it to "Auto"
if (GetStartupType(NameOfService) == "Disabled")
{
using (var svc = new ServiceController(NameOfService))
{
ServiceHelper.ChangeStartMode(svc, ServiceStartMode.Automatic);
if (svc.Status != ServiceControllerStatus.Running)
{
svc.Start();
svc.WaitForStatus(ServiceControllerStatus.Running);
if(GetServiceStatus(NameOfService) == "Running")
{
return true;
}
else
{
return false;
}
}
else
{
svc.Stop();
svc.WaitForStatus(ServiceControllerStatus.Stopped);
if(GetServiceStatus(NameOfService) == "Stopped")
{
svc.Start();
svc.WaitForStatus(ServiceControllerStatus.Running);
if(GetServiceStatus(NameOfService) == "Running")
{
return true;
}
else
{
return false;
}
}
//restart through PID
else
{
return RestartServiceByPID(NameOfService);
}
}
}
}
//If service is not disabled it will restart it
else
{
using(ServiceController ScvController = new ServiceController(NameOfService))
{
if(GetServiceStatus(NameOfService) == "Running")
{
ScvController.Stop();
ScvController.WaitForStatus(ServiceControllerStatus.Stopped);
if(GetServiceStatus(NameOfService) == "Stopped")
{
ScvController.Start();
ScvController.WaitForStatus(ServiceControllerStatus.Running);
if(GetServiceStatus(NameOfService) == "Running")
{
return true;
}
else
{
return false;
}
}
//if stopping service fails, it uses taskkill
else
{
return RestartServiceByPID(NameOfService);
}
}
else
{
ScvController.Start();
ScvController.WaitForStatus(ServiceControllerStatus.Running);
if(GetServiceStatus(NameOfService) == "Running")
{
return true;
}
else
{
return false;
}
}
}
}
}
}
catch(Exception ex)
{
return RestartServiceByPID(NameOfService);
}
}
You can set a service to restart after failure. So a restart can be forced by throwing an exception.
Use recovery tab on service properties.
Be sure to use reset fail count property to prevent service stopping altogether.
Call Environment.Exit with an error code greater than 0, which seems appropriate, then on install we configure the service to restart on error.
Environment.Exit(1);
I have done same thing in my Service. It is working fine.

Categories