How can i successfully stop a service using c#? - c#

I am trying to stop a service using the following code:
public static void StopService(string name, out string message)
{
message = string.Empty;
EndTask();
ServiceController sc = new ServiceController();
sc.ServiceName = name;
if (sc.Status == ServiceControllerStatus.Running)
{
try
{
sc.Stop();
sc.WaitForStatus(ServiceControllerStatus.Stopped);
}
catch (Exception e)
{
throw ex;
}
}
else
{
message = $"The service has been stopped.";
}
}
The EndTask() is defined as follows:
public static void EndTask()
{
string taskname = "myservice.exe";
string processName = taskname.Replace(".exe", "");
foreach (Process process in Process.GetProcessesByName(processName))
{
process.Kill();
}
}
But I occasionally get the following error
Cannot stop mytestservice service on computer '.'.Inner Exception: System.ComponentModel.Win32Exception
(0x80004005): The pipe has been ended"
Is this to do with the EndTask routine ? do i need to run the EndTask() asynchronously ?

Related

UWP AppServiceConnection - SendResponseAsync returns AppServiceResponseStatus.Failure

I'm trying to create a UWP service app on the Raspberry Pi3 which provides the access to the on board UART. I'm facing an issue about the AppConnection Request/response.
this is the service method that handles the incoming requests from client apps
internal class Inbound
{
public static async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
var messageDeferral = args.GetDeferral();
var response = new ValueSet();
bool success = false;
var msg = args.Request.Message.Keys;
if (args.Request.Message.TryGetValue(ServiceApiRequests.Keys.Command, out object command))
{
try
{
switch (command)
{
case ServiceApiRequests.CommandValues.UartWrite:
if (args.Request.Message.TryGetValue(ServiceApiRequests.Keys.UartTxBuffer, out object txBuffer))
{
string rxBuff = "";
success = await Pi3.Peripherals.Uart.GerInstance(57600).Write((string)txBuffer);
if (success)
{
Debug.WriteLine("Tx: " + (string)txBuffer);
if (args.Request.Message.TryGetValue(ServiceApiRequests.Keys.ReadUartResponse, out object getResponse))
{
if ((string)getResponse == ServiceApiRequests.ReadUartResponse.Yes)
{
rxBuff = await Pi3.Peripherals.Uart.GerInstance(57600).Read();
Debug.WriteLine("Rx: " + rxBuff);
}
}
}
response.Add(ServiceApiRequests.Keys.UartRxBuffer, rxBuff);
}
break;
}
}
catch (Exception ex)
{
success = false;
}
}
response.Add(new KeyValuePair<string, object>(ServiceApiRequests.Keys.Result, success ? ServiceApiRequests.ResultValues.Ok : ServiceApiRequests.ResultValues.Ko));
var result = await args.Request.SendResponseAsync(response);
if (result == AppServiceResponseStatus.Failure)
{
Debug.WriteLine("Failed to send the response");
}
messageDeferral.Complete();
}
}
As you can figure out, the Uart class is get using the Singleton pattern using the method Pi3.Peripherals.Uart.GerInstance(57600).
Following the code i using for send the request from the client app.
public static class Uart
{
public static IAsyncOperation<string> SendCommand(this AppServiceConnection DriverControllerConnection, string txBuffer, string awaitResponse = ServiceApiRequests.ReadUartResponse.Yes)
{
return _SendCommand(DriverControllerConnection, txBuffer, awaitResponse).AsAsyncOperation();
}
private static async Task<string> _SendCommand(AppServiceConnection DriverControllerConnection, string txBuffer, string awaitResponse)
{
AppServiceResponse response = null;
string response_str = "";
try
{
if (DriverControllerConnection != null)
{
response = await DriverControllerConnection.SendMessageAsync(new ServiceApiRequests.UartWrite().GetCommand(txBuffer, awaitResponse));
if (response.Status == AppServiceResponseStatus.Success)
{
if (response.Message.TryGetValue(ServiceApiRequests.Keys.Result, out object result))
{
if ((string)result == ServiceApiRequests.ResultValues.Ok && awaitResponse == ServiceApiRequests.ReadUartResponse.Yes)
{
response_str = response.Message[ServiceApiRequests.Keys.UartRxBuffer] as string;
}
}
}
}
}
catch (Exception ex)
{
// TODO: log
}
return response_str;
}
}
The system works well just for a while, until i have response.Status == AppServiceResponseStatus.Success , then the result of the request changes and it becomes AppServiceResponseStatus.Failure. This way the program counter never steps into the condition if (response.Status == AppServiceResponseStatus.Success).
Any idea about the cause?
Thank you so much for the help.
EDIT
Follow the suggestions, i added an handler for the ServiceClosed event. This is the main class.
public sealed class DriverListener : IBackgroundTask
{
private BackgroundTaskDeferral backgroundTaskDeferral;
private AppServiceConnection appServiceConnection;
public void Run(IBackgroundTaskInstance taskInstance)
{
backgroundTaskDeferral = taskInstance.GetDeferral();
// taskInstance.Canceled += OnTaskCanceled;
var triggerDetails = taskInstance.TriggerDetails as AppServiceTriggerDetails;
appServiceConnection = triggerDetails.AppServiceConnection;
appServiceConnection.RequestReceived += Inbound.OnRequestReceived;
appServiceConnection.ServiceClosed += OnTaskCanceled;
}
private void OnTaskCanceled(AppServiceConnection sender, AppServiceClosedEventArgs reason)
{
if (this.backgroundTaskDeferral != null)
{
Debug.WriteLine("ServiceClosed");
// Complete the service deferral.
this.backgroundTaskDeferral.Complete();
}
}
}
Placing a breakpoint in this function, i see that it was never triggered.
The app connection is opened using the singleton pattern, and putted in a dll that i use in the client app
public static AppServiceConnection GetDriverConnectionInstance()
{
if (_DriverConnectionInstance == null)
{
try
{
_DriverConnectionInstance = OpenDriverConnection().AsTask().GetAwaiter().GetResult();
}
catch
{
}
}
return _DriverConnectionInstance;
}
I also add a Request to the service that toggles a led, and i noticed that the led status changes but the response from the app service is still "Failure" and the message is null.
The AppService has a default lifetime of 25sec, unless it is being requested by the foreground experience. When the service shuts down the connection, your client process will receive the ServiceClosed event, so you know you will need to reopen the connection the next time you want to send a request.

How can I get GCM registered Id with asp.net?

I have an android application which receives registered IDs and sends GCM. When a device registers I would like to take its id and add it to my MSSQL server. How can I get the devices's registered ID with asp.net?
android request code:
private void sendRegistrationIdToBackend() {//Sunucuya regid deðerini gönderecek method
URI url = null;
try {
url = new URI("http://aaaaa.com/bbbbb/duyuru-haber.aspx?regId=" + regid);
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
HttpClient httpclient = new DefaultHttpClient();
HttpGet request = new HttpGet();
request.setURI(url);
try {
httpclient.execute(request);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
asp.net get ıd code :
string registered_id = Request.QueryString["regId"];
Try the following code:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_launch);
context = getApplicationContext();
if (checkPlayServices())
{
gcm = GoogleCloudMessaging.getInstance(this);
regid = getRegistrationId(context);
if (regid.isEmpty())
{
registerInBackground();
}
else
{
Log.d(TAG, "No valid Google Play Services APK found.");
}
}
}
private String getRegistrationId(Context context)
{
final SharedPreferences prefs = getGCMPreferences(context);
String registrationId = prefs.getString(PROPERTY_REG_ID, "");
if (registrationId.isEmpty()) {
Log.d(TAG, "Registration ID not found.");
return "";
}
int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
int currentVersion = getAppVersion(context);
if (registeredVersion != currentVersion) {
Log.d(TAG, "App version changed.");
return "";
}
return registrationId;
}
private SharedPreferences getGCMPreferences(Context context)
{
return getSharedPreferences(LaunchActivity.class.getSimpleName(),
Context.MODE_PRIVATE);
}
private static int getAppVersion(Context context)
{
try
{
PackageInfo packageInfo = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionCode;
}
catch (NameNotFoundException e)
{
throw new RuntimeException("Could not get package name: " + e);
}
}
private void registerInBackground()
{ new AsyncTask() {
Override
protected Object doInBackground(Object... params)
{
String msg = "";
try
{
if (gcm == null)
{
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
Log.d(TAG, "########################################");
Log.d(TAG, "Current Device's Registration ID is: "+msg);
}
catch (IOException ex)
{
msg = "Error :" + ex.getMessage();
}
return null;
} protected void onPostExecute(Object result)
{ //to do here };
}.execute(null, null, null);
}
You may want to make sure you added all the required lines in the AndroidManifest file, as well as declaring a GCM Service and a GCM Broadcast Receiver.
Link to the full answer

WCF service server throws an exception Cannot access a disposed object

So my service is a simple chat application between two wcf clients. Event callback works when I call events. After I close my client and run it again, and write a message again (to call the event) it throws me exception:
An exception of type 'System.ObjectDisposedException' occurred in
RussianRouletteServiceLibrary.dll but was not handled in user code
Additional information: Cannot access a disposed object.
The code for my service callback is as follows:
private static Action<User, UMessage> gameChat = delegate { };
public void Play()
{
IGameCallback subscriber =
OperationContext.Current.GetCallbackChannel<IGameCallback>();
gameChat += subscriber.PlayerSentMessage;
}
This is the event trigger:
public void SendMessage(User user, UMessage message)
{
try
{
gameChat(user, message);
}
catch (Exception ex)
{
throw ex;
}
}
I get this error every time I .ChannelFactory.Close(); .Close(); the client while closing form event is happening.
Is there anyone that knows how to fix this and is willing to share his knowledge?
Thank you in advance!
EDIT #1
This is the code of the client when it opens:
ConcurrencyMode.Multiple,
UseSynchronizationContext = false)]
public partial class GameForm : Form, IGameCallback
{
#region IGame Callbacks
public void PlayerSentMessage(User user, UMessage message)
{
string nickname = user.NickName == clientUser.NickName ? "You" : user.NickName;
this.Invoke(new MethodInvoker(() => lb_ChatBox.Items.Add(nickname + " : " + message.MessageContent)));
}
#endregion
private GameClient _gameClient = null;
private InstanceContext _instance = null;
private User clientUser = new User(){ Email = "zigm4s#gmail.com", Id = 0, FirstName = "Zigmas", LastName = "Slusnys", NickName = "Ziggy", Password = "test123"};
public GameForm()
{
string state;
if (_gameClient != null)
{
MessageBox.Show("nelygu null");
MessageBox.Show(_gameClient.State.ToString());
//_gameClient = new GameClient(new InstanceContext(this));
}
else
{
_gameClient = new GameClient(new InstanceContext(this));
MessageBox.Show(_gameClient.State.ToString());
}
InitializeComponent();
try
{
_gameClient.Open();
_gameClient.Play();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
This is when the client form is closing.
private void GameForm_FormClosing(object sender, FormClosingEventArgs e)
{
try {
if (_gameClient.State != System.ServiceModel.CommunicationState.Faulted)
{
MessageBox.Show("Closing client");
_gameClient.ChannelFactory.Close();
_gameClient.Close();
}
else
{
MessageBox.Show("Aborting client");
_gameClient.Abort();
}
}
catch(Exception ex)
{ MessageBox.Show(ex.ToString());}
}
EDIT #2
I found the mistake, on the service side i had delegates that were static. It doesn't throw this error when it's not static.

How can I find the message I added in my msmq

I wet through this except that I added it to a windows service like this
public partial class TriggerHostProcesses : ServiceBase
{
private const string MESSAGE_QUEUE = #".\Private$\Sample Queue";
private MessageQueue _queue;
public TriggerHostProcesses()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
SendMessage("Hope This Works");
}
protected override void OnStop()
{
}
internal void start()
{
OnStart(null);
}
private void SendMessage(string message)
{
_queue = new MessageQueue(MESSAGE_QUEUE);
Message msg = new Message();
msg.Body = message;
msg.Label = "Testing " + DateTime.Now.ToString();
_queue.Send(msg,new MessageQueueTransaction());
}
}
and to get the message
partial class HostListener : ServiceBase
{
private const string MESSAGE_QUEUE = #".\Private$\Sample Queue";
private MessageQueue _queue;
public HostListener()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try
{
var myTransaction = new MessageQueueTransaction();
var queue = new MessageQueue(MESSAGE_QUEUE);
var message = queue.Receive(new TimeSpan(0, 0, 20),myTransaction);
message.Formatter = new XmlMessageFormatter(
new String[] { "System.String,mscorlib" });
Console.WriteLine(message.Body.ToString());
}
catch(Exception ex)
{
Console.WriteLine("No Message");
}
}
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop your service.
}
internal void start()
{
OnStart(null);
}
}
in my main I added this
var ServiceToRun1 = new TriggerHostProcesses();
var ServiceToRun2 = new HostListener();
if (Environment.UserInteractive)
{
// This used to run the service as a console (development phase only)
ServiceToRun1.start();
ServiceToRun2.start();
Console.WriteLine("Press Enter to terminate ...");
Console.ReadLine();
ServiceToRun1.Stop();
ServiceToRun2.Stop();
}
else
{
ServiceBase.Run(ServiceToRun1);
}
I get the exception Timeout for the requested operation has expired.
Can someone please check if they can see what the problem is?
I don't believe you are using transactions correctly. For example, when sending a message you use:
_queue.Send(msg,new MessageQueueTransaction());
However, this does not begin or commit a transaction. Looking in MSDN the example uses the following code (edited by me):
var myTransaction = new MessageQueueTransaction();
myTransaction.Begin();
myQueue.Send("hello world", myTransaction);
myTransaction.Commit();
I don't believe your message is getting sent, and so your Receive times out.
Similarly your receive logic doesn't seem to correctly use transactions:
myTransaction.Begin();
var myMessage = myQueue.Receive(myTransaction);
var body myOrder = (string)myMessage.Body;
myTransaction.Commit();
You should Rollback in the event of an exception processing your messages so they can be placed back on the queue.
Here is my final product. I'm using this in a windows service. 20 s at a time to see if I have a message then do my processes.
public class MSMQueue:IQueue
{
public MSMQueue(string queueName)
{
Message_Queue = queueName;
}
public string Message_Queue { get; private set; }
public string Pop()
{
MessageQueue queue = new MessageQueue(Message_Queue);
if (queue.Transactional)
return popTransactionalQueue(queue, new TimeSpan(0, 0, 1));
else
return popNormalQueue(queue, new TimeSpan(0, 0, 1));
}
public string Pop(TimeSpan timeSpan)
{
MessageQueue myQueue = new MessageQueue(Message_Queue);
if (myQueue.Transactional)
return popTransactionalQueue(myQueue, timeSpan);
else
return popNormalQueue(myQueue, timeSpan);
}
public void Add(string message)
{
// Connect to a queue on the local computer.
MessageQueue myQueue = new MessageQueue(Message_Queue);
// Send a message to the queue.
if (myQueue.Transactional)
{
var myTransaction = new MessageQueueTransaction();
myTransaction.Begin();
myQueue.Send(message, myTransaction);
myTransaction.Commit();
}
else
myQueue.Send(message);
}
#region private methods
private string popNormalQueue(MessageQueue queue, TimeSpan timeOut)
{
var message = queue.Receive(timeOut);
message.Formatter = new XmlMessageFormatter(
new String[] { "System.String,mscorlib" });
return message.Body.ToString();
}
private string popTransactionalQueue(MessageQueue queue, TimeSpan timeOut)
{
// Set the formatter.
queue.Formatter = new XmlMessageFormatter(new Type[]
{typeof(String)});
// Create a transaction.
MessageQueueTransaction myTransaction = new
MessageQueueTransaction();
String message=string.Empty;
try
{
myTransaction.Begin();
Message myMessage = queue.Receive(timeOut, myTransaction);
message = (String)myMessage.Body;
myTransaction.Commit();
}
catch (MessageQueueException e)
{
myTransaction.Abort();
throw e;
}
return message;
}
#endregion
}

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