<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="https://wiki.ledhed.net/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://wiki.ledhed.net/index.php?action=history&amp;feed=atom&amp;title=Logging_Application_Usage</id>
		<title>Logging Application Usage - Revision history</title>
		<link rel="self" type="application/atom+xml" href="https://wiki.ledhed.net/index.php?action=history&amp;feed=atom&amp;title=Logging_Application_Usage"/>
		<link rel="alternate" type="text/html" href="https://wiki.ledhed.net/index.php?title=Logging_Application_Usage&amp;action=history"/>
		<updated>2026-05-22T18:40:56Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.23.2</generator>

	<entry>
		<id>//wiki.ledhed.net/index.php?title=Logging_Application_Usage&amp;diff=2620&amp;oldid=prev</id>
		<title>Ledhed: Created page with 'As an admin from time to time you have a need to log application time. For example you are asked by HR to monitor how many hours an employee spends playing games. Here is a VBScr...'</title>
		<link rel="alternate" type="text/html" href="https://wiki.ledhed.net/index.php?title=Logging_Application_Usage&amp;diff=2620&amp;oldid=prev"/>
				<updated>2012-01-20T00:02:25Z</updated>
		
		<summary type="html">&lt;p&gt;Created page with &amp;#039;As an admin from time to time you have a need to log application time. For example you are asked by HR to monitor how many hours an employee spends playing games. Here is a VBScr...&amp;#039;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;As an admin from time to time you have a need to log application time.&lt;br /&gt;
For example you are asked by HR to monitor how many hours an employee spends playing games.&lt;br /&gt;
Here is a VBScript that will accomplish just that.&lt;br /&gt;
&lt;br /&gt;
== The Script ==&lt;br /&gt;
&lt;br /&gt;
 On Error Resume Next&lt;br /&gt;
 &lt;br /&gt;
 '******************************************************************************&lt;br /&gt;
 'Change block - change values to fit local environment.&lt;br /&gt;
 strCompList = &amp;quot;complist.txt&amp;quot;&lt;br /&gt;
 strProcList = &amp;quot;proclist.txt&amp;quot;&lt;br /&gt;
 g_strOutputFile = &amp;quot;applog.txt&amp;quot;&lt;br /&gt;
 Const MON_TIME = 3600 'seconds script should run&lt;br /&gt;
 Const MAX_TIME = 3600 'seconds - time limit on processes&lt;br /&gt;
 '******************************************************************************&lt;br /&gt;
 &lt;br /&gt;
 Dim g_arrTimeCounters() 'time counters for each app&lt;br /&gt;
 Dim g_arrFreqCounters() 'frequency of usage counters for each app&lt;br /&gt;
 Dim g_arrOverCounters() 'over-limit usage counters for each app&lt;br /&gt;
 arrComputers = ReadTextFile(strCompList)&lt;br /&gt;
 g_arrTargetProcs = ReadTextFile(strProcList)&lt;br /&gt;
 &lt;br /&gt;
 'Redim counter arrays to same size as target process array&lt;br /&gt;
 intUBound = UBound(g_arrTargetProcs)&lt;br /&gt;
 Redim g_arrTimeCounters(intUBound)&lt;br /&gt;
 Redim g_arrFreqCounters(intUBound)&lt;br /&gt;
 Redim g_arrOverCounters(intUBound)&lt;br /&gt;
 &lt;br /&gt;
 'Initialize all counters to 0.&lt;br /&gt;
 For Each intTimeCounter In g_arrTimeCounters&lt;br /&gt;
   intTimeCounter = 0&lt;br /&gt;
 Next&lt;br /&gt;
 For Each intFreqCounter In g_arrFreqCounters&lt;br /&gt;
   intFreqCounter = 0&lt;br /&gt;
 Next&lt;br /&gt;
 For Each intOverCounter In g_arrOverCounters&lt;br /&gt;
   intOverCounter = 0&lt;br /&gt;
 Next&lt;br /&gt;
 &lt;br /&gt;
 strMessageHeader = vbCrLf &amp;amp; &amp;quot;Target processes:&amp;quot; &amp;amp; vbCrLf&lt;br /&gt;
 For Each strTargetProc In g_arrTargetProcs&lt;br /&gt;
   strMessageHeader = strMessageHeader &amp;amp; strTargetProc &amp;amp; vbCrLf&lt;br /&gt;
 Next&lt;br /&gt;
 strMessageHeader = strMessageHeader &amp;amp; vbCrLf &amp;amp; &amp;quot;Querying machines on list:&amp;quot;&lt;br /&gt;
 WScript.Echo strMessageHeader&lt;br /&gt;
 WriteTextFile g_strOutputFile, strMessageHeader&lt;br /&gt;
 &lt;br /&gt;
 Set SINK = WScript.CreateObject(&amp;quot;WbemScripting.SWbemSink&amp;quot;,&amp;quot;SINK_&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 For Each strComputer In arrComputers&lt;br /&gt;
   strMessageHost = vbCrLf &amp;amp; &amp;quot;Host: &amp;quot; &amp;amp; strComputer&lt;br /&gt;
   WScript.Echo strMessageHost&lt;br /&gt;
   WriteTextFile g_strOutputFile, strMessageHost&lt;br /&gt;
 &lt;br /&gt;
   Set g_objWMIService = GetObject(&amp;quot;winmgmts:&amp;quot; _&lt;br /&gt;
    &amp;amp; &amp;quot;{impersonationLevel=impersonate}!\\&amp;quot; &amp;amp; strComputer &amp;amp; &amp;quot;\root\cimv2&amp;quot;)&lt;br /&gt;
   If Err = 0 Then&lt;br /&gt;
     QueryProcess strComputer&lt;br /&gt;
   Else&lt;br /&gt;
     HandleError strComputer, &amp;quot;Unable to bind to WMI on host.&amp;quot;&lt;br /&gt;
   End If&lt;br /&gt;
 Next&lt;br /&gt;
 &lt;br /&gt;
 strMessageMon = vbCrLf &amp;amp; &amp;quot;Monitoring start time: &amp;quot; &amp;amp; Now &amp;amp; vbCrLf &amp;amp; _&lt;br /&gt;
  &amp;quot;In monitoring mode for &amp;quot; &amp;amp; SecsToHours(MON_TIME) &amp;amp; vbCrLf &amp;amp; _&lt;br /&gt;
  &amp;quot; ... Ctrl+C to end&amp;quot; &amp;amp; vbCrLf &amp;amp; _&lt;br /&gt;
  &amp;quot;----------------------------------------------------&amp;quot;&lt;br /&gt;
 WScript.Echo strMessageMon&lt;br /&gt;
 WriteTextFile g_strOutputFile, strMessageMon&lt;br /&gt;
 &lt;br /&gt;
 WScript.Sleep MON_TIME * 1000&lt;br /&gt;
 &lt;br /&gt;
 strMessageSum = _&lt;br /&gt;
  vbCrLf &amp;amp; &amp;quot;--------------------------------------------------  &amp;quot; &amp;amp; _&lt;br /&gt;
  vbCrLf &amp;amp; &amp;quot;Monitoring finish time: &amp;quot; &amp;amp; Now &amp;amp; vbCrLf &amp;amp; _&lt;br /&gt;
  vbCrLf &amp;amp; &amp;quot;Application usage:&amp;quot;&lt;br /&gt;
 For i = 0 To UBound(g_arrTargetProcs)&lt;br /&gt;
   strMessageSum = strMessageSum &amp;amp; vbCrLf &amp;amp; vbCrLf &amp;amp; &amp;quot;Application: &amp;quot; &amp;amp; _&lt;br /&gt;
   g_arrTargetProcs(i) &amp;amp; vbCrLf &amp;amp; _&lt;br /&gt;
   &amp;quot;  Total Duration: &amp;quot; &amp;amp; SecsToHours(CInt(g_arrTimeCounters(i))) &amp;amp; vbCrLf &amp;amp; _&lt;br /&gt;
   &amp;quot;  Number of Uses: &amp;quot; &amp;amp; CInt(g_arrFreqCounters(i)) &amp;amp; vbCrLf &amp;amp; _&lt;br /&gt;
   &amp;quot;  Number of Uses over Time Limit: &amp;quot; &amp;amp; CInt(g_arrOverCounters(i))&lt;br /&gt;
 Next&lt;br /&gt;
 WScript.Echo strMessageSum&lt;br /&gt;
 WriteTextFile g_strOutputFile, strMessageSum&lt;br /&gt;
 &lt;br /&gt;
 '******************************************************************************&lt;br /&gt;
 &lt;br /&gt;
 Sub QueryProcess(strHost)&lt;br /&gt;
 &lt;br /&gt;
 On Error Resume Next&lt;br /&gt;
 &lt;br /&gt;
 Set objContext = CreateObject(&amp;quot;WbemScripting.SWbemNamedValueSet&amp;quot;)&lt;br /&gt;
 objContext.Add &amp;quot;hostname&amp;quot;, strHost&lt;br /&gt;
 &lt;br /&gt;
 'Query host asynchronously for process creation events.&lt;br /&gt;
 For Each strTargetProc In g_arrTargetProcs&lt;br /&gt;
   strQuery = &amp;quot;SELECT * FROM __InstanceDeletionEvent WITHIN 10 &amp;quot; &amp;amp; _&lt;br /&gt;
    &amp;quot;WHERE TargetInstance ISA 'Win32_Process' &amp;quot; &amp;amp; _&lt;br /&gt;
    &amp;quot;AND TargetInstance.Name = '&amp;quot; &amp;amp; strTargetProc &amp;amp; &amp;quot;'&amp;quot;&lt;br /&gt;
   g_objWMIService.ExecNotificationQueryAsync SINK, _&lt;br /&gt;
    strQuery, , , , objContext&lt;br /&gt;
 Next&lt;br /&gt;
 If Err = 0 Then&lt;br /&gt;
   strMessageTNP = vbCrLf &amp;amp; &amp;quot;  Monitoring target processes.&amp;quot;&lt;br /&gt;
   WScript.Echo strMessageTNP&lt;br /&gt;
   WriteTextFile g_strOutputFile, strMessageTNP&lt;br /&gt;
 Else&lt;br /&gt;
   HandleError strHost, &amp;quot;  Unable to run asynchronous query.&amp;quot;&lt;br /&gt;
 End If&lt;br /&gt;
 &lt;br /&gt;
 End Sub&lt;br /&gt;
 &lt;br /&gt;
 '******************************************************************************&lt;br /&gt;
 &lt;br /&gt;
 Sub SINK_OnObjectReady(objLatestEvent, objAsyncContext)&lt;br /&gt;
 'Trap asynchronous events.&lt;br /&gt;
 &lt;br /&gt;
 Set objAsyncContextItem = objAsyncContext.Item(&amp;quot;hostname&amp;quot;)&lt;br /&gt;
 strHost = objAsyncContextItem.Value&lt;br /&gt;
 strProcName = objLatestEvent.TargetInstance.Name&lt;br /&gt;
 strProcID = objLatestEvent.TargetInstance.ProcessId&lt;br /&gt;
 &lt;br /&gt;
 Set objDateTime1 = CreateObject(&amp;quot;WbemScripting.SWbemDateTime&amp;quot;)&lt;br /&gt;
 objDateTime1.Value = objLatestEvent.TargetInstance.CreationDate&lt;br /&gt;
 vtmCreated = objDateTime1.GetVarDate&lt;br /&gt;
 &lt;br /&gt;
 Set objDateTime2 = CreateObject(&amp;quot;WbemScripting.SWbemDateTime&amp;quot;)&lt;br /&gt;
 objDateTime2.SetFileTime objLatestEvent.TIME_CREATED, False&lt;br /&gt;
 vtmDeleted = objDateTime2.GetVarDate&lt;br /&gt;
 &lt;br /&gt;
 intDuration = DateDiff(&amp;quot;s&amp;quot;, vtmCreated, vtmDeleted)&lt;br /&gt;
 &lt;br /&gt;
 If intDuration &amp;gt; MAX_TIME Then&lt;br /&gt;
   strTimeLimit = &amp;quot;  Over time limit&amp;quot;&lt;br /&gt;
 Else&lt;br /&gt;
   strTimeLimit = &amp;quot;  Not over time limit&amp;quot;&lt;br /&gt;
 End If&lt;br /&gt;
 &lt;br /&gt;
 strSinkData = VbCrLf &amp;amp; &amp;quot;Computer Name: &amp;quot; &amp;amp; strHost &amp;amp; vbCrLf &amp;amp; _&lt;br /&gt;
  &amp;quot;Process Name: &amp;quot; &amp;amp; strProcName &amp;amp; VbCrLf &amp;amp; _&lt;br /&gt;
  &amp;quot;Process ID: &amp;quot; &amp;amp; strProcID &amp;amp; VbCrLf &amp;amp; _&lt;br /&gt;
  &amp;quot;  Time created: &amp;quot; &amp;amp; vtmCreated &amp;amp; VbCrLf &amp;amp; _&lt;br /&gt;
  &amp;quot;  Time deleted: &amp;quot; &amp;amp; vtmDeleted &amp;amp; VbCrLf &amp;amp; _&lt;br /&gt;
  &amp;quot;  Duration: &amp;quot; &amp;amp; SecsToHours(intDuration) &amp;amp; VbCrLf &amp;amp; _&lt;br /&gt;
  strTimeLimit&lt;br /&gt;
 WScript.Echo strSinkData&lt;br /&gt;
 WriteTextFile g_strOutputFile, strSinkData&lt;br /&gt;
 &lt;br /&gt;
 'Increment time and frequency counters for app.&lt;br /&gt;
 intCount = 0&lt;br /&gt;
 For intCount = 0 to UBound(g_arrTargetProcs)&lt;br /&gt;
   If g_arrTargetProcs(intCount) = objLatestEvent.TargetInstance.Name Then&lt;br /&gt;
     g_arrTimeCounters(intCount) = g_arrTimeCounters(intCount) + intDuration&lt;br /&gt;
     g_arrFreqCounters(intCount) = g_arrFreqCounters(intCount) + 1&lt;br /&gt;
     If intDuration &amp;gt; MAX_TIME Then&lt;br /&gt;
       g_arrOverCounters(intCount) = g_arrOverCounters(intCount) + 1&lt;br /&gt;
     End If&lt;br /&gt;
   End If&lt;br /&gt;
 Next&lt;br /&gt;
 &lt;br /&gt;
 End Sub&lt;br /&gt;
 &lt;br /&gt;
 '******************************************************************************&lt;br /&gt;
 &lt;br /&gt;
 Function ReadTextFile(strFileName)&lt;br /&gt;
 'Read lines of text file and return array with one element for each line.&lt;br /&gt;
 &lt;br /&gt;
 On Error Resume Next&lt;br /&gt;
 &lt;br /&gt;
 Const FOR_READING = 1&lt;br /&gt;
 &lt;br /&gt;
 Set objFSO = CreateObject(&amp;quot;Scripting.FileSystemObject&amp;quot;)&lt;br /&gt;
 If objFSO.FileExists(strFilename) Then&lt;br /&gt;
   Set objTextStream = objFSO.OpenTextFile(strFilename, FOR_READING)&lt;br /&gt;
 Else&lt;br /&gt;
   strRTFMessage1 = VbCrLf &amp;amp; &amp;quot;Input text file &amp;quot; &amp;amp; strFilename &amp;amp; &amp;quot; not found.&amp;quot;&lt;br /&gt;
   Wscript.Echo strRTFMessage1&lt;br /&gt;
   WriteTextFile g_strOutputFile, strRTFMessage1&lt;br /&gt;
   WScript.Quit(1)&lt;br /&gt;
 End If&lt;br /&gt;
 &lt;br /&gt;
 If objTextStream.AtEndOfStream Then&lt;br /&gt;
   strRTFMessage2 = VbCrLf &amp;amp; &amp;quot;Input text file &amp;quot; &amp;amp; strFilename &amp;amp; &amp;quot; is empty.&amp;quot;&lt;br /&gt;
   Wscript.Echo strRTFMessage2&lt;br /&gt;
   WriteTextFile g_strOutputFile, strRTFMessage2&lt;br /&gt;
   WScript.Quit(2)&lt;br /&gt;
 End If&lt;br /&gt;
 &lt;br /&gt;
 strFileContents = objTextStream.ReadAll&lt;br /&gt;
 arrLines = Split(strFileContents, vbCrLf)&lt;br /&gt;
 &lt;br /&gt;
 objTextStream.Close&lt;br /&gt;
 &lt;br /&gt;
 ReadTextFile = arrLines&lt;br /&gt;
 &lt;br /&gt;
 End Function&lt;br /&gt;
 &lt;br /&gt;
 '******************************************************************************&lt;br /&gt;
 &lt;br /&gt;
 'Write or append data to text file.&lt;br /&gt;
 Sub WriteTextFile(strFileName, strOutput)&lt;br /&gt;
 &lt;br /&gt;
 On Error Resume Next&lt;br /&gt;
 &lt;br /&gt;
 Const FOR_APPENDING = 8&lt;br /&gt;
 &lt;br /&gt;
 'Open text file for output.&lt;br /&gt;
 Set objFSO = CreateObject(&amp;quot;Scripting.FileSystemObject&amp;quot;)&lt;br /&gt;
 If objFSO.FileExists(strFileName) Then&lt;br /&gt;
   Set objTextStream = objFSO.OpenTextFile(strFileName, FOR_APPENDING)&lt;br /&gt;
 Else&lt;br /&gt;
   Set objTextStream = objFSO.CreateTextFile(strFileName)&lt;br /&gt;
 End If&lt;br /&gt;
 &lt;br /&gt;
 'Write data to file.&lt;br /&gt;
 objTextStream.WriteLine strOutput&lt;br /&gt;
 &lt;br /&gt;
 objTextStream.Close&lt;br /&gt;
 &lt;br /&gt;
 End Sub&lt;br /&gt;
 &lt;br /&gt;
 '******************************************************************************&lt;br /&gt;
 &lt;br /&gt;
 Function SecsToHours(intTotalSecs)&lt;br /&gt;
 'Convert time in seconds to hours, minutes, seconds and return in string.&lt;br /&gt;
 &lt;br /&gt;
 intHours = intTotalSecs \ 3600&lt;br /&gt;
 intMinutes = (intTotalSecs Mod 3600) \ 60&lt;br /&gt;
 intSeconds = intTotalSecs Mod 60&lt;br /&gt;
 &lt;br /&gt;
 SecsToHours = intHours &amp;amp; &amp;quot; hours, &amp;quot; &amp;amp; intMinutes &amp;amp; &amp;quot; minutes, &amp;quot; &amp;amp; _&lt;br /&gt;
  intSeconds &amp;amp; &amp;quot; seconds&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 End Function&lt;br /&gt;
 &lt;br /&gt;
 '******************************************************************************&lt;br /&gt;
 &lt;br /&gt;
 Sub HandleError(strHost, strMsg)&lt;br /&gt;
 'Handle errors.&lt;br /&gt;
 &lt;br /&gt;
 strError = VbCrLf &amp;amp; &amp;quot;  ERROR on &amp;quot; &amp;amp; strHost &amp;amp; VbCrLf &amp;amp; _&lt;br /&gt;
  &amp;quot;  Number: &amp;quot; &amp;amp; Err.Number &amp;amp; VbCrLf &amp;amp; _&lt;br /&gt;
  &amp;quot;  Description: &amp;quot; &amp;amp; Err.Description &amp;amp; VbCrLf &amp;amp; _&lt;br /&gt;
  &amp;quot;  Source: &amp;quot; &amp;amp; Err.Source &amp;amp; VbCrLf &amp;amp; _&lt;br /&gt;
  &amp;quot;  Explanation: &amp;quot; &amp;amp; strMsg&lt;br /&gt;
 WScript.Echo strError&lt;br /&gt;
 WriteTextFile g_strOutputFile, strError&lt;br /&gt;
 Err.Clear&lt;br /&gt;
 &lt;br /&gt;
 End Sub&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Supporting Files ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== proclist.txt ===&lt;br /&gt;
proclist.txt contains a list of processes you'd like to monitor usage.&lt;br /&gt;
One process per line.&lt;br /&gt;
'''Example:'''&lt;br /&gt;
 sol.exe&lt;br /&gt;
 winmine.exe&lt;br /&gt;
 iexplore.exe&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== complist.txt ===&lt;br /&gt;
complist.txt contains a list of computer names you'd like to monitor appliactions on.&lt;br /&gt;
One computer per line.&lt;br /&gt;
'''Example:'''&lt;br /&gt;
 comp-1&lt;br /&gt;
 comp-2&lt;br /&gt;
 file-srvr&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== applog.txt ===&lt;br /&gt;
This file contains the logging information gathered by the script.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
You can configure settings within the script to achieve the desired behavior:&lt;br /&gt;
&lt;br /&gt;
 MON_TIME = 60 'seconds script should run&lt;br /&gt;
 MAX_TIME = 10 'seconds - time limit on processes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Reference ==&lt;br /&gt;
http://technet.microsoft.com/en-us/library/ee692850.aspx#EDAA&lt;br /&gt;
&lt;br /&gt;
[[Category:Windows]]&lt;/div&gt;</summary>
		<author><name>Ledhed</name></author>	</entry>

	</feed>