VBscript create array but omit blank variables - arrays

I am looking to create a script that will compare the last modified date of up to 4 files then capture the one most recently modified. My current road block is that some files might not exist.
The set will fail if the file does not exist but I can easily overcome that by looking for the file and if it does not exist simply skip the set command. This would cause the creation of the array to fail because my variable is now blank.
Any suggestions how to resolve this?
Here is what I have so far:
Option Explicit
Dim objFSO, path, file, recentDate, recentFile, File1, File2, File3, File4, afiles, File1date, date1
Set objFSO = CreateObject("Scripting.FileSystemObject")
set File1=objFSO.getfile("c:\temp\file.txt")
set File2=objFSO.getfile("c:\test\File.txt")
set File3=objFSO.getfile("c:\users\%profile%\documents\File.txt")
set File4=objFSO.getfile("c:\users\public\documents\File.txt")
'Prepare variables to store the required information
Dim dateMin, dateMax
date1 = File1.datelastmodified
wscript.echo date1
wscript.echo now
dateMin = date1
dateMax = date1
afiles = Array( File1.datelastmodified, File2.datelastmodified, File3.datelastmodified, File4.datelastmodified )
Dim i
For i=1 to UBound(aFiles)
If aFiles(i) < dateMin Then dateMin = aFiles(i)
if aFiles(i) > dateMax Then dateMax = aFiles(i)
Next
'
' Output Information
WScript.Echo "Highest: " & CStr( dateMax )
WScript.Echo " Lowest: " & CStr( dateMin )

I think this would be much easier if you use an ArrayList to capture the DateLastModified for each file.
An ArrayList lets you dynamically add values unlike a VBScript Array.
Furthermore, the ArrayList has a very useful method called Sort() we can use here to determine the dateMin and dateMax values.
Try:
Option Explicit
Dim objFSO, objList, objFile, arrFiles, fileName
arrFiles = Array("c:\temp\file.txt","c:\test\File.txt","c:\users\%profile%\documents\File.txt","c:\users\public\documents\File.txt")
Set objList = CreateObject("System.Collections.ArrayList")
Set objFSO = CreateObject("Scripting.FilesystemObject")
For Each fileName In arrFiles
If objFSO.FileExists(fileName) Then
Set objFile = objFSO.GetFile(fileName)
objList.Add objFile.DateLastModified
End If
Next
objList.Sort()
' Prepare variables to store the required information
Dim dateMin, dateMax
dateMin = objList.item(0)
dateMax = objList.item(objList.Count - 1)
' Output Information
WScript.Echo "Highest: " & CStr( dateMax )
WScript.Echo "Lowest: " & CStr( dateMin )
' Clean up
Set objFSO = Nothing
Set objFile = Nothing
Set objList = Nothing
Edit
The above code was a remake of your original code. I may have misunderstood then that your goal is to find the file most recently modified.
This should do what you have in mind:
Option Explicit
Dim objFSO, objFile, objLatest, fileName, arrFiles
arrFiles = Array("c:\temp\file.txt","c:\test\File.txt","c:\users\%profile%\documents\File.txt","c:\users\public\documents\File.txt")
Set objFSO = CreateObject("Scripting.FilesystemObject")
Set objLatest = Nothing
For Each fileName In arrFiles
If objFSO.FileExists(fileName) Then
Set objFile = objFSO.GetFile(fileName)
If (objLatest Is Nothing) Then
Set objLatest = objFile
ElseIf (objFile.DateLastModified > objLatest.DateLastModified) Then
Set objLatest = objFile
End If
End If
Next
If objLatest Is Nothing Then
WScript.Echo "None of the files in 'arrFiles' exist.."
Else
' Here you decide if you want to keep the latest file as Object (-> objLatest) or just as a string to the full pathname of that file
Dim latestFile
latestFile = objFSO.GetAbsolutePathName(objLatest) ' store the full path and filename
' Info on FormatDateTime() at https://www.w3schools.com/asp/func_formatdatetime.asp
WScript.Echo "Most recently modified file is '" & latestFile & "' at " & FormatDateTime(objLatest.DateLastModified, 0)
End If
' Clean up
Set objFSO = Nothing
Set objFile = Nothing
Set objLatest = Nothing

Related

Load all files within a folder into an array with vbscript / hta?

I want to load all files of a directory into an array with vbscipt/hta in order to sort and "call" them later by index. I've tried something like this, but it's not working:
Set objFSO = CreateObject("Scripting.FileSystemObject")
objFileFolder = "C:\"
Set objFolder = objFSO.GetFolder(objFileFolder)
Set colFiles = objFolder.Files
dim arrFileList()
For Each objFile in colFiles
ReDim Preserve arrFileList(UBound(arrFileList) + 1)
FileList(UBound(arrFileList)) = objFile.Name
Next
I'd be grateful for any help! THX in advance
You need to change two things, please see new code below. Comments in line.
Set objFSO = CreateObject("Scripting.FileSystemObject")
objFileFolder = "C:\"
Set objFolder = objFSO.GetFolder(objFileFolder)
Set colFiles = objFolder.Files
dim arrFileList()
ReDim Preserve arrFileList(0) 'If you wish to use the array UBound later on you must redim this here
For Each objFile in colFiles
ReDim Preserve arrFileList(UBound(arrFileList) + 1)
arrFileList(UBound(arrFileList)) = objFile.Name ' Here you were calling FileList, not arrFileList
Next
You could further tidy / improve this code as arrFileList(0) will have no value upon finishing.

Code fails on "Application.Match" call, "object required" message

Need help, in this line....If IsError(Application.Match(iLine, arr, 0)) Then ...
Its runtime error is that an object is required. I've tried a number of different things to solve, but am stuck. Been researching but not finding anything as a resolution.
When I try to declare..."Dim arr as variant" it retorts that "Expected end of statement". I am simply clicking on "ProcessCollection.vbs" to run the script. I'm using EditPlus3, and it does highlight "Application" in red text in this line.
I've tried VbsEdit and when it debugs to this line, iLine, arr, are defined, but the value of "Application" is "Empty".
GetFiles()
'WriteCSV()
'*****
Function GetFiles
Dim arr
'Dim arr as Variant
Dim iFileLines
Dim iLine
Set objFSO = CreateObject("Scripting.FileSystemObject")
objStartFolder = "C:\hgis\a"
Set objFolder = objFSO.GetFolder(objStartFolder)
Set colFiles = objFolder.Files
For Each objFile in colFiles
'Wscript.Echo objFile.Name
mfn = objStartFolder +"\"+ objFile.Name
Wscript.Echo mfn
'open file & process each file
set fso = CreateObject("Scripting.FileSystemObject")
Set theFile = fso.OpenTextFile(mfn, 8, True)
iFileLines = theFile.Line
iLine = 0
arr = Array(2, 3, iFileLines - 1) ' second, third, and 2nd from last
msgbox iFileLines
Set objFileToRead = CreateObject("Scripting.FileSystemObject").OpenTextFile(mfn,1)
Dim strLine, TotStr
TotStr = "CellA"
do while not objFileToRead.AtEndOfStream
strLine = objFileToRead.ReadLine()
msgbox strline
'Parse lines for specific data - i.e. "-2014-" to get date/time stamp
iLine = iLine + 1
'And then check if the line number is in the array:
'Capture data and store to csv file for Excel analysis
If IsError(Application.Match(iLine, arr, 0)) Then
' It isn't in the array, do this....
msgbox "no"
Else
' It is in the array, grab it
TotStr = TotStr +","+ strline
msgbox TotStr
End If
loop
objFileToRead.Close
Set objFileToRead = Nothing
Next
'csvFile.Close
End Function
'*****
I found a function from Justin Doles at DigitalDeviation.com that I used to replace the Application.Match function.
Function IsInArray(strIn, arrCheck)
'IsInArray: Checks for a value inside an array
'Author: Justin Doles - www.DigitalDeviation.com
Dim bFlag
bFlag = False
If IsArray(arrCheck) AND Not IsNull(strIn) Then
Dim i
For i = 0 to UBound(arrCheck)
If LCase(arrcheck(i)) = LCase(strIn) Then
bFlag = True
Exit For
End If
Next
End If
IsInArray = bFlag
End Function
'*****

VB script: if file exists then run if not then end

I'm looking to use a script to go about disabling a file (REAgentc.exe) on Windows 7 machines and if it does not exist (i.e. on XP machines) then end. Below is what I've got so far but can anyone assist me in implementing the rest of what I'm after? My knowledge on VB script is admittedly not great but any help that can be offered forward would be greatly appreciated, thanks.
'Declare Variables
Dim strApp
Dim arrPath
Dim strPath
Dim strAppPath
' main if statement to run the script and call functions and sub's
If (CheckRegistryForValue)= True Then
'msgbox( strPath & " I am here")
WScript.Quit (0)
Else
RunCommand
WriteRegkey
WScript.Quit (0)
End If
'Sub to run the REAgent disable command
Sub RunCommand
Set objShell = CreateObject("Wscript.Shell")
strApp = "C:\Windows\System32\REAgentc.exe /disable"
arrPath = Split(strApp, "\")
For i = 0 To Ubound(arrPath) - 1
strAppPath = strAppPath & arrPath(i) & "\"
Next
objShell.CurrentDirectory = strAppPath
objShell.Run(strApp)
End Sub
'Function to check registry for value, Return check registry for value
Function CheckRegistryForValue
Set WshShell = WScript.CreateObject("WScript.Shell")
On Error Resume Next
dong = wshShell.RegRead ("HKLM\SOFTWARE\REAgent\")
If (Err.Number <> 0) Then
CheckRegistryForValue = False
Else
CheckRegistryForValue = True
End If
End Function
' sub to write registery key to flag computers that the script has run On
Sub WriteRegkey
HKEY_LOCAL_MACHINE = &H80000002
strComputer = "."
Set ObjRegistry = GetObject("winmgmts:{impersonationLevel = impersonate}!\\" & strComputer & "\root\default:StdRegProv")
strPath = "SOFTWARE\REAgent\Script Complete"
Return = objRegistry.CreateKey(HKEY_LOCAL_MACHINE, strPath)
End Sub
You can modify your RunCommand to detect & run;
dim FSO, objShell, strApp
set FSO = CreateObject("Scripting.FileSystemObject")
set objShell = CreateObject("Wscript.Shell")
'//get system path
strApp = FSO.GetSpecialFolder(1) & "\REAgentc.exe"
if FSO.FileExists(strApp) then
'//no need to change directory as you have the full path
objShell.Run(strApp & " /disable")
else
'//does not exist
end if

Creating a VBS file with the ability to write out to a text file

I have a VBS file that I am trying to use to determine what folders and files are in a certain directory. I believe I have the code written correctly, but whenever I try to write out the file or current directory I get a blank text document with nothing but the root directory written out. Any advice would be greatly appreciated.
Dim NewFile
Function GetFolders (strFolderPath)
Dim objCurrentFolder, colSubfolders, objFolder, files
Set objCurrentFolder = objFSO.GetFolder(strFolderPath)
Set colSubfolders = objCurrentFolder.SubFolders
For Each objFolder In colSubfolders
NewFile.WriteLine(" - " & objFolder.Path)
Set files = folder.Files
For each folderIdx In files
NewFile.WriteLine(" - "& folderIdx.Name)
Next
Call GetFolders (objFolder.Path)
Next
End Function
Dim fso, sFolder
Set fso = CreateObject("Scripting.FileSystemObject")
sFolder = Wscript.Arguments.Item(0)
If sFolder = "" Then
Wscript.Echo "No Folder parameter was passed"
Wscript.Quit
End If
Set NewFile = fso.CreateTextFile(sFolder&"\FileList.txt", True)
NewFile.WriteLine(sFolder)
Call GetFolders(sFolder)
NewFile.Close
You haven't payed sufficient attention to your variable naming. Your script is a good example of the reason why all VBScripts should start with the line:-
Option Explicit
This would highlight all the variables that haven't been declared which in turn will point out typos and inconsistencies in variable naming. Here is how I would write it:-
Option Explicit
Dim msFolder : msFolder = Wscript.Arguments.Item(0)
If msFolder = "" Then
Wscript.Echo "No Folder parameter was passed"
Wscript.Quit
End If
Dim mfso : Set mfso = CreateObject("Scripting.FileSystemObject")
Dim moTextStream : Set moTextStream = mfso.CreateTextFile(msFolder & "\FileList.txt", True)
moTextStream.WriteLine(msFolder)
WriteFolders mfso.GetFolder(msFolder)
moTextStream.Close
Sub WriteFolders(oParentFolder)
Dim oFolder
For Each oFolder In oParentFolder.SubFolders
moTextStream.WriteLine(" - " & oFolder.Path)
Dim oFile
For Each oFile In oFolder.Files
moTextStream.WriteLine(" - " & oFile.Name)
Next
WriteFolders oFolder
Next
End Sub

How to make a batch file edit a text file

I got the code
Set objFS = CreateObject("Scripting.FileSystemObject")
strFile = "C:\test\file.txt"
Set objFile = objFS.OpenTextFile(strFile)
Do Until objFile.AtEndOfStream
strLine = objFile.ReadLine
If InStr(strLine,"ex3")> 0 Then
strLine = Replace(strLine,"ex3","ex5")
End If
WScript.Echo strLine
Loop
The strLine replacing part i can fix myself to use with my own purposes, but how do i do something like this so that it doesn't require the file's name, it just edits all text files within the document?
you can do it like this,
strFolder = "c:\myfolder"
Set objFolder = objFS.GetFolder(strFolder)
For Each strFile In objFolder.Files
strFileName =strFile.Name
strFilePath = strFile.Path
strFileExt = objFS.GetExtensionName(strFile)
If strFileExt = "txt" Then
Set objFile = objFS.OpenTextFile(strFile)
' your current code here..
objFile.Close()
End If
Next

Resources