{"id":65033,"date":"2007-04-20T21:19:00","date_gmt":"2007-04-20T21:19:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2007\/04\/20\/how-can-i-write-a-script-that-increments-a-counter-each-time-a-log-file-is-updated\/"},"modified":"2007-04-20T21:19:00","modified_gmt":"2007-04-20T21:19:00","slug":"how-can-i-write-a-script-that-increments-a-counter-each-time-a-log-file-is-updated","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-write-a-script-that-increments-a-counter-each-time-a-log-file-is-updated\/","title":{"rendered":"How Can I Write a Script That Increments a Counter Each Time a Log File is Updated?"},"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 write a script that increments a counter each time a particular log file gets updated?<BR><BR>&#8212; HJ<\/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, HJ. You know, lately the Scripting Guy who writes this column has been victimized by a disturbing phenomenon: he keeps getting phone calls from machines. For the past several nights the phone has rung in the Scripting House, and each time there\u2019s been a computer on the other end: \u201cHello, this is an automated survey being conducted by \u2026.\u201d To tell you the truth, the Scripting Guy who writes this column doesn\u2019t like talking on the phone to begin with; as you might expect, then, he especially doesn\u2019t like talking on the phone to a machine. With that in mind, it probably goes without saying that he\u2019s developed his own \u201cautomated response\u201d to these surveys.<\/P>\n<P>And yet, as irritating as this is, these incidents <I>have<\/I> got him thinking about automated responses in general. Maybe, he thought, it would be possible to create an automated response mechanism for <I>Hey, Scripting Guy!<\/I> That shouldn\u2019t be too difficult, and it would save him a <I>ton<\/I> of work. To begin with, the mechanism would need the ability to pick out a few keywords and then use those keywords to determine the question that was being asked. The machine would then have to prepare a response using the traditional <I>Hey, Scripting Guy!<\/I> format: a series of nonsensical anecdotes, ramblings, and rhetorical questions followed by a script that actually solves the problem. After playing around with this for a little while he managed to come up with a mechanism that produced the following:<\/P><PRE class=\"codeSample\">Hey, HJ. You know, the Scripting Son pitched quite well last night; in fact, \nhe had [insert number] strikeouts and only walked [insert number]. Did you see \nthat new commercial? That has to be the [best\/worst] commercial we\u2019ve seen \nin a long time. That Scripting Editor, she sure is [mean], isn\u2019t she? As for \nPeter Costantini, the oldest living Scripting Guy \u2026.\n<\/PRE>\n<P>Well, you get the idea. We have to admit that it\u2019s an intriguing concept, and it <I>is<\/I> hard to tell the real column from the fake column. But it\u2019s a moot point: after all, even the Scripting Guy who writes this column would never be so lazy as to let a machine do all his work for him.<\/P>\n<P>With that in mind, why don\u2019t \u2026 we \u2026 take a look at a script that increments a counter each time a particular log file gets updated:<\/P><PRE class=\"codeSample\">intModifications = 0<\/p>\n<p>strComputer = &#8220;.&#8221;<\/p>\n<p>Set objWMIService = GetObject(&#8220;winmgmts:\\\\&#8221; &amp; strComputer &amp; &#8220;\\root\\cimv2&#8221;)<\/p>\n<p>Set colMonitoredEvents = objWMIService.ExecNotificationQuery _\n    (&#8220;SELECT * FROM __InstanceModificationEvent WITHIN 1 WHERE &#8221; _\n        &amp; &#8220;TargetInstance ISA &#8216;CIM_DataFile&#8217; and &#8221; _\n            &amp; &#8220;TargetInstance.Name=&#8217;C:\\\\Scripts\\\\Test.txt'&#8221;)<\/p>\n<p>Do\n    Set objLatestEvent = colMonitoredEvents.NextEvent\n    If objLatestEvent.TargetInstance.LastModified &lt;&gt; objLatestEvent.PreviousInstance.LastModified Then\n        intModifications = intModifications + 1\n        Wscript.Echo &#8220;File modified: &#8221; &amp; Now\n        Wscript.Echo &#8220;Number of modifications: &#8221; &amp; intModifications\n        Wscript.Echo\n    End If\nLoop\n<\/PRE>\n<P>Now comes the fun part: figuring out how this script actually works. As you can see, we start out in very simple fashion: we assign the value 0 to a variable named intModifications (which, needless to say, is the counter variable we\u2019ll use to keep a running count of each time the file in question gets modified). We then connect to the WMI service on the local computer, although \u2013 and stop us if you\u2019ve heard this one before \u2013 you can just as easily run the script against a remote computer; all you have to do is assign the name of that computer to the variable strComputer.<\/P>\n<P>That brings us to this crazy-looking chunk of code:<\/P><PRE class=\"codeSample\">Set colMonitoredEvents = objWMIService.ExecNotificationQuery _\n    (&#8220;SELECT * FROM __InstanceModificationEvent WITHIN 1 WHERE &#8221; _\n        &amp; &#8220;TargetInstance ISA &#8216;CIM_DataFile&#8217; and &#8221; _\n            &amp; &#8220;TargetInstance.Name=&#8217;C:\\\\Scripts\\\\Test.txt'&#8221;)\n<\/PRE>\n<P>Believe it or not, this is our event subscription query. We won\u2019t explain the ins and outs of event subscriptions in today\u2019s column; if you need more information on the subject you might want to take a look at our <A href=\"http:\/\/msevents.microsoft.com\/cui\/eventdetail.aspx?EventID=1032268754&amp;culture=en-US\" target=\"_blank\"><B>Scripting Week 2 webcast<\/B><\/A> on WMI events. In a nutshell, we\u2019re simply asking the script to check every second (<B>WITHIN 1<\/B>) to see if any new members of the <B>__InstanceModificationEvent <\/B>class have been created. (As the name implies, instances of this class are created any time an object is modified.) Of course, objects get modified all the time on a computer: processes use more (or less) CPU power; memory goes up and down; network connections are enabled and disabled. That\u2019s all well and good, except that we don\u2019t want to be notified when any of <I>those<\/I> things occur. Therefore, we\u2019ve added a couple stipulations to our query:<\/P>\n<TABLE class=\"\" cellSpacing=\"0\" cellPadding=\"0\" border=\"0\">\n<TBODY>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>We only want to be notified if the new instance (the <B>TargetInstance<\/B>) of the __InstanceModificationEvent class happens to be a file (CIM_DataFile).<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>We only want to be notified if this new file has a <B>Name<\/B> (path) of C:\\\\Scripts\\\\Test.txt.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<TABLE class=\"dataTable\" id=\"ETE\" 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>. What\u2019s that? Why the extra \\\u2019s in the file path? That\u2019s easy: as it turns out, the \\ is a reserved character in WMI. Therefore, any time you use a \\ in a Where clause you must \u201cescape\u201d the character; that simply means you have to preface each \\ with a second \\. As a result, C:\\Scripts\\Test.txt gets written as C:\\\\Scripts\\\\Test.txt.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Still with us? Good. Next we create a Do loop designed to run forever and ever; notice that we don\u2019t include any sort of exit condition (like, say, do until something happens, or do while something is true):<\/P><PRE class=\"codeSample\">Do\n<\/PRE>\n<P>Inside that loop, we then use this line of code to instruct the script to sit tight and wait until the target file (C:\\Scripts\\Test.txt) has been modified:<\/P><PRE class=\"codeSample\">Set objLatestEvent = colMonitoredEvents.NextEvent\n<\/PRE>\n<P>What happens if the file <I>never<\/I> gets modified? Nothing; the script will dutifully \u201cblock\u201d on that line of code until the universe collapses in on itself. And even then it will continue to wait for the file to be modified.<\/P>\n<P>But what happens if the file <I>does<\/I> get modified? That\u2019s going to do two things. First, it\u2019s going to create a new member of the __InstanceModificationEvent class. Second, because this new class member meets our event subscription criteria, that\u2019s going to cause the script to unblock. And that, in turn, causes the script to execute <I>this<\/I> line of code:<\/P><PRE class=\"codeSample\">If objLatestEvent.TargetInstance.LastModified &lt;&gt; objLatestEvent.PreviousInstance.LastModified Then\n<\/PRE>\n<P>Depending on how you want to look at things, this line of code might be optional. In testing the script we discovered that just opening the file, even without making a single change to it, triggered a new instance of the __InstanceModificationEvent class. We didn\u2019t like that; that made it difficult to separate times when someone actually modified the file from times when someone merely looked at the file. To get around that problem, we use the preceding line of code to determine when the file was last modified (something we do by checking the value of the <B>LastModified<\/B> property). In particular, what we do is compare the LastModified property for the latest version of the file (the TargetInstance) with the LastModified property of the previous version of the file (<B>PreviousInstance<\/B>); that is, we compare the file as it exists right now with the file as it existed before the new member of the __InstanceModificationEvent class was created. If the two dates and times match then we know that the file wasn\u2019t actually modified. <\/P>\n<P>And if they <I>don\u2019t<\/I> match that means that a change of some kind was made. Therefore, we run this little block of code:<\/P><PRE class=\"codeSample\">intModifications = intModifications + 1\nWscript.Echo &#8220;File modified: &#8221; &amp; Now\nWscript.Echo &#8220;Number of modifications: &#8221; &amp; intModifications\nWscript.Echo\n<\/PRE>\n<P>Here we start off by incrementing the counter variable intModifications by 1; that\u2019s because a new modification just took place. We then echo back two things: 1) the fact that the file has been modified, along with the current date and time (<B>Now<\/B>); and 2) the total number of modifications that have been made (intModifications). And then we loop around and repeat the process all over again.<\/P>\n<P>All in all, so easy a, uh, machine could have done it<\/P>\n<P>A couple of things to keep in mind here. First, we recommend that you run this script in a command window under the CScript script host. Why? Because that way the script will be able to write its notifications to the command window and keep running. If you run it under WScript, you\u2019ll need to dismiss several dialog boxes each time the file gets modified. Yuck.<\/P>\n<P>Second, tallying takes place only while the script is running; as you probably guessed if the script is terminated then you won\u2019t be able to keep track of modifications. (Plus the current tally will be erased forever.) Because of that, you might want to modify the script so that, instead of echoing information to the screen, it writes its tally to a text file. In addition, you might want to think about turning this into a permanent event consumer, something that would enable WMI to track file modifications without even needing a script. That\u2019s not necessarily hard, but it can be a little tricky. For more information on permanent event consumers, see the <A href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/aa393014.aspx\" target=\"_blank\"><B>WMI SDK<\/B><\/A> on MSDN.<\/P>\n<P>And now for the big question: who <I>did<\/I> write today\u2019s column? Was it the Scripting Guy who typically writes this column, or was it some cold, unthinking machine that parsed the question as best it could, began its reply with a series of totally unrelated and irrelevant anecdotes, and then simply parroted back a script it probably copied off the Scripting Editor\u2019s computer?<\/P>\n<P>You know, when you put it like that it <I>is<\/I> hard to tell, isn\u2019t it?<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I write a script that increments a counter each time a particular log file gets updated?&#8212; HJ Hey, HJ. You know, lately the Scripting Guy who writes this column has been victimized by a disturbing phenomenon: he keeps getting phone calls from machines. For the past several nights the phone [&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":[98,236,3,4,5,6],"class_list":["post-65033","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-logs-and-monitoring","tag-plain-text-logs","tag-scripting-guy","tag-scripting-techniques","tag-vbscript","tag-wmi"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I write a script that increments a counter each time a particular log file gets updated?&#8212; HJ Hey, HJ. You know, lately the Scripting Guy who writes this column has been victimized by a disturbing phenomenon: he keeps getting phone calls from machines. For the past several nights the phone [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/65033","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=65033"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/65033\/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=65033"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=65033"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=65033"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}