'for Each objDrive in colDrives' creating function syntax error - vbscript

I am trying to create a .vbs that will check is a dvd drive exists (if objdrive.drivetype= 4) while ignoring other drives such as hard drives (else if cdrive = 1 then -no statement- ect.).
However this line is causing me grief: "For Each objDrive in colDrives". When it exists it causes a syntax error, yet when it is removed it causes an error saying "object required: objdrive". The script uses a hta/vbs hybrid that offers the user to cancel the search for media, and this is achieved by using a function so putting this in a sub and calling this would be useless. Here is my code, please help.
Set shell=CreateObject("wscript.shell")
Set objShell = Wscript.CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set colDrives = objFSO.Drives
For Each objDrive in colDrives
if objdrive.drivetype= 4 then
select case 1
case 1
if objdrive.isready then
'continue statement here
else
select case 2
case 2
with HTABox("#F2F2F2", 115, 300, 700, 400)
.document.title = "Waiting..."
.msg.innerHTML = "Waiting for playable media...<b>"
end with
function HTABox(sBgColor, h, w, l, t)
Dim IE, HTA
randomize : nRnd = Int(1000000 * rnd)
sCmd = "mshta.exe ""javascript:{new " _
& "ActiveXObject(""InternetExplorer.Application"")" _
& ".PutProperty('" & nRnd & "',window);" _
& "window.resizeTo(" & w & "," & h & ");" _
& "window.moveTo(" & l & "," & t & ")}"""
with CreateObject("WScript.Shell")
.Run sCmd, 1, False
do until .AppActivate("javascript:{new ") : WSH.sleep 10 : loop
end with ' WSHShell
For Each IE In CreateObject("Shell.Application").windows
If IsObject(IE.GetProperty(nRnd)) Then
set HTABox = IE.GetProperty(nRnd)
IE.Quit
HTABox.document.title = "Waiting"
HTABox.document.write _
"<HTA:Application contextMenu=no border=thin " _
& "minimizebutton=no maximizebutton=no sysmenu=no />" _
& "<body scroll=no style='background-color:" _
& sBgColor & ";font:normal 10pt Arial;" _
& "border-Style:normal;border-Width:0px'" _
& "onbeforeunload='vbscript:if (done.value or cancel.value) then " _
& "window.event.cancelBubble=false:" _
& "window.event.returnValue=false:" _
& "cancel.value=false: done.value=false:end if'>" _
& "<input type=hidden id=done value=false>" _
& "<input type=hidden id=cancel value=false>" _
& "<center><span id=msg> </span><br>" _
& " <center><input type=button id=btn1 value=Cancel
' "_
& "onclick=self.close><center></body>"
exit function
End If
Next
MsgBox "HTA window not found."
wsh.quit
End Function
end select
end select
else if objdrive.drivetype = 1 then
else if objdrive.drivetype = 2 then
else if objdrive.drivetype = 3 then
else if objdrive.drivetype = 5 then
end if

The syntax error is most likely caused by the missing Next keyword that would close the loop. I think the conditional if objdrive.isready then is missing a closing End If too (between the two End Select). Add the missing keywords and the error should go away.
However, you're doing this whole thing upside down. Why are you creating an HTA on the fly from a VBScript? Just write the HTA and embed whatever VBScript code you need in it. See this tutorial for an introduction. Also, I would strongly recommend avoiding nested function definitions. They will cause you maintenance headaches at some point and they're not even generally allowed in VBScript. And what are your Select statements supposed to do? A construct
Select Case 1
Case 1
'instruction
End Select
is utterly pointless, because there is no selection in the first place. It's the exact same as running the instruction directly. Another thing to avoid are empty actions in conditionals. They just make your code harder to read and to maintain without generating you any benefit.

Its possible your issue may be due to the Upper Case D in "objDrive" in your For statement and then you later reference the name with a lower case "d" objdrive.isready within the loop. You may want to declare 'Option Explicit' at the top to find all undeclared variables.
Can you test the below code and see if it performs properly.
Set objFSO = CreateObject("Scripting.FileSystemObject")
For Each objDrive in objFSO.Drives
If objDrive.DriveType = 4 Then
If objDrive.IsReady Then
MsgBox "The appropriate media is inserted and ready for access"
Else
MsgBox "The Drive Is Not Ready"
End If
End If
Next
Also, I'm not sure the code snippet you provided is your full code but there appear to be several missing End statements. If so, these may also cause you problems.

Related

Check if a drive is mapped and active

I have a requirement within my VBScript to ensure that a drive is mapped and contactable.
Initially I was using only the DriveExists() method of the FileSystemObject, but this fell short as in certain scenarios users start the day in the office but then take their laptops on tour, without shutting down; thus the drive in question is still listed as mapped, but is not contactable.
To Address this I have created the below function, but it seems a bit dirty due to the use of On Error Resume Next.
So my question is this; is there a method that achieves my goal built in to VBS, or is my approach (or similar) the only way it can be done?
Function CheckDriveExists(drive)
CheckDriveExists = false
If FSO.DriveExists(drive) Then ' A drive is mapped for the required 'drive'
'** Create a file name for the test file *'
Dim tfDate, tfName
tfDate = Year(Now) & Month(Now) & Day(Now) & Hour(Now) & Minute(Now) & Second(Now)
tfName = "tstfile-" & tfDate & ".bucf"
'** Try to create and then delete a file on the usrs backup drive *'
On Error Resume Next
FSO.CreateTextFile(drive & ":\" & tfName)
FSO.DeleteFile(drive & ":\" & tfName)
CheckDriveExists = (Err.Number = 0) ' Check to see if the file was created and deleted successfully
Err.Clear ' Clear any possible error
On Error GoTo 0 ' Reset error handling
End If
End Function
from Windows Scripting documentation
Function ShowDriveList
Dim fso, d, dc, s, n
Set fso = CreateObject("Scripting.FileSystemObject")
Set dc = fso.Drives
For Each d in dc
n = ""
s = s & d.DriveLetter & " - "
If d.DriveType = 3 Then
n = d.ShareName
ElseIf d.IsReady Then
n = d.VolumeName
Else
n = "[Drive not ready]"
End If
s = s & n & "<BR>"
Next
ShowDriveList = s
End Function
perhaps you also need
Function ShowDriveType(drvpath)
Dim fso, d, t
Set fso = CreateObject("Scripting.FileSystemObject")
Set d = fso.GetDrive(drvpath)
Select Case d.DriveType
Case 0: t = "Unknown"
Case 1: t = "Removable"
Case 2: t = "Fixed"
Case 3: t = "Network"
Case 4: t = "CD-ROM"
Case 5: t = "RAM Disk"
End Select
ShowDriveType = "Drive " & d.DriveLetter & ": - " & t
End Function

VBScript Higher-Order Functions

Is there a way to write anonymous functions, pass them to other functions, in which they are invoked, in vbscript?
There are no anonymous functions/subs/methods in VBScript.
You can use GetRef() (see sample1, sample2) to get something like a function pointer that can be passed to functions/subs to be invoked there (callback). But there are no closures in VBScript, so tricks possible in other languages fail in VBScript.
For specific problems that can be solved with higher order functions in functional languages there may be (nearly) equivalent VBScript solutions involving classes/objects; but for discussing that approach you need to describe your/such a problem in detail.
VBScript has the ability to execute arbitatry code.
Execute and Eval just do what they say to a string containing code.
ExecuteGlobal adds code to your program, like a new function, new variables.
Script Control adds vbscript/jscript scripting language to any program including vbscripts. It can have access to the host's data.
If using ExecuteGlobal/Execute/Eval it is best to run through a scriptcontrol first to test for syntax errors (as you can't trap syntax errors, but you can trap the runtime error the script control gives off on a syntax error).
So you can build your program at runtime.
Set Arg = WScript.Arguments
set WshShell = createObject("Wscript.Shell")
Set Inp = WScript.Stdin
Set Outp = Wscript.Stdout
Sub VBSCmd
RawScript = LCase(Arg(1))
'Remove ^ from quoting command line and replace : with vbcrlf so get line number if error
Script = Replace(RawScript, "^", "")
Script = Replace(Script, "'", chr(34))
Script = Replace(Script, ":", vbcrlf)
'Building the script with predefined statements and the user's code
Script = "Dim gU" & vbcrlf & "Dim gdU" & vbcrlf & "Set gdU = CreateObject(" & chr(34) & "Scripting.Dictionary" & chr(34) & ")" & vbcrlf & "Function UF(L, LC)" & vbcrlf & "Set greU = New RegExp" & vbcrlf & "On Error Resume Next" & vbcrlf & Script & vbcrlf & "End Function" & vbcrlf
'Testing the script for syntax errors
On Error Resume Next
set ScriptControl1 = wscript.createObject("MSScriptControl.ScriptControl",SC)
With ScriptControl1
.Language = "VBScript"
.UseSafeSubset = False
.AllowUI = True
.AddCode Script
End With
With ScriptControl1.Error
If .number <> 0 then
Outp.WriteBlankLines(1)
Outp.WriteLine "User function syntax error"
Outp.WriteLine "=========================="
Outp.WriteBlankLines(1)
Outp.Write NumberScript(Script)
Outp.WriteBlankLines(2)
Outp.WriteLine "Error " & .number & " " & .description
Outp.WriteLine "Line " & .line & " " & "Col " & .column
Exit Sub
End If
End With
ExecuteGlobal(Script)
'Remove the first line as the parameters are the first line
'Line=Inp.readline
Do Until Inp.AtEndOfStream
Line=Inp.readline
LineCount = Inp.Line
temp = UF(Line, LineCount)
If err.number <> 0 then
outp.writeline ""
outp.writeline ""
outp.writeline "User function runtime error"
outp.writeline "==========================="
Outp.WriteBlankLines(1)
Outp.Write NumberScript(Script)
Outp.WriteBlankLines(2)
Outp.WriteLine "Error " & err.number & " " & err.description
Outp.WriteLine "Source " & err.source
Outp.WriteLine "Line number and column not available for runtime errors"
wscript.quit
End If
outp.writeline temp
Loop
End Sub
Vbs
filter vbs "text of a vbs script"
filter vb "text of a vbs script"
Use colons to seperate statements and lines. Use single quotes in place of double quotes, if you need a single quote use chr(39). Escape brackets and ampersand with the ^ character. If you need a caret use chr(136).
The function is called UF (for UserFunction). It has two parameters, L which contains the current line and LC which contains the linecount. Set the results of the script to UF. See example.
There are three global objects available. An undeclared global variable gU to maintain state. Use it as an array if you need more than one variable. A Dictionary object gdU for saving and accessing previous lines. And a RegExp object greU ready for use.
Example
This vbs script inserts the line number and sets the line to the function UF which Filter prints.
filter vbs "uf=LC ^& ' ' ^& L"<"%systemroot%\win.ini"
This is how it looks in memory
Dim gU
Set gdU = CreateObject("Scripting.Dictionary")
Set greU = New RegExp
Function UF(L, LC)
---from command line---
uf=LC & " " & L
---end from command line---
End Function
If there is a syntax error Filter will display debugging details.
User function syntax error
==========================
1 Dim gU
2 Dim gdU
3 Set greU = CreateObject("Scripting.Dictionary")
4 Function UF(L, LC)
5 On Error Resume Next
6 uf=LC dim & " " & L
7 End Function
Error 1025 Expected end of statement
Line 6 Col 6
User function runtime error
===========================
1 Dim gU
2 Dim gdU
3 Set greU = CreateObject("Scripting.Dictionary")
4 Function UF(L, LC)
5 On Error Resume Next
6 uf=LC/0 & " " & L
7 End Function
Error 11 Division by zero
Source Microsoft VBScript runtime error
Line number and column not available for runtime errors
the funny thing about function objects is that they by definition are a memory leak. This means that once you create a function object, you need to keep the scope it was created in intact, which threw me off.
Class VBCompiler
Public leaks
Public Sub Class_Initialize()
leaks = Array()
End Sub
Public Function Compile(code)
Dim compiler, result
Set compiler = CreateObject("MSScriptControl.ScriptControl")
Set portal = CreateObject("Scripting.Dictionary")
Dim name
compiler.Language = "VBScript"
compiler.AddObject "portal", portal, True
compiler.ExecuteStatement code
name = compiler.Procedures(1).Name
compiler.ExecuteStatement "portal.Add ""result"", GetRef(""" & name & """)"
' save the script control because if we go out of scope...
' our function object goes poof!
' leaks.Push compiler
ReDim Preserve leaks(UBound(leaks) + 1)
Set leaks(UBound(leaks)) = compiler
Set Compile = portal("result")
End Function
End Class
Dim z
Set z = New VBCompiler
Set z2 = z.Compile("Function Foo(s):MsgBox s:Foo = 2:End Function")
z2("Hi!")
z2 "Hello Again!"
Gives the two message boxes as desired
Class VBCompiler
Public Function Compile(code)
Dim compiler, result
Set compiler = CreateObject("MSScriptControl.ScriptControl")
Set portal = CreateObject("Scripting.Dictionary")
Dim name
compiler.Language = "VBScript"
compiler.AddObject "portal", portal, True
compiler.ExecuteStatement code
name = compiler.Procedures(1).Name
compiler.ExecuteStatement "portal.Add ""result"", GetRef(""Foo"") "
Set Compile = portal("result")
End Function
End Class
Dim z
Set z = New VBCompiler
Set z2 = z.Compile("Function Foo():MsgBox ""Well Met!"":Foo = 2:End Function")
z2("Hi!")
z2 "Hello Again!"
The above gives (29, 5) (null): Unspecified error. This error is in essence: your object has committed suicide.
This approach can be improved(in particular, the issue of wasteful one ScriptControl per compilation without any plans to release them).

exception handling and skip text messages

My script is basically the same as last time, but there are some bonus features I'm having problems with.
Is there something similar to exception handling in VBScript? I've read about it and I'm not to sure and is there a way if the script gets canceled for not existing path folders, to create them and continue/restart?
Is there a way how I'm able to skip (They've to be there, but it would be fancy if I could be able to skip them.) at the beginning of the script all these text messages and how is it done?
Here's the code I've got so far:
Set fso = CreateObject("Scripting.FileSystemObject")
Function Pad(s)
Pad = Right("00" & s, 2)
End Function
Sub CopyFiles(fldr, dst)
'Copy all files from fldr to destination folder and append the date (in ISO
'format) to the name. Overwrite existing files.
For Each f In fldr.Files
created = Year(f.DateCreated) & "-" & Pad(Month(f.DateCreated)) & "-" & _
Pad(Day(f.DateCreated)) & "_" & Pad(Hour(f.DateCreated)) & _
Pad(Minute(f.DateCreated)) & Pad(Second(f.DateCreated))
newname = fso.GetBaseName(f) & "_" & created & "." & fso.GetExtensionName(f)
WScript.Echo "Aktuelles File, welches gerade kopiert wird: " & newname
f.Copy fso.BuildPath(dst, newname), True
Next
'Recurse into subfolders.
For Each sf In fldr.SubFolders
CopyFiles sf, dst
Next
End Sub
CopyFiles fso.GetFolder("C:\test"), "C:\test1"
How do I have to implement "On Error Resume Next"?
I've done something like this right now and I'm not to sure if it's correct:
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FolderExists("C:\test") Then
On Error Goto 0
Dim StartFolder, TargetFolder
StartFolder = "C:\test"
TargetFolder = "C:\test1"
Function Pad(s)
Pad = Right("00" & s, 2)
End Function
Sub CopyFiles(fldr, dst)
'Copy all files from fldr to destination folder and append the date (in ISO
'format) to the name. Overwrite existing files.
For Each f In fldr.Files
created = Year(f.DateCreated) & "-" & Pad(Month(f.DateCreated)) & "-" & _
Pad(Day(f.DateCreated)) & "_" & Pad(Hour(f.DateCreated)) & Pad(Minute(f.DateCreated)) & Pad(Second(f.DateCreated))
newname = fso.GetBaseName(f) & "_" & created & "." & fso.GetExtensionName(f)
If UCase(FSO.GetExtensionName(f.name)) = "JPG" Then
f.Copy fso.BuildPath(dst, newname), True
WScript.Echo "Ich kopiere: " & StartFolder & "\" & f.name & " nach " & TargetFolder & "\" & newname
End If
Next
'Recurse into subfolders.
For Each sf In fldr.SubFolders
CopyFiles sf, dst
Next
End Sub
CopyFiles fso.GetFolder("C:\test"), "C:\test1"
End If
On Error Resume Next
f.Copy fso.BuildPath(dst, newname), True
If Err Then
WScript.Echo Err.Description & " [0x" & Hex(Err.Number) & "]"
End If
On Error Goto 0
If I understood your question correctly, error handling should not be required for what you're trying to do. To make sure that a folder exists before doing something with it, you can simply use the FolderExists method:
If fso.FolderExists("C:\some\folder") Then
'do stuff
End If
However, if for some reason you must use error handling, it can be enabled with the statement On Error Resume Next and disabled with the statement On Error Goto 0. While error handling is enabled you can detect errors by checking the state of the Err object.
A very simple error handling routine might look like this:
On Error Resume Next
f.Copy fso.BuildPath(dst, newname), True
If Err Then
WScript.Echo Err.Description & " [0x" & Hex(Err.Number) & "]"
End If
On Error Goto 0
Error handling suppresses all runtime error messages, so you should keep it as local as possible. Having error handling enabled on a broader scope bears the risk of errors going unnoticed, causing unexpected/undesired behavior for instance due to variables being not initialized or retaining an obsolete value.
If you have several subsequent statements that could fail make sure you add error handling routines for each and clear the Err object after each statement:
On Error Resume Next
Set wmi = GetObject("winmgmts://./root/cimv2")
If Err Then
WScript.Echo Err.Description & " [0x" & Hex(Err.Number) & "]"
End If
Err.Clear
Set proc = wmi.ExecQuery("SELECT * FROM Win32_Process")
If Err Then
WScript.Echo Err.Description & " [0x" & Hex(Err.Number) & "]"
End If
Err.Clear
'...
On Error Goto 0

Checking and opening different browsers using wsh script

hey guys i know this may sound stupid, but i am stuck with this question in my head...im really new to this wscript or vbscripting....at the time of writing i figured out how to open IE using wscript...heres the code
Set WshShell = WScript.CreateObject("WScript.Shell")
Return = WshShell.Run("iexplore.exe www.bbc.co.uk", 1)
but i cant figure out how to check if firefox is installed, then open firefox, if chrome is installed, open chrome, and the same thing goes for all the browser types.....
Update:
I did a little research and thought why not check the registry for that, so i came up with this script for checking the registry, now i dont know why but this always gives the same output "key does not exists" event though i have this registry in my system
keyTest = keyExists("HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\Mozilla Firefox")
If keyTest = False Then
wscript.echo "Key does not exist"
Elseif keyTest = True then
wscript.echo "Key exists"
End if
Function keyExists (RegistryKey)
If (Right(RegistryKey, 1) <> "\") Then
RegistryKeyExists = false
Else
On Error Resume Next
WshShell.RegRead RegistryKey
Select Case Err
Case 0:
keyExists = true
Case &h80070002:
ErrDescription = Replace(Err.description, RegistryKey, "")
Err.clear
WshShell.RegRead "HKEY_ERROR\"
If (ErrDescription <> Replace(Err.description, _
"HKEY_ERROR\", "")) Then
keyExists = true
Else
RegistryKeyExists = false
End If
Case Else:
keyExists = false
End Select
On Error Goto 0
End If
End Function
Problems in your example:
In keyExists(), a variable named RegistryKeyExists is being used for the return value from the function when keyExists is intended.
The Shell object variable WshShell is never instantiated via CreateObject().
The value of the registry key of interest does not end with a backslash.
Here's my streamlined version of your code which I believe accomplishes your objective:
Option Explicit ' programming with your seatbelt on :-)
Dim keys(4)
keys(0) = "HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\Mozilla Firefox"
keys(1) = "HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\Mozilla Firefox\"
keys(2) = "HKEY_LOCAL_MACHINE\Bad\Key\"
keys(3) = "BAD\Root\On\This\Key\Causes\Exception"
keys(4) = "HKLM\SOFTWARE\Microsoft\Internet Explorer\"
On Error Resume Next
Dim i, key
For i = 0 To UBound(keys)
key = keyExists(keys(i))
If Err Then
WScript.Echo "An exception occurred reading registry key" _
& " '" & keys(i) & "':" _
& " [" & Err.Number & "] " _
& Err.Description _
& ""
Else
If keyExists(keys(i)) Then
WScript.Echo "Key *exists*: [" & keys(i) & "]"
Else
WScript.Echo "Key does *not* exist: [" & keys(i) & "]"
End If
End If
WScript.Echo "--"
Next
Function keyExists (RegistryKey)
Dim keyVal, errNum, errDesc
keyExists = False
On Error Resume Next
Dim WshShell : Set WshShell = CreateObject("WScript.Shell")
keyVal = WshShell.RegRead(RegistryKey)
Select Case Err
Case 0
keyExists = True
Case &h80070002
' key does not exist
Case Else
errNum = Err.Number
errDesc = Err.Description
On Error GoTo 0
Err.Raise vbObjectError + 1, "WScript.Shell", _
"Something went wrong reading the registry:" _
& " [" & Hex(errNum) & "] " & errDesc
End Select
On Error GoTo 0
Set WshShell = Nothing
End Function
' End
Generally following code can be used to find out to get List of All Installed Software.
Here I have used Message box to display this list, you can use if condition to find out desired software is installed or not............
' List All Installed Software
Const HKLM = &H80000002 'HKEY_LOCAL_MACHINE
strComputer = "."
strKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
strEntry1a = "DisplayName"
Set objReg = GetObject("winmgmts://" & strComputer & _
"/root/default:StdRegProv")
objReg.EnumKey HKLM, strKey, arrSubkeys
For Each strSubkey In arrSubkeys
intRet1 = objReg.GetStringValue(HKLM, strKey & strSubkey, _
strEntry1a, strValue1)
If strValue1 <> "" Then
MsgBox VbCrLf & "Display Name: " & strValue1
End If
Next
I have tried this code on machine & found that,it just listing Firefox browser, even when i have installed chrome & IE.So this regular method wont work surely for everyone. After that I have checked registry and found that,all browser are listed on.....
HKEY_LOCAL_MACHINE\SOFTWARE\Clients\StartMenuInternet\
So we can write code to find is is particular browser is installed or not.
Following sample code to check if Chrome & Firefox is installed or not and if installed open it with URL passed
Set WshShell = CreateObject("WScript.Shell")
Const HKEY_LOCAL_MACHINE = &H80000002
strComputer = "."
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\default:StdRegProv")
strKeyPath = "SOFTWARE\Clients\StartMenuInternet\chrome.exe\shell\open\command\"
strValueName = ""
oReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue
If InStr(1,strValue,"chrome",vbTextCompare) Then WshShell.Run("chrome www.google.com")
strKeyPath = "SOFTWARE\Clients\StartMenuInternet\FIREFOX.EXE\shell\open\command\"
strValueName = ""
oReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue
If InStr(1,strValue,"firefox",vbTextCompare) Then WshShell.Run("firefox www.google.com")
Similarly you can modify this code for IE, Opera & Safari
Hope this helps.......

How do I know when a file has been modified in a VBA Macro?

Is there a way to watch a file in VBA (which is essentially VB6), so that I know when the file has been modified? -- similar to this only I don't want to know when a file is unused, just when its modified.
The answers I've found have recommended using "FileSystemWatcher" and the Win32 API "FindFirstChangeNotification". I can't figure out how to use these though, any idea?
Okay, I put together a solution that is able to detect file system changes, in VBA (VB6).
Public objWMIService, colMonitoredEvents, objEventObject
'call this every 1 second to check for changes'
Sub WatchCheck()
On Error GoTo timeout
If objWMIService Is Nothing Then InitWatch 'one time init'
Do While True
Set objEventObject = colMonitoredEvents.NextEvent(1)
'1 msec timeout if no events'
MsgBox "got event"
Select Case objEventObject.Path_.Class
Case "__InstanceCreationEvent"
MsgBox "A new file was just created: " & _
objEventObject.TargetInstance.PartComponent
Case "__InstanceDeletionEvent"
MsgBox "A file was just deleted: " & _
objEventObject.TargetInstance.PartComponent
Case "__InstanceModificationEvent"
MsgBox "A file was just modified: " & _
objEventObject.TargetInstance.PartComponent
End Select
Loop
Exit Sub
timeout:
If Trim(Err.Source) = "SWbemEventSource" And Trim(Err.Description) = "Timed out" Then
MsgBox "no events in the last 1 sec"
Else
MsgBox "ERROR watching"
End If
End Sub
Copy and paste this sub near the above, it is called automatically if needed to initialize the global vars.
Sub InitWatch()
On Error GoTo initerr
Dim watchSecs As Integer, watchPath As String
watchSecs = 1 'look so many secs behind'
watchPath = "c:\\\\scripts" 'look for changes in this dir'
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colMonitoredEvents = objWMIService.ExecNotificationQuery _
("SELECT * FROM __InstanceOperationEvent WITHIN " & watchSecs & " WHERE " _
& "Targetinstance ISA 'CIM_DirectoryContainsFile' and " _
& "TargetInstance.GroupComponent= " _
& "'Win32_Directory.Name=""c:\\\\scripts""'")
MsgBox "init done"
Exit Sub
initerr:
MsgBox "ERROR during init - " & Err.Source & " -- " & Err.Description
End Sub
You should consider using a WMI temporary event consumer to watch the file, along the lines suggested here but narrowing it down to a specific file instead of a folder
(This is assuming you can't just keep an eye on the file's Modified Date property..)
Have a look here. The page has a "Watch Directory Demo" VB sample, by Bryan Stafford.
I take it into vb6,run,display:ERROR watching.

Resources