{"id":64393,"date":"2007-07-24T00:59:00","date_gmt":"2007-07-24T00:59:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2007\/07\/24\/how-can-i-check-every-30-minutes-to-see-if-a-file-has-been-modified\/"},"modified":"2007-07-24T00:59:00","modified_gmt":"2007-07-24T00:59:00","slug":"how-can-i-check-every-30-minutes-to-see-if-a-file-has-been-modified","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-check-every-30-minutes-to-see-if-a-file-has-been-modified\/","title":{"rendered":"How Can I Check Every 30 Minutes to See If a File Has Been Modified?"},"content":{"rendered":"<p><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> \n<P>Hey, Scripting Guy! How can I monitor an application\u2019s log file and issue an alert if the timestamp on that file hasn\u2019t changed in the last 30 minutes?<BR><BR>&#8212; JA <\/P><IMG height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"Script Center\" height=\"288\" alt=\"Script Center\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" align=\"right\" border=\"0\"><\/A> \n<P>Hey, JA. You know that\u2019s a very interesting question, and one that \u2013 say, wait a second. You\u2019re not JA from <I>Stanwood<\/I><I>, <\/I><I>WA<\/I> are you? Are you sure about that? Well, OK; we\u2019ll take your word for it, and we\u2019ll try to answer your question. But if you <I>are<\/I> from Stanwood, WA \u2026.<\/P>\n<P>Not that the Scripting Guy who writes this column has anything against Stanwood, WA, mind you; it\u2019s just that the Scripting Guy who writes this column has something against Stanwood, WA. The other day this Scripting Guy found himself with a little time to kill in Stanwood, the Scripting Son having to arrive in town some 90 minutes prior to a doubleheader with the Skagit Sox. Being behind on his work, and having snuck out of the office at noon in order to get to Stanwood on time, the Scripting Guy who writes this column was glad to have 90 minutes to kill: that gave him just enough time to go get some ice cream before the game started.<\/P>\n<P>Or so he thought. But here\u2019s a tip for you: if you ever find yourself in Stanwood, WA, don\u2019t bother looking for ice cream; they don\u2019t have any. With seemingly-plenty of time on his hands the Scripting Guy who writes this column walked over to a nearby shopping center, one chockfull of stores and restaurants, none of which actually sold ice cream. (You know, <I>real<\/I> ice cream, like a hot fudge sundae.) At one point the Scripting Guy who writes this column saw a huge sign proclaiming <B>Ice Cream<\/B>; as he rounded the corner, however, he discovered that the place was locked up tight as a drum.<\/P>\n<TABLE class=\"dataTable\" id=\"EPD\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\"><B>Note<\/B>. So did the ice cream shop gone out of business, or did they simply lock the doors and pull the blinds when they saw this Scripting Guy headed their way? Good question \u2026.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Eventually the Scripting Guy who writes this column gave up on finding an old-fashioned hot fudge sundae and decided to get some ice cream at McDonald\u2019s instead. \u201cOh, ice cream,\u201d said the girl behind the counter. \u201cWe\u2019re all out of ice cream \u2026.\u201d<\/P>\n<P>Right \u2026.<\/P>\n<P>In the end, the Scripting Guy who writes this column never did get his ice cream, and the Scripting Son and his team went on to lose both ends of the doubleheader. Coincidence? We think not.<\/P>\n<P>Oh, well; in the great good news\/bad news scheme of life, that\u2019s the bad news. The good news? With no hot fudge sundae to occupy his time, the Scripting Guy who writes this column was able to do something he hadn\u2019t really planned on doing: write this column.<\/P>\n<P>As you might expect, there are a number of different ways we could have approached the problem of monitoring a log file and issuing an alert if the timestamp on that file hasn\u2019t changed in the last 30 minutes. After carefully weighing all these alternative approaches can we assume that the Scripting Guys chose the best <I>possible<\/I> method for carrying out this task? Heavens no. However, you <I>can<\/I> assume that the Scripting Guys chose the <I>easiest<\/I> possible method for carrying out this task:<\/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 colFiles = objWMIService.ExecQuery _\n    (&#8220;Select * from CIM_Datafile Where Name = &#8216;C:\\\\Scripts\\\\Application.log'&#8221;)<\/p>\n<p>For Each objFile in colFiles\n    strOriginalTimestamp = objFile.LastModified\nNext<\/p>\n<p>Wscript.Echo &#8220;Monitoring application log file: &#8221; &amp; Now\nWscript.Echo<\/p>\n<p>Do While True\n    Wscript.Sleep 1800000\n    Set colFiles = objWMIService.ExecQuery _\n        (&#8220;Select * from CIM_Datafile Where Name = &#8216;C:\\\\Scripts\\\\Application.log'&#8221;)<\/p>\n<p>    For Each objFile in colFiles\n        strLatestTimestamp = objFile.LastModified\n    Next <\/p>\n<p>    If strLatestTimestamp &lt;&gt; strOriginalTimestamp Then\n        strOriginalTimestamp = strLatestTimeStamp\n    Else\n        Wscript.Echo &#8220;ALERT: &#8221; &amp; Now\n        Wscript.Echo &#8220;The application log file has not been modified in the last 30 minutes.&#8221;\n        Wscript.Echo\n        strOriginalTimestamp = strLatestTimeStamp\n    End If\nLoop\n<\/PRE>\n<P>Let\u2019s see if we can explain how this works. To begin with, we connect to the WMI service on the local computer. This was one of the first decisions we had to make: do we use WMI to carry out this task, or do we use some alternate technology, such as the FileSystemObject? We opted to go with WMI, and for one simple reason: this enables us to write a script that can monitor a log file on a remote computer just as easily as it can monitor a log file on the local computer. Need to perform this task against a log file on the remote computer atl-fs-01? No problem; just assign the name of that computer to the variable strComputer:<\/P><PRE class=\"codeSample\">strComputer = &#8220;atl-fs-01&#8221;\n<\/PRE>\n<P>Our next step is to determine the last time the file was changed; we need to know the current value of the file\u2019s <B>LastModified<\/B> property in order to tell whether or not that value (and thus the file itself) has changed in the past 30 minutes. With that in mind, we use this line of code to select all the instances of the <B>CIM_Datafile<\/B> class that have a <B>Name<\/B> (path) equal to C:\\\\Scripts\\\\Application.log:<\/P><PRE class=\"codeSample\">Set colFiles = objWMIService.ExecQuery _\n    (&#8220;Select * from CIM_Datafile Where Name = &#8216;C:\\\\Scripts\\\\Application.log'&#8221;)\n<\/PRE>\n<P>And yes, that <I>is<\/I> C:<B>\\\\<\/B>Scripts<B>\\\\<\/B>. Because the \\ is a reserved character in WMI, any \\ that appears in a WQL query needs to be \u201cescaped;\u201d that is, we need to preface it with another \\.<\/P>\n<P>Admittedly that\u2019s a little strange. But nowhere near as strange as a town completely devoid of ice cream.<\/P>\n<P>After making the connection we set up a For Each loop to loop through the collection of files returned by the query. (Needless to say, there can be only one such file in the collection.) We then use this line of code to assign the value of the LastModified property to a variable named strOriginalTimestamp:<\/P><PRE class=\"codeSample\">strOriginalTimestamp = objFile.LastModified\n<\/PRE>\n<P>All of that is required just to give us a starting point; now we need to do some real work. To that end, we set up a Do While loop designed to run forever and ever (or at least for as long as True is equal to True):<\/P><PRE class=\"codeSample\">Do While True\n<\/PRE>\n<P>What\u2019s the first thing we do inside that loop? In a sense, nothing at all; the first thing we do is call the <B>Sleep <\/B>method and pause the script for 30 minutes:<\/P><PRE class=\"codeSample\">Wscript.Sleep 1800000\n<\/PRE>\n<TABLE class=\"dataTable\" id=\"EOF\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\"><B>Note<\/B>. In case you\u2019re wondering, the 1800000 represents 1,800,000 milliseconds. There are 1,000 milliseconds in a second; 60,000 milliseconds in a minute; and 1,800,000 milliseconds in 30 minutes (1,000 x 60 x 30).<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>When those 30 minutes are up we check the <I>current<\/I> value of the log\u2019s LastModified property; to do that, we reconnect to the file, then store the value of the LastModified property in a variable named strLatestTimestamp:<\/P><PRE class=\"codeSample\">strLatestTimestamp = objFile.LastModified\n<\/PRE>\n<P>That brings us to this line of code:<\/P><PRE class=\"codeSample\">If strLatestTimestamp &lt;&gt; strOriginalTimestamp Then\n<\/PRE>\n<P>What are we doing here? Well, here we\u2019re comparing the original timestamp with the current timestamp. Suppose the two timestamps are different; what does that mean? That can only man one thing: the file must have been modified sometime during the past 30 minutes. Therefore, we simply assign the current timestamp (strLatestTimestamp) to the variable strOriginalTimestamp, loop around, pause the script for another 30 minutes, then perform this check again.<\/P>\n<P>That was easy. Now, what if the two timestamps are <I>identical<\/I>? Again, there\u2019s only one possible explanation: if the two timestamps are identical that means the file must <I>not<\/I> have been modified in the past 30 minutes. In that case, we use the following lines of code to echo a message back to the command window (and yes, like most monitoring scripts you <I>really<\/I> want to run this one in a command window under the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/begin\/ss1006.mspx\"><B>CScript script host<\/B><\/A>):<\/P><PRE class=\"codeSample\">Wscript.Echo &#8220;ALERT: &#8221; &amp; Now\nWscript.Echo &#8220;The application log file has not been modified in the last 30 minutes.&#8221;\nWscript.Echo\n<\/PRE>\n<P>That\u2019s going to result in a message similar to this appearing onscreen:<\/P><PRE class=\"codeSample\">ALERT: 7\/20\/2007 1:26:35 PM\nThe application log file has not been modified in the last 30 minutes.\n<\/PRE>\n<P>We then assign the current timestamp to the variable strOriginalTimestamp, loop around, pause the script for another 30 minutes, then perform the check again. This process continues until the end of time, or until you terminate the script or close the command window.<\/P>\n<P>Whichever comes first. And we\u2019re guessing all of those things will happen long before they get any ice cream in Stanwood.<\/P>\n<P>Needless to say, you aren\u2019t limited to echoing back an alert; if you want to you can send an email, write an event to the event log, or do pretty much anything else you want. We\u2019ll leave that up to you.<\/P>\n<P>We hope that answers your question, JA. If it turns out that you really <I>are<\/I> JA from Stanwood, WA then no doubt you have another question as well: you\u2019re wondering if the Scripting Guy who writes this column will hold it against you just because he couldn\u2019t find any ice cream in your town. Well, JA, the answer to your unasked question is this: you bet he does. But don\u2019t worry; just send a hot fudge sundae to the following address and we\u2019ll call it good:<\/P>\n<P>The Scripting Guy Who Writes That Column<BR>Microsoft Corporation<BR>Building 42\/4039<BR>Redmond, WA 98052<\/P>\n<P>P.S. Extra whipped cream, and no maraschino cherry. Thanks!<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I monitor an application\u2019s log file and issue an alert if the timestamp on that file hasn\u2019t changed in the last 30 minutes?&#8212; JA Hey, JA. You know that\u2019s a very interesting question, and one that \u2013 say, wait a second. You\u2019re not JA from Stanwood, WA are you? Are [&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":[42,38,3,4,12,5],"class_list":["post-64393","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-events-and-monitoring","tag-files","tag-scripting-guy","tag-scripting-techniques","tag-storage","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I monitor an application\u2019s log file and issue an alert if the timestamp on that file hasn\u2019t changed in the last 30 minutes?&#8212; JA Hey, JA. You know that\u2019s a very interesting question, and one that \u2013 say, wait a second. You\u2019re not JA from Stanwood, WA are you? Are [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/64393","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=64393"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/64393\/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=64393"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=64393"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=64393"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}