{"id":249,"date":"2011-05-23T19:47:37","date_gmt":"2011-05-23T17:47:37","guid":{"rendered":"http:\/\/hen.co.za\/blog\/?p=249"},"modified":"2011-05-24T07:23:17","modified_gmt":"2011-05-24T05:23:17","slug":"scheduled-tasks-and-restarting-services","status":"publish","type":"post","link":"https:\/\/hen.co.za\/blog\/2011\/05\/scheduled-tasks-and-restarting-services\/","title":{"rendered":"Scheduled tasks and restarting services"},"content":{"rendered":"<p>I recently had the &#8216;pleasure&#8217; to have some of my maintenance scripts that restart some &#8216;<em>Windows Services<\/em>&#8216; stopped working since &#8216;other&#8217; people installed stuff that creates new dependencies. The problem is that the normal commands like &#8216;net stop&#8217; or &#8216;sc start&#8217; are not aware of dependent services and simply fail to perform their task if the dependent service is still running. Additionally, the built in task engine for Windows does not really have much in the line of useful logging and error reporting. Most of the time you have to &#8216;guess&#8217; what went wrong \ud83d\ude09<\/p>\n<h2><span style=\"color: #800000;\">.Net to the rescue<\/span><\/h2>\n<p>Fortunately I knew from past experience that the .Net framework&#8217;s <strong>ServiceController<\/strong> class has the Stop and Start methods that do take into account the dependencies and also try to stop or start them as needed. So all you need is to create what is essentially a wrapper class to call these methods. Additionally you have full access to errors and can log them in any way you like. As a side bonus it might be useful to have this tool also handle batches of requests since you usually want to stop and start a bunch of related services at the same time.<\/p>\n<p>To keep things simple the tool simple accepts one parameter that &#8211; a file name for the file that contain a list of the action &#8216;service name&#8217;s. e.g.<\/p>\n<blockquote><p>stop .\\Winmgmt<br \/>\nstart .\\Winmgmt<\/p><\/blockquote>\n<p>Then it is a simple matter of reading the file line for line using File.ReadAllLines() method and using the first part of the line to see if the service must be stopped or started. I like things that are simple and &#8216;just works&#8217;.<\/p>\n<p>The code also makes provision that it can stop\/start services on other machines &#8211; provided the account it runs under has the right privileges. The rest of the code are there just for error handling and logging.<\/p>\n<h2><span style=\"color: #800000;\">The code<\/span><\/h2>\n<blockquote><p><span style=\"color: #0000ff;\">static void<\/span> Main(<span style=\"color: #0000ff;\">string<\/span>[] args)<br \/>\n{<\/p>\n<p style=\"padding-left: 30px;\">&#8230;initial stuff<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\">string<\/span>[] lines = <span style=\"color: #0000ff;\">File<\/span>.ReadAllLines(args[0]);<br \/>\n<span style=\"color: #0000ff;\">foreach <\/span>(string line in lines)<br \/>\n{<\/p>\n<p style=\"padding-left: 60px;\">ProcessLine(line);<br \/>\nSystem.Threading.<span style=\"color: #0000ff;\">Thread<\/span>.Sleep(new <span style=\"color: #0000ff;\">TimeSpan<\/span>(0,0, waitBetweenServiceChangeSec));<\/p>\n<p style=\"padding-left: 30px;\">}<\/p>\n<p>}<\/p>\n<p><span style=\"color: #0000ff;\">private static void<\/span> ProcessLine(<span style=\"color: #0000ff;\">string <\/span>line)<br \/>\n{<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\">string <\/span>action = &#8220;&#8221;;<br \/>\n<span style=\"color: #0000ff;\">string <\/span>machineName = &#8220;.&#8221;;<br \/>\n<span style=\"color: #0000ff;\">string <\/span>serviceName = &#8220;&#8221;;<br \/>\n<span style=\"color: #0000ff;\">if <\/span>(line.Split(&#8216; &#8216;).Length &gt; 1) <span style=\"color: #800000;\">\/\/make sure there is an &#8216;action&#8217; and service name<\/span><br \/>\n{<\/p>\n<p style=\"padding-left: 60px;\">action = line.Split(&#8216; &#8216;)[0].Trim().ToLower();<br \/>\nserviceName = line.Substring(line.IndexOf(&#8216; &#8216;)).Trim();<br \/>\n<span style=\"color: #0000ff;\">if <\/span>(serviceName.IndexOf(&#8216;\\\\&#8217;) &gt; -1)<br \/>\n{<\/p>\n<p style=\"padding-left: 90px;\">machineName = serviceName.Substring(0, serviceName.IndexOf(&#8216;\\\\&#8217;));<br \/>\nserviceName = serviceName.Substring(serviceName.IndexOf(&#8216;\\\\&#8217;) + 1);<\/p>\n<p style=\"padding-left: 60px;\">}<\/p>\n<p style=\"padding-left: 60px;\"><span style=\"color: #0000ff;\">if <\/span>(action == &#8220;start&#8221;)<\/p>\n<p style=\"padding-left: 90px;\">StartService(serviceName, machineName);<\/p>\n<p style=\"padding-left: 60px;\"><span style=\"color: #0000ff;\">else if<\/span> (action == &#8220;stop&#8221;)<\/p>\n<p style=\"padding-left: 90px;\">StopService(serviceName, machineName);<\/p>\n<p style=\"padding-left: 30px;\">}<\/p>\n<p>}<\/p>\n<p><span style=\"color: #0000ff;\">private static void<\/span> StopService(<span style=\"color: #0000ff;\">string <\/span>serviceName, <span style=\"color: #0000ff;\">string <\/span>machineName)<br \/>\n{<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\">ServiceController <\/span>sc;<br \/>\n<span style=\"color: #0000ff;\">ServiceControllerStatus <\/span>resultingStatus = <span style=\"color: #0000ff;\">ServiceControllerStatus<\/span>.Stopped;<br \/>\n<span style=\"color: #0000ff;\">try<\/span><br \/>\n{<\/p>\n<p style=\"padding-left: 60px;\">LogProgress(string.Format(&#8220;Stopping the service {0}\\\\{1}&#8221;, machineName, serviceName), <span style=\"color: #0000ff;\">EventLogEntryType<\/span>.Information, 2);<br \/>\n<span style=\"color: #0000ff;\">if <\/span>(machineName == &#8220;.&#8221;)<\/p>\n<p style=\"padding-left: 90px;\">sc = new ServiceController(serviceName);<\/p>\n<p style=\"padding-left: 60px;\">else<\/p>\n<p style=\"padding-left: 90px;\">sc = new ServiceController(serviceName, machineName);<\/p>\n<p style=\"padding-left: 60px;\"><span style=\"color: #0000ff;\">if <\/span>(sc.CanStop &amp;&amp; sc.Status != <span style=\"color: #0000ff;\">ServiceControllerStatus<\/span>.Stopped)<br \/>\n{<\/p>\n<p style=\"padding-left: 90px;\">sc.Stop();<br \/>\nsc.WaitForStatus(resultingStatus, <span style=\"color: #0000ff;\">new TimeSpan<\/span>(0, 0, waitTimeSec));<br \/>\nsc.Refresh();<br \/>\n<span style=\"color: #0000ff;\">if <\/span>(sc.Status != resultingStatus)<br \/>\n{<\/p>\n<p style=\"padding-left: 120px;\">LogProgress(string.Format(&#8220;The service {0}\\\\{1} did not stop properly in the time allowed!&#8221;, machineName, serviceName), <span style=\"color: #0000ff;\">EventLogEntryType<\/span>.Warning, 2);<\/p>\n<p style=\"padding-left: 90px;\">}<br \/>\n<span style=\"color: #008000;\">#if DEBUG<\/span><br \/>\nLogProgress(<span style=\"color: #0000ff;\">string<\/span>.Format(&#8220;The service {0}\\\\{1} stopped sucessfully&#8221;, machineName, serviceName), <span style=\"color: #0000ff;\">EventLogEntryType<\/span>.Information, 2);<br \/>\n<span style=\"color: #008000;\">#endif<\/span><\/p>\n<p style=\"padding-left: 60px;\">}<\/p>\n<p style=\"padding-left: 30px;\">}<br \/>\n<span style=\"color: #0000ff;\">catch <\/span>(<span style=\"color: #0000ff;\">Exception <\/span>ex)<br \/>\n{<\/p>\n<p style=\"padding-left: 60px;\">LogProgress(string.Format(&#8220;Error stopping service {0}\\\\{1}: {2}&#8221;, machineName, serviceName, ex.Message), <span style=\"color: #0000ff;\">EventLogEntryType<\/span>.Error, 2);<\/p>\n<p style=\"padding-left: 30px;\">}<\/p>\n<p>}<\/p>\n<p><span style=\"color: #0000ff;\">private static void<\/span> LogProgress(<span style=\"color: #0000ff;\">string <\/span>message, <span style=\"color: #0000ff;\">EventLogEntryType <\/span>elet, <span style=\"color: #0000ff;\">int<\/span> eventId)<br \/>\n{<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\">Console<\/span>.WriteLine(message);<br \/>\n<span style=\"color: #0000ff;\">EventLog<\/span>.WriteEntry(eventLogSource, message, elet, eventId);<\/p>\n<p>}<\/p><\/blockquote>\n<p>I&#8217;m not showing the StartService method as it is basically the same as the StopService method (with one or two extra &#8216;if&#8217;s).<\/p>\n<h2><span style=\"color: #800000;\">Alternatives<\/span><\/h2>\n<p>I considered powershell (for 0.834 seconds like Data would have said) but it is only really useful if you run them manually since you have to &#8216;sign&#8217; them and jump through a million hoops to get it working in a scheduled &#8216;hands-off&#8217; way. Yes I know this was done to make it more &#8216;secure&#8217; and avoid malicious stuff but it also makes it useless to solve a simple problem. With the amount of trouble you have to go through to get it working you might as well create a proper app like I did here to solve the issue.<\/p>\n<p>Find a copy <a title=\"SrvsBatchMan.zip\" href=\"http:\/\/www.hen.co.za\/downloads\/SrvsBatchMan.zip\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I recently had the &#8216;pleasure&#8217; to have some of my maintenance scripts that restart some &#8216;Windows Services&#8216; stopped working since &#8216;other&#8217; people installed stuff that creates new dependencies. The problem is that the normal commands like &#8216;net stop&#8217; or &#8216;sc &hellip;<\/p>\n<p class=\"read-more\"><a href=\"https:\/\/hen.co.za\/blog\/2011\/05\/scheduled-tasks-and-restarting-services\/\">Read more &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[7,9,303,26],"class_list":["post-249","post","type-post","status-publish","format-standard","hentry","category-development","tag-net","tag-code","tag-development","tag-services"],"_links":{"self":[{"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/posts\/249","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/comments?post=249"}],"version-history":[{"count":9,"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/posts\/249\/revisions"}],"predecessor-version":[{"id":257,"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/posts\/249\/revisions\/257"}],"wp:attachment":[{"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/media?parent=249"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/categories?post=249"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hen.co.za\/blog\/wp-json\/wp\/v2\/tags?post=249"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}