I have a Topshelf C# service that must restore adapter DNS settings when exiting. My stop/start methods work just fine and this code works:
ManagementObject.InvokeMethod("SetDNSServerSearchOrder", DNS, null);
Shutdown, however, is a problem, even with RequestAdditionalTime
I log the following error:
2016-11-30 15:10:53,427 [7] TRACE MyDNSService - DNSService Shutdown command received.
2016-11-30 15:10:53,677 [7] DEBUG MyDNSService - DNSService Error setting DNS: A system shutdown is in progress. (Exception from HRESULT: 0x8007045B)
So it appears that the OS is blocking my call to ManagementObject.InvokeMethod
I'm stymied. Is there a way around this issue? On startup my service detects the anomaly and recovers, but that takes too long. I'd really like to be able to shutdown gracefully.
Rocky, I just re-created the functional elements of your code (logging what's happening) but I'm not getting the error. I'm setting the DNSServerSearchOrder to null and feeding that to the SetDNSServerSearchOrder method of the management object. https://github.com/paulsbruce/StackOverflowExamples/blob/master/PriorityShutdown/PriorityShutdown/MyService.cs
My only additional recommendation is that you can try changing the priority of the shutdown order of your service to see if that has any effect. See this thread: .NET Windows Services stopping order when the system shutdown
I've got a WinForm application and a service that does some work from the application on a server. I want the user to able to control the service from the application, so I added a ServiceController to do all the work (Start, Stop, Restart at first only). Everything works fine so far but while testing different scenarios I encountered a problem: My service is running on a server, the application is running on a client in the same network. I connect to the service and open the ServiceController.
I then shut down the server (VM) where the service is running and trigger the stop method from the client. I use the WaitForStatus method with a timeout, problem is: the timeout is seemingly ignored by the app:
public void StopService()
{
if (this._serviceController.CanStop &&
(this.ServiceStatus == ServiceControllerStatus.Running || this.ServiceStatus == ServiceControllerStatus.Paused))
{
this._serviceController.Stop();
this._serviceController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(30));
}
}
In my case, the methods seems to try to stop the service for around 90 seconds and then throws an InvalidOperationException, which I can handle but I don't want the user to wait 90 seconds.
I think my question basically is: What happens when the timer (30 seconds in this case) runs out? Shouldn't the code just continue to run? And when does this function throw an TimeoutException? MSDN says when "The value specified for the timeout parameter expires." - but it seems like this doesn't mean after the value reaches zero.
Can someone enlighten me?
When we specify TimeSpan, WaitForStatus will rise timeout exception after waiting for given time but it seems to be you having exception on privileges.
please read this answer.
I'm trying to create message queue:
MessageQueue.Create(path, true);
And I'm getting the following exception:
The queue does not exist or you do not have sufficient permissions to
perform the operation.
But queue was created in spite of exception. I tried several times:
Remove queue
Invoke create method
Exception occurs
Queue was created.
Could someone tell me the reason of exception? How can I avoid it?
Edited:
I tried on different machine. The same behavior.
OS: Windows 7. Console application. Runned by user with admin rights.
I found how it can be avoided.
Path was equal to #"**localhost**\Private$\Queue".
I changed it to #"**.**\Private$\Queue" and the exception disappeared.
But the reason is still unclear.
I am working on Windows Service. It works fine. When i am trying to stop the service from services.msc, it throws the following error:
Windows could not stop the xxx service on Local Computer.
The service did not return an error. This could be an internal Windows error or an internal service error.
If the problem persists, contact your system administrator.
If I try to stop it again, it takes lots of time and then throws the error as below:
Windows could not stop the xxx service on Local Computer.
Error 1061: The service cannot accept control messages at this time.
At this point, the service has stopped. But if I try to reinstall the service, it throws another error:
Windows could not stop the xxx service on Local Computer.
Error 1001: The specified service is marked for deletion.
After closing services.msc, it lets me reinstall the service and again things start working fine.
In OnStop(), I am doing some lengthy operations and it takes time to complete.
Any idea how I can make the whole thing go smoothly?
--Edit--
This is what my OnStop method looks like:
protected override void OnStop()
{
base.OnStop();
//Some lengthy operation
}
The windows service have a default timeout in onstart and onstop events. Normally if you are doing time consuming operations in any of these events start a new thread and let the operation to perform in background.
Usually the OnStart as well as OnStop events within the windows service are used to initiate a process and the time consuming process will carryout it's execution within a child thread.
Hope this will solve your issue..
There is a registry entry that controls how much time windows gives services to shut down before giving up: http://support.microsoft.com/kb/146092
Trivially, increasing this time would fix the issue, assuming that your service is actually shutting down after that long operation.
Quick summary with what I now know
I've got an EventWaitHandle that I created and then closed. When I try to re-create it with this ctor, an "Access to the path ... is denied" exception is thrown. This exception is rare, most of the times it just re-creates the EventWaitHandle just fine. With the answer posted below (by me), I'm able to successfully call EventWaitHandle.OpenExisting and continue on in the case that an exception was thrown, however, the ctor for EventWaitHandle should have done this for me, right? Isn't that what the out parameter, createdNew is for?
Initial question
I've got the following architecture, a windows service and a web service on the same server. The web service tells the windows service that it has to do work by opening and setting the wait handle that the windows service is waiting on.
Normally everything is flawless and I'm able to start / stop the windows service without any issue popping up. However, some times when I stop the web service and then start it up again, it will be completely unable to create the wait handle, breaking the whole architecture.
I specifically need to find out what is breaking the event wait handle and stop it. When the wait handle "breaks", I have to reboot windows before it will function properly again and thats obviously not ideal.
UPDATE: Exception thrown & Log of Issue
I rebooted the windows service while the web service was doing work in hopes of causing the issue and it did! Some of the class names have been censored for corporate anonymity
12:00:41,250 [7] - Stopping execution due to a ThreadAbortException
System.Threading.ThreadAbortException: Thread was being aborted.
at System.Threading.Thread.SleepInternal(Int32 millisecondsTimeout)
at OurCompany.OurProduct.MyClass.MyClassCore.MonitorRequests()
12:00:41,328 [7] - Closing Event Wait Handle
12:00:41,328 [7] - Finally block reached
12:00:42,781 [6] - Application Start
12:00:43,031 [6] - Creating EventWaitHandle: Global\OurCompany.OurProduct.MyClass.EventWaitHandle
12:00:43,031 [6] - Creating EventWaitHandle with the security entity name of : Everyone
12:00:43,078 [6] - Unhandled Exception
System.UnauthorizedAccessException: Access to the path 'Global\OurCompany.OurProduct.MyClass.EventWaitHandle' is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.Threading.EventWaitHandle..ctor(Boolean initialState, EventResetMode mode, String name, Boolean& createdNew, EventWaitHandleSecurity eventSecurity)
at OurCompany.OurProduct.MyClassLibrary.EventWaitHandleFactory.GetNewWaitHandle(String handleName, String securityEntityName, Boolean& created)
at OurCompany.OurProduct.MyClassLibrary.EventWaitHandleFactory.GetNewEventWaitHandle()
at OurCompany.OurProduct.MyClass.MyClassCore..ctor()
Rough timeline:
11:53:09,937: The last thread on the web service to open that existing wait handle, COMPLETED its work (as in terminated connection with the client)
12:00:30,234: The web service gets a new connection, not yet using the wait handle. The thread ID for this connection is the same as the thread ID for the last connection at 11:53
12:00:41,250: The windows service stops
12:00:42,781: The windows service starts up
12:00:43,078: The windows service finished crashing
12:00:50,234: The web service was actually able to open the wait handle call Set() on it without any exception thrown etc.
12:02:00,000: I tried rebooting the windows service, same exception
12:36:57,328: After arbitrarily waiting 36 minutes, I was able to start the windows service up without a full system reboot.
Windows Service Code
Initialization:
// I ran into security issues so I open the global EWH
// and grant access to Everyone
var ewhSecurity = new EventWaitHandleSecurity();
ewhSecurity.AddAccessRule(
new EventWaitHandleAccessRule(
"Everyone",
EventWaitHandleRights.Synchronize | EventWaitHandleRights.Modify,
AccessControlType.Allow));
this.ewh = new EventWaitHandle(
false,
EventResetMode.AutoReset,
#"Global\OurCompany.OurProduct.MyClass.EventWaitHandle",
out created,
ewhSecurity);
// the variable "created" is logged
Utilization:
// wait until the web service tells us to loop again
this.ewh.WaitOne();
Disposal / closing:
try
{
while (true)
{
// entire service logic here
}
}
catch (Exception e)
{
// should this be in a finally, instead?
if (this.ewh != null)
{
this.ewh.Close();
}
}
Web Service Code
Initialization:
// NOTE: the wait handle is a member variable on the web service
this.existing_ewh = EventWaitHandle.OpenExisting(
#"Global\OurCompany.OurProduct.MyClass.EventWaitHandle");
Utilization:
// wake up the windows service
this.existing_ewh.Set();
Since the EventWaitHandle is a member variable on the web service, I don't have any code that specifically closes it. Actually, the only code that interacts with the EventWaitHandle on the web service is posted above.
Looking back, I should probably have put the Close() that is in the catch block, in a finally block instead. I probably should have done the same for the web service but I didn't think that it was needed.
At any rate, can anyone see if I'm doing anything specifically wrong? Is it crucially important to put the close statements within a finally block? Do I need to manually control the Close() of the existing_ewh on the web service?
Also, I know this is a slightly complex issue so let me know if you need any additional info, I'll be monitoring it closely and add any needed information or explanations.
Reference material
EventWaitHandleSecurity Class
EventWaitHandleAccessRule Class
EventWaitHandle Class
In the code that creates the wait handle on the windows service, if it fails (as in access denied), you could try to "open an existing wait handle" via
EventWaitHandle.OpenExisting(
#"Global\OurCompany.OurProduct.MyClass.EventWaitHandle",
EventWaitHandleRights.Synchronize | EventWaitHandleRights.Modify);
Though, I'm not entirely sure if the behaviour would stay the same at that point.
Note: I'd appreciate feedback. Its a potential answer so I'm answering my own question, again, plenty of comments are quite welcome!
Note 2: Amazingly, applying EventWaitHandleRights.FullControl instead of the above flags (Synchronize + Modify) doesn't work well. You must use the sample above.
MSDN says:
UnauthorizedAccessException - The named event exists and has access control security, but the user does not have EventWaitHandleRights.FullControl.
and
The caller has full control over the newly created EventWaitHandle object even if eventSecurity denies or fails to grant some access rights to the current user.
Your service has no rights to get the existing event via EventWaitHandle constructor. (EventWaitHandleRights.FullControl is not specified. And your named event exists while it has opened handles on it.) You can open the existing event using EventWaitHandle.OpenExisting.