I have an existing script, let's say this:
set cimv2=getobject("winmgmts:root\cimv2")
set evcol=cimv2.execquery("select * from win32_ntlogevent where logfile='System' and (sourcename='Microsoft-Windows-Kernel-General' or sourcename='Disk')")
for each evt in evcol
wscript.echo evt.timewritten & ": " & evt.sourcename & ", " & evt.type & ", " & evt.eventcode & ", " & evt.message
next
Is there a way that I can query the Windows Event Log using XPath query instead of WMI select query?
For example:
*[System[Provider[#Name='Microsoft-Windows-Disk' or #Name='Microsoft-Windows-Kernel-General']]]
Edit: I still want to have VBscript Collection as an object, not just execute "wevtutil".
The PowerShell Get-WinEvent cmdlet has a -FilterXPath parameter to which you can pass an XPath expression:
$xpath = "*[System[Provider[#Name='Microsoft-Windows-Disk' or #Name='Microsoft-Windows-Kernel-General']]]"
Get-WinEvent -LogName 'Security' -FilterXPath $xpath
In VBScript you'll need to shell out to wevutil and then load the XML data into a DOMDocument object:
Function qq(s) : qq = """" & s & """" : End Function
xpath = "*[System[Provider[#Name='Microsoft-Windows-Disk' or #Name='Microsoft-Windows-Kernel-General']]]"
datafile = "C:\temp.xml"
Set sh = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
Set evt = sh.Exec("cmd /c wevtutil qe Security /q:" & qq(xpath) & " > " & qq(datafile))
While evt.Status = 0 : WScript.Sleep 100 : Wend
Set xml = CreateObject("Msxml2.DOMDocument.6.0")
xml.async = False
xml.loadXML "<events>" & fso.OpenTextFile(datafile).ReadAll & "</events>"
If xml.parseError <> 0 Then
WScript.Echo xml.parseError.reason
WScript.Quit 1
End If
For further information on filtering event logs via XPath expressions see here.
Related
I would like to analyze the event log of a special windows application (Windows 7 Enterprise, 64Bit).
I need a special event which is logged some seconds ago.
Here is my VBScript code, which produces a completely wrong result (wrong number of events):
strComputer = "." ' Dieser Computer
' Retrieving Specific Events from an Event Log
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\" & strComputer & "\root\cimv2")
Const CONVERT_TO_LOCAL_TIME = True
Set dtmStartDate = CreateObject("WbemScripting.SWbemDateTime")
Set dtmEndDate = CreateObject("WbemScripting.SWbemDateTime")
dtmStartDate.SetVarDate dateadd("s", -10, now()) ' CONVERT_TO_LOCAL_TIME
dtmEndDate.SetVarDate now() ' CONVERT_TO_LOCAL_TIME
dim var_wql
var_wql = "SELECT * FROM Win32_NTLogEvent WHERE Logfile = '< ... >' AND SourceName = '< ... >' AND EventCode = '< ... >' AND (TimeWritten >= '" & dtmStartDate & "') AND (TimeWritten < '" & dtmEndDate & "')"
Set colLoggedEvents = objWMIService.ExecQuery(var_wql)
...
The number of rows (anzahl = colLoggedEvents.count) must be 0 or 1, anything else is impossible.
What is wrong with the wql statement? I would like to check the last seconds in the past (from now).
Thanks.
Tommy
Syntax error. If I change the objWMIService line to this, it works for me.
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\\" & strComputer & "\root\cimv2")
Updated to grab ALL event logs created in the last 10 secs and write to log file.
On Error Resume Next
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate,authenticationLevel=pktPrivacy}!\\.\root\cimv2")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set WshShell = WScript.CreateObject("WScript.Shell")
strSystemDrive = WshShell.ExpandEnvironmentStrings("%SystemDrive%")
Const CONVERT_TO_LOCAL_TIME = True
Set dtmStartDate = CreateObject("WbemScripting.SWbemDateTime")
Set dtmEndDate = CreateObject("WbemScripting.SWbemDateTime")
dtmStartDate.SetVarDate dateadd("s", -10, now()) ' CONVERT_TO_LOCAL_TIME
dtmEndDate.SetVarDate now() ' CONVERT_TO_LOCAL_TIME
var_wql = "SELECT * FROM Win32_NTLogEvent WHERE (TimeWritten >= '" & dtmStartDate & "') AND (TimeWritten < '" & dtmEndDate & "')"
Set LogFile = objFSO.CreateTextFile(strSystemDrive & "\Temp\EvtLog.txt", True)
Set colLoggedEvents = objWMIService.ExecQuery(var_wql)
For Each objEvent in colLoggedEvents
LogFile.WriteLine "Computer Name : " & objEvent.ComputerName
LogFile.WriteLine "Logfile : " & objEvent.Logfile
LogFile.WriteLine "Type : " & objEvent.Type
LogFile.WriteLine "User : " & objEvent.User
LogFile.WriteLine "Category : " & objEvent.Category
LogFile.WriteLine "Category String : " & objEvent.CategoryString
If IsArray(objEvent.Data) Then
For i = 0 To UBound(objEvent.Data)
strData = strData & objEvent.Data(i) & ","
Next
LogFile.WriteLine "Data : " & strData
Else
LogFile.WriteLine "Data : " & objEvent.Data
End If
LogFile.WriteLine "Event Code : " & objEvent.EventCode
LogFile.WriteLine "Event Identifier : " & objEvent.EventIdentifier
LogFile.WriteLine "Message : " & objEvent.Message
LogFile.WriteLine "Record Number : " & objEvent.RecordNumber
LogFile.WriteLine "Source Name : " & objEvent.SourceName
LogFile.WriteLine "Time Generated : " & objEvent.TimeGenerated
LogFile.WriteLine "Time Written : " & objEvent.TimeWritten
If IsArray(objEvent.InsertionStrings) Then
For i = 0 To UBound(objEvent.InsertionStrings)
strInsert = strInsert & objEvent.InsertionStrings(i) & ","
Next
LogFile.WriteLine "Insertion Strings: " & strInsert
Else
LogFile.WriteLine "Insertion Strings: " & objEvent.InsertionStrings
End If
LogFile.WriteLine "----------------------------------------------------------------------------------------------------------"
Next
Output sample (Not all fields used for every event) -
----------------------------------------------------------------------------------------------------------
Computer Name : Randy-PC
Logfile : Application
Type : Information
User :
Category : 0
Category String :
Data :
Event Code : 9019
Event Identifier : 1073750843
Message : The Desktop Window Manager was unable to start because the desktop composition setting is disabled
Record Number : 37395
Source Name : Desktop Window Manager
Time Generated : 20160903031728.000000-000
Time Written : 20160903031728.000000-000
Insertion Strings:
----------------------------------------------------------------------------------------------------------
I'm needing do a query on Google Chrome database SQLite3 for capture of all urls visited without use ODBC Driver or any other type of packet where is necessary your installation by final user.
Then I found that the way more near for this is using SQLite3.exe utilitary and SQLite3.dll (C:\Windows\System32\sqlite3.dll) in my opinion.
So I want know how I can list these urls based in code below?
Const LOCAL_APPLICATION_DATA = &H1c&
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace(LOCAL_APPLICATION_DATA)
Set objFolderItem = objFolder.Self
Set colItems = objFolder.Items
Dim sCurDir
Dim sFina
For Each objItem in colItems
If InStr(1, objItem.Name, "Google") > 0 Then
sCurDir = objFolderItem.Path + "\" + objItem.Name + "\Chrome\User Data\Default\"
sFina = "History"
Exit For
End If
Next
'Location of SQLite
strSQLlite = "sqlite3.exe"
strCommand = strSQLlite & " " & sCurDir + sFina & " " & "SELECT * FROM urls;"
Set objOutput = objShell.Exec (strCommand)
You need a shell to start the sqlite3.exe and to capture the output. As in:
Option Explicit
Function qq(s) : qq = """" & s & """" : End Function
Const cnHidden = 0
Const cbWait = True
Dim sCmd : sCmd = Join(Array( _
"%comspec%" _
, "/c" _
, "sqlite3.exe" _
, "-csv" _
, qq("..\data\History") _
, qq("SELECT id, url FROM urls LIMIT 5") _
, ">.\urls.csv" _
))
WScript.Echo sCmd
CreateObject("WScript.Shell").Run sCmd, cnHidden, cbWait
WScript.Echo "Done"
output:
cscript 36346886.vbs
%comspec% /c sqlite3.exe -csv "..\data\History" "SELECT id, url FROM urls LIMIT 5" >.\urls.csv
Done
type urls.csv
25,https://de.add-ons.mozilla.com/de/firefox/bookmarks/
31,http://public.fh-wolfenbuettel.de/~hoeppnef/hanserSWE.html
33,http://cartan.cas.suffolk.edu/moin/OopDocbookWiki
34,http://book.realworldhaskell.org/read/
35,http://book.realworldhaskell.org/read/types-and-functions.html
I made some effort to isolate the components of a successful command line. So make sure you understand the whats and whys of each part before you start to adapt the demo code to your specs and circumstances.
MsgBox ("Do you want to start the autoclicker?", vbOkOnly, "Autoclicker")
CreateObject("WScript.Shell").Run("""C:\Users\Henry\Desktop\Fun.vbs""")
MsgBox ("Do you want to stop the autoclicker?", vbOkOnly, "Autoclicker")
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_Process")
For Each objItem in colItems
'msgbox objItem.ProcessID & " " & objItem.CommandLine
If objItem.name = "Calculator.exe" then objItem.terminate
Next
This kills calculator.exe. Change it to wscript.exe. You might want to check command line if you just want to kill fun.vbs.
The following routine kills all processes whose command lines contain a specified string. The 3 lines below the routine are for testing it. We pause the routine by showing a message box and when you dismiss the message box, we kill the script instance, so the second message box doesn't show up. When you use it, you want to replace the last 3 lines with
KillProcesses "Fun.vbs"
I'd be careful using this and specify as much of the command line as possible to make sure I absolutely, positively match only the processes I want to terminate. You can modify the Task Manager and add a column to show the command line for every running process. In the routine below, the search in command line is case-insensitive.
Option Explicit
Sub KillProcesses(strPartOfCommandLine)
Dim colProcesses
Dim objProcess
Dim lReturn
' Get list of running processes using WMI
Set colProcesses = GetObject("winmgmts:\\.\root\cimv2").ExecQuery("Select * From Win32_Process")
For Each objProcess in colProcesses
If (Instr(1, objProcess.Commandline, strPartOfCommandLine, vbTextCompare) <> 0) Then
lReturn = objProcess.Terminate(0)
End If
Next
End Sub
Msgbox "Before being killed"
KillProcesses "KillProcesses.vbs"
Msgbox "After being killed"
I made before a script that ask you what vbscript did you want to kill and log the result into file.
So just, give a try :
Option Explicit
Dim Titre,Copyright,fso,ws,NomFichierLog,temp,PathNomFichierLog,OutPut,Count,strComputer
Copyright = "[© Hackoo © 2014 ]"
Titre = " Process "& DblQuote("Wscript.exe") &" running "
Set fso = CreateObject("Scripting.FileSystemObject")
Set ws = CreateObject( "Wscript.Shell" )
NomFichierLog="Process_WScript.txt"
temp = ws.ExpandEnvironmentStrings("%temp%")
PathNomFichierLog = temp & "\" & NomFichierLog
Set OutPut = fso.CreateTextFile(temp & "\" & NomFichierLog,1)
Count = 0
strComputer = "."
Call Find("wscript.exe")
Call Explorer(PathNomFichierLog)
'***************************************************************************************************
Function Explorer(File)
Dim ws
Set ws = CreateObject("wscript.shell")
ws.run "Explorer "& File & "\",1,True
end Function
'***************************************************************************************************
Sub Find(MyProcess)
Dim colItems,objItem,Processus,Question
Set colItems = GetObject("winmgmts:").ExecQuery("Select * from Win32_Process " _
& "Where Name like '%"& MyProcess &"%' AND NOT commandline like '%" & wsh.scriptname & "%'",,48)
For Each objItem in colItems
Count= Count + 1
Processus = Mid(objItem.CommandLine,InStr(objItem.CommandLine,""" """) + 2) 'Extraction of the commandline script path
Processus = Replace(Processus,chr(34),"")
Question = MsgBox ("Did you want to stop this script : "& DblQuote(Processus) &" ?" ,VBYesNO+VbQuestion,Titre+Copyright)
If Question = VbYes then
objItem.Terminate(0)'Kill this process
OutPut.WriteLine DblQuote(Processus)
else
Count= Count - 1 'decrement the counter -1
End if
Next
OutPut.WriteLine String(100,"*")
OutPut.WriteLine count & Titre & " were stopped !"
End Sub
'**********************************************************************************************
Function DblQuote(Str)
DblQuote = Chr(34) & Str & Chr(34)
End Function
'**********************************************************************************************
Good morning all,
I have been trying to pull together a VBscript that takes a file path and a file name (that may have a wildcard in it) from the user when the script is exicuted. The script will then check the specified directory for a file that matches the provided file name and then looks at the last modified date to see if it was created/modified within a certain time frame (i.e. 6am plus or minus 5 minutes). It would then copy said file into a zip file.
So far I have been able to get the arguments working, and I have it setup to grab the current time, look at the files in the folder and match a hard coded filename to one in the folder. This is what I have thus far.
currentTime = Now()
filePath = Wscript.Arguments.Item(0)
fileName = Wscript.Arguments.Item(1)
Set fileSystem = CreateObject("Scripting.FileSystemObject")
Set directory = fileSystem.GetFolder(filePath)
For each file in directory.Files
If file.Name = fileName Then
Wscript.echo file.Name & " " & file.DateLastModified
end if
Next
I am a VBscript noob and I am looking forward to learning the way!
Cap3
If you use WMI, it supports wildcards.
Dim strPath
strFile = "*.*"
If WScript.Arguments.Count > 1 Then
strPath = WScript.Arguments.Item(0)
strFile = WScript.Arguments.Item(1)
Elseif WScript.Arguments.Count = 1 Then
strPath = WScript.Arguments.Item(0)
Else
End If
Set objFso = CreateObject("Scripting.FileSystemObject")
If Not objFso.FolderExists(strPath) Then
WScript.Echo "Folder path does not exist."
WScript.Quit
Else
'Remove any trailing slash
If Right(strPath, 1) = "\" Then
strPath = Left(strPath, Len(strPath) - 1)
End If
End If
Set objFso = Nothing
If Not IsNull(strPath) And strPath <> "" Then
strQuery = strPath & "\" & strFile
Else
strQuery = strFile
End If
strQuery = Replace(strQuery, "*", "%")
strQuery = Replace(strQuery, "?", "_")
strQuery = Replace(strQuery, "\", "\\")
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}\\" & strComputer & "\root\cimv2")
Set colFiles = objWMIService.ExecQuery _
("Select * From CIM_DataFile Where FileName Like '" & strQuery & "'")
For Each objFile in colFiles
WScript.Echo "Access mask: " & objFile.AccessMask
WScript.Echo "Archive: " & objFile.Archive
WScript.Echo "Compressed: " & objFile.Compressed
WScript.Echo "Compression method: " & objFile.CompressionMethod
WScript.Echo "Creation date: " & objFile.CreationDate
WScript.Echo "Computer system name: " & objFile.CSName
WScript.Echo "Drive: " & objFile.Drive
WScript.Echo "8.3 file name: " & objFile.EightDotThreeFileName
WScript.Echo "Encrypted: " & objFile.Encrypted
WScript.Echo "Encryption method: " & objFile.EncryptionMethod
WScript.Echo "Extension: " & objFile.Extension
WScript.Echo "File name: " & objFile.FileName
WScript.Echo "File size: " & objFile.FileSize
WScript.Echo "File type: " & objFile.FileType
WScript.Echo "File system name: " & objFile.FSName
WScript.Echo "Hidden: " & objFile.Hidden
WScript.Echo "Last accessed: " & objFile.LastAccessed
WScript.Echo "Last modified: " & objFile.LastModified
WScript.Echo "Manufacturer: " & objFile.Manufacturer
WScript.Echo "Name: " & objFile.Name
WScript.Echo "Path: " & objFile.Path
WScript.Echo "Readable: " & objFile.Readable
WScript.Echo "System: " & objFile.System
WScript.Echo "Version: " & objFile.Version
WScript.Echo "Writeable: " & objFile.Writeable
Next
EDIT..........
You can use a WMI event script with the __InstanceCreationEvent to monitor for new file creation in a specific folder. It looks like this:
strSource = "C:\\somefilepath\\withdoubleshlashes"
strComputer = "."
Set objWMIService = GetObject("winmgmts:" & strComputer & "rootcimv2")
Set colEvents = objWMIService.ExecNotificationQuery _
("SELECT * FROM __InstanceCreationEvent WITHIN 10 WHERE " _
& "Targetinstance ISA 'CIM_DirectoryContainsFile' AND " _
& "TargetInstance.GroupComponent= " _
& "'Win32_Directory.Name=""" & strSource & """'")
Do While True
Set objEvent = colEvents.NextEvent()
copyFile(objEvent.TargetInstance.PartComponent)
Loop
For a full explanation, you can read Monitoring and Archiving Newly Created Files on my blog.
This answer uses Regular Expressions. To make it work it rewrites your pattern format into regular expression format. e.g. *.txt will become ^.*[.]txt$.
The following lists text files in C:\Temp last modified between 5:55 AM and 6:05 AM:
strPath = "C:\Temp"
strFile = "*.txt"
startTime = 555
endTime = 605
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder(strPath)
Set files = folder.Files
Set re = New RegExp
re.IgnoreCase = true
re.Pattern = "^" + Replace(Replace(strFile, ".", "[.]"), "*", ".*") + "$"
For Each f in Files
Set matches = re.Execute(f.Name)
If matches.Count > 0 Then
HM = Hour(f.DateLastAccessed) * 100 + Minute(f.DateLastAccessed)
If HM >= startTime And HM <= endTime Then
WScript.Echo f.Name, f.DateLastAccessed
End If
End If
Next
References:
Regular Expression (RegExp) Object
Regular Expressions and Operators
Microsoft Beefs Up VBScript with Regular Expressions
Hey, Scripting Guy! Raising Eyebrows on Regular Expressions
For your example, the easiest way to do this is to use the inStr (In String)function. I find it works in 99% of my wild card tasks. So, in your example, instead of using:
If file.Name = fileName Then
use:
If inStr(file.Name, filename) Then
This doesn't actually allow for wildcards(*) as it won't find a match(with the asterisk in the argument), so you would need to strip the wildcard from the string and replace it with nothing (or just train the user to not use wildcards):
Replace(filename,"*", "")
However, the inStr function does allow for partial or full matches which makes it suitable for most wildcard tasks. Therefore, if your file name is pic.jpg, whether the user searches for:
pic or jpg or p or c or pi etc.
It will return a match. Keep in mind though, that the instr function returns a number where the match shows up in the string. So, if it doesn't create a match, the result will be 0. I've run into examples where NOT doesn't work or I've needed to use the full syntax which in this case would be:
If inStr(file.Name, filename)<>0 Then
I have written a VBScript to enumerate events from the event log on a particular day.
The first query select from the NT event log events between todays date and yesterdays date,
Set colEvents = objWMIService.ExecQuery _
("Select * from Win32_NTLogEvent Where TimeWritten >= '" _
& dtmStartDate & "' and TimeWritten < '" & dtmEndDate & "'")
Then from the query above i want to extract event id's from a log file.
For Each objEvent in colEvents
If objEvent.Eventcode = EventNu And (objEvent.LogFile = EventLog) Then
I have placed the following into the script and it works, however I want to use arguments instead via command line (i.e. EventLogCheck.vbs EventNumber LogFile )but if i use the arguments secion of the script no items are returned. This is driving me nuts. The full script below uses variables, i have commented out the arguments section, but you can uncomment them and play around with it. What am i doing wrong? Thanks for any help!
Const CONVERT_TO_LOCAL_TIME = True
Dim EventLog
EventNu = 18
EventLog = "System"
'Input from the command line
'If Wscript.Arguments.Count <= 1 Then
' Wscript.Echo "Usage: EventLogCheck.vbs EventNumber LogFile"
' Wscript.Quit
'End If
'EventNu = WScript.Arguments.Item(0)
'EventLog = WScript.Arguments.Item(1)
'For Each Computer In Wscript.Arguments
Set dtmStartDate = CreateObject("WbemScripting.SWbemDateTime")
Set dtmEndDate = CreateObject("WbemScripting.SWbemDateTime")
'DateToCheck = CDate("5/18/2009")
DateToCheck = date
dtmStartDate.SetVarDate DateToCheck, CONVERT_TO_LOCAL_TIME
dtmEndDate.SetVarDate DateToCheck + 1, CONVERT_TO_LOCAL_TIME
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colEvents = objWMIService.ExecQuery _
("Select * from Win32_NTLogEvent Where TimeWritten >= '" _
& dtmStartDate & "' and TimeWritten < '" & dtmEndDate & "'")
For Each objEvent in colEvents
If objEvent.Eventcode = EventNu And (objEvent.LogFile = EventLog) Then
'Wscript.Echo "Category: " & objEvent.Category
Wscript.Echo "Computer Name: " & objEvent.ComputerName
Wscript.Echo "Event Code: " & objEvent.EventCode
Wscript.Echo "Message: " & objEvent.Message
' Wscript.Echo "Record Number: " & objEvent.RecordNumber
' Wscript.Echo "Source Name: " & objEvent.SourceName
Wscript.Echo "Time Written: " & objEvent.TimeWritten
Wscript.Echo "Event Type: " & objEvent.Type
' Wscript.Echo "User: " & objEvent.User
Wscript.Echo objEvent.LogFile
End if
Next
'Next
WScript.Echo EventNu
WScript.Echo EventLog
The arguments passed are treated as being of type string. However, EventNu should be an integer. You therefore have to convert the arguments to the correct type using CInt and CStr:
EventNu = CInt(WScript.Arguments.Item(0))
EventLog = CStr(WScript.Arguments.Item(1))