{"id":65413,"date":"2007-03-01T01:05:00","date_gmt":"2007-03-01T01:05:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2007\/03\/01\/how-can-i-get-the-uptime-of-a-service\/"},"modified":"2007-03-01T01:05:00","modified_gmt":"2007-03-01T01:05:00","slug":"how-can-i-get-the-uptime-of-a-service","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-get-the-uptime-of-a-service\/","title":{"rendered":"How Can I Get the Uptime of a Service?"},"content":{"rendered":"<p><H2><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"> <\/H2>\n<P>Hey, Scripting Guy! How can I get the uptime of a service?<BR><BR>&#8212; JC<\/P><IMG border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"Script Center\" border=\"0\" alt=\"Script Center\" align=\"right\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" height=\"288\"><\/A> \n<P>Hey, JC. You know, if you could have seen the Scripting Guy who writes this column this morning you would have reconsidered asking <I>him<\/I> a question about uptime. Although he woke up in plenty of time, even turning off the alarm before it was due to sound, he had a \u2026 little \u2026 trouble actually getting up out of bed. Five minutes past the appointed hour and he was still lying there; ten minutes past the appointed hour and he was still lying there \u2013 if he hadn\u2019t had to go to the bathroom he might <I>still<\/I> be in bed. And while he eventually did get out of bed, whether or not he actually woke up is debatable.<\/P>\n<P>Of course, with this Scripting Guy it\u2019s almost-always debatable whether he\u2019s awake or asleep anyway. For example, last year the Scripting Son had a high school baseball game out of town. At the start of the game the Scripting Guy who writes this column was the only fan in the stands. A short time later another fan showed up and somewhat hesitantly asked the Scripting Guy if he knew who was winning. \u201cIt\u2019s 2-to-2 in the top of the second. Brandon hit the ball hard his first time out, but the shortstop made a nice play and threw him out at first. However, he did get an RBI by knocking Barrett in.\u201d<\/P>\n<P>The other fan was taken aback. \u201cOh, I didn\u2019t know you knew anything about baseball,\u201d she said. \u201cYou\u2019re always so quiet, even when we score; I assumed you didn\u2019t know anything about the game. To tell you the truth, we always wondered why you even came to the games.\u201d<\/P>\n<P>That\u2019s OK; he\u2019s used to it. Besides, you have no idea how many times a hearse has come to haul this Scripting Guy away, despite his insistence that he was still alive. <I>(Editor\u2019s Note: What he doesn\u2019t know is that the hearse is always sent by the other Scripting Guys.)<\/I><\/P>\n<P>But enough with all that; let\u2019s get to work here. The Scripting Guys have always bragged that they could write system administration scripts in their sleep. We\u2019re about to put that notion to the test.<\/P>\n<P>To begin with, let\u2019s take a look at a script that lets you know the date and time that a service first started. As you\u2019ll soon see, there\u2019s a bit of a problem with this script: it doesn\u2019t report the service start time in user-friendly fashion. But that\u2019s OK; after we explain the basic concept behind determining the start time for a service we\u2019ll show you a much friendlier version.<\/P>\n<P>Here\u2019s the basic script for determining the date and time a service first started:<\/P><PRE class=\"codeSample\">strComputer = &#8220;.&#8221;<\/p>\n<p>Set objWMIService = GetObject(&#8220;winmgmts:\\\\&#8221; &amp; strComputer &amp; &#8220;\\root\\cimv2&#8221;)<\/p>\n<p>Set colServices = objWMIService.ExecQuery _\n    (&#8220;Select * From Win32_Service Where Name = &#8216;Spooler'&#8221;)<\/p>\n<p>For Each objService in colServices\n    intProcessID = objService.ProcessID<\/p>\n<p>    Set colProcesses = objWMIService.ExecQuery _\n        (&#8220;Select * From Win32_Process Where ProcessID = &#8221; &amp; intProcessID)<\/p>\n<p>    For Each objProcess in colProcesses\n        Wscript.Echo objProcess.CreationDate\n    Next\nNext\n<\/PRE>\n<P>As you can see, we start out by connecting to the WMI service on the local computer, although \u2013 that\u2019s right, you <I>can<\/I> run this script against a remote machine. (Hmmm, you don\u2019t think that, after two-and-half years, we\u2019re beginning to repeat ourselves in this column, do you?) Because we\u2019re interested in the uptime for just one service (in our example, the Print Spooler service), we then issue this query to return a collection of all the services that have the name <I>Spooler<\/I> (and, yes, because service names must be unique there will be only one such service):<\/P><PRE class=\"codeSample\">Set colServices = objWMIService.ExecQuery _\n    (&#8220;Select * From Win32_Service Where Name = &#8216;Spooler'&#8221;)\n<\/PRE>\n<P>Now, ideally, we\u2019d be done at this point: we\u2019d simply report back the date and time that the service started. That would be nice, but, for better or worse, the <B>Win32_Service<\/B> class doesn\u2019t include a property that tells us when the service started. So does that mean that all is lost? Yes, yes it does.<\/P>\n<P>Ha-ha; sometimes we crack ourselves up. No, in the wonderful world of scripting nothing is <I>ever<\/I> lost. While it\u2019s true that the Win32_Service class doesn\u2019t have a property that tells us when a service was started, it <I>does<\/I> have a property that tells us the process ID (PID) of the process in which the service is running. Is that useful? You bet it: we can take that PID and use it to retrieve process information from the <B>Win32_Process<\/B> class. Is <I>that<\/I> useful? Of course it is: after all, the Win32_Process class just happens to have a property (<B>CreationDate<\/B>) that tells us when the process started.<\/P>\n<TABLE id=\"EQE\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\"><B>Note<\/B>. OK, admittedly, this is not 100% foolproof. Why not? Because it\u2019s not unusual for services to run in shared processes; a single process might host multiple services, some of which might be running and some of which might <I>not<\/I> be running. However, this is the best we can do short of searching through the System event log and looking for service-related events involving, in this case, the Print Spooler service. If you\u2019re interested in trying that, search the System event log for events with an EventCode of 7036, which tracks changes in service status.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>After we get back our collection of services we use this line of code to grab the service PID and store it in a variable named intProcessID:<\/P><PRE class=\"codeSample\">intProcessID = objService.ProcessID\n<\/PRE>\n<P>Once we\u2019ve done that we can then retrieve a collection of all the processes that have that particular PID (again, there will be only one item in the resulting collection):<\/P><PRE class=\"codeSample\">Set colProcesses = objWMIService.ExecQuery _\n    (&#8220;Select * From Win32_Process Where ProcessID = &#8221; &amp; intProcessID)\n<\/PRE>\n<P>And then we set up a For Each loop to loop through the one-item collection. Inside that loop all we do is echo back the value of the CreationDate property:<\/P><PRE class=\"codeSample\">Wscript.Echo objProcess.CreationDate\n<\/PRE>\n<P>In turn that gives us output that looks something like this:<\/P><PRE class=\"codeSample\">20070227074100.796875-480\n<\/PRE>\n<P>Yuck. That\u2019s what we were talking about when we said that the information reported back by our first script wasn\u2019t very user-friendly. This isn\u2019t really the fault of the script; the problem is that WMI always reports dates and times as UTC (Universal Time Coordinate) values. Is it possible to convert a UTC value to something a little easier to understand? You bet it is:<\/P><PRE class=\"codeSample\">strComputer = &#8220;.&#8221;<\/p>\n<p>Set objWMIService = GetObject(&#8220;winmgmts:\\\\&#8221; &amp; strComputer &amp; &#8220;\\root\\cimv2&#8221;)<\/p>\n<p>Set colServices = objWMIService.ExecQuery _\n    (&#8220;Select * From Win32_Service Where Name = &#8216;Spooler'&#8221;)<\/p>\n<p>For Each objService in colServices\n    intProcessID = objService.ProcessID<\/p>\n<p>    Set colProcesses = objWMIService.ExecQuery _\n        (&#8220;Select * From Win32_Process Where ProcessID = &#8221; &amp; intProcessID)<\/p>\n<p>    For Each objProcess in colProcesses\n        dtmStartTime = objProcess.CreationDate<\/p>\n<p>        dtmConvertedDate = CDate(Mid(dtmStartTime, 5, 2) &amp; &#8220;\/&#8221; &amp; _\n            Mid(dtmStartTime, 7, 2) &amp; &#8220;\/&#8221; &amp; Left(dtmStartTime, 4) _\n                &amp; &#8221; &#8221; &amp; Mid (dtmStartTime, 9, 2) &amp; &#8220;:&#8221; &amp; _\n                    Mid(dtmStartTime, 11, 2) &amp; &#8220;:&#8221; &amp; Mid(dtmStartTime,13, 2))<\/p>\n<p>        Wscript.Echo DateDiff(&#8220;n&#8221;, dtmConvertedDate, Now)\n    Next\nNext\n<\/PRE>\n<P>We\u2019ve done two things with this modified script. First, we\u2019ve used this chunk of code to take the value of the CreationDate property and convert it to a \u201creal\u201d date-time value:<\/P><PRE class=\"codeSample\">dtmStartTime = objProcess.CreationDate<\/p>\n<p>dtmConvertedDate = CDate(Mid(dtmStartTime, 5, 2) &amp; &#8220;\/&#8221; &amp; _\n    Mid(dtmStartTime, 7, 2) &amp; &#8220;\/&#8221; &amp; Left(dtmStartTime, 4) _\n        &amp; &#8221; &#8221; &amp; Mid (dtmStartTime, 9, 2) &amp; &#8220;:&#8221; &amp; _\n            Mid(dtmStartTime, 11, 2) &amp; &#8220;:&#8221; &amp; Mid(dtmStartTime,13, 2))\n<\/PRE>\n<P>We won\u2019t discuss this code in any detail today; if you\u2019d like to know more about converting a UTC value to a standard date-time value take a look at <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/guide\/sas_wmi_yakv.mspx\"><B>this portion<\/B><\/A> of the <I>Microsoft Windows 2000 Scripting Guide<\/I>. Once we <I>do<\/I> convert the UTC value to a plain old date-time value we can then use the <B>DateDiff<\/B> function to report, in this case, the number of minutes that the process has been running:<\/P><PRE class=\"codeSample\">Wscript.Echo DateDiff(&#8220;n&#8221;, dtmConvertedDate, Now)\n<\/PRE>\n<P>As you can see, we pass DateDiff three parameters:<\/P>\n<TABLE border=\"0\" cellSpacing=\"0\" cellPadding=\"0\">\n<TBODY>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P><I>\u201cn\u201d<\/I> indicating the time interval to report. Here we\u2019re reporting the uptime in minutes; for other time intervals (seconds, hour, days, etc.) see the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/guide\/sas_vbs_ufbq.mspx\"><B>Scripting Guide<\/B><\/A>.<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P><I>dtmConvertedDate<\/I>, the date-time value we derived from the CreationDate property.<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P><I>Now<\/I>, the current date and time.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<P>This modified script reports the amount of time, in minutes, that the process has been running:<\/P><PRE class=\"codeSample\">225\n<\/PRE>\n<P>Like we said, it\u2019s not the perfect solution, but it\u2019s still a useful script to have in your arsenal. And it <I>does<\/I> work exceedingly well for services that run in their own process; that\u2019s because stopping a service also terminates the process. And how do you know which services run in their own process? Why, you use this script, of course:<\/P><PRE class=\"codeSample\">strComputer = &#8220;.&#8221;<\/p>\n<p>Set objWMIService = GetObject(&#8220;winmgmts:\\\\&#8221; &amp; strComputer &amp; &#8220;\\root\\cimv2&#8221;)<\/p>\n<p>Set colServices = objWMIService.ExecQuery _\n    (&#8220;Select * From Win32_Service Where ServiceType = &#8216;Own process'&#8221;)<\/p>\n<p>For Each objService in colServices\n    Wscript.Echo objService.DisplayName\nNext\n<\/PRE>\n<P>There you have it, JC. As for the Scripting Guy who writes this column, he\u2019s ready to call it a day. Is he all worn out after the fun and excitement of the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/funzone\/games\/default.mspx\"><B>2007 Winter Scripting Games<\/B><\/A>? No, not really; he\u2019s just lazy. But, in his defense, if he wasn\u2019t lazy then he really wouldn\u2019t be a Scripting Guy, would he?<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I get the uptime of a service?&#8212; JC Hey, JC. You know, if you could have seen the Scripting Guy who writes this column this morning you would have reconsidered asking him a question about uptime. Although he woke up in plenty of time, even turning off the alarm before [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[31,3,39,5],"class_list":["post-65413","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-operating-system","tag-scripting-guy","tag-services","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I get the uptime of a service?&#8212; JC Hey, JC. You know, if you could have seen the Scripting Guy who writes this column this morning you would have reconsidered asking him a question about uptime. Although he woke up in plenty of time, even turning off the alarm before [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/65413","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=65413"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/65413\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=65413"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=65413"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=65413"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}