VBScript Environment variables - vbscript

I have a question regarding how I should go about fixing an error that I am seeing when running my script. I am pretty sure it has to do with the way in which I am using the %COMPUTERNAME% environment variable.
What my script does is it zips up some files locally, then copies them using robocopy to a mounted or shared drive, then checks to see if the file sizes are the same, and if they are then it deletes the files on the original computer. If any step in the process produces an error it exits the script.
Now the script works perfectly fine if I do not add in the "%COMPUTERNAME%" to the final destination path. (Where the zipped files will eventually be) I need the zipped files to be placed into their own folders with the name of the host from which it originated, because this script will be run on many different machines all going to the same location.
So basically it needs to look something like this:
E:\LocalHostName\TestZip.zip
Now the script will build the folder just fine when the zipped files are being copied over, the problem occurs once the file size check starts. I am getting the error of "File not found" for the line "FileToBeCompared2". I understand why the error is being produced, because it is not recogizing the %COMPUTERNAME% environment variable, but I do not know how to go about addressing this issue.
I am also going to try to add in some functionality where if an error occurs a text file with something like "An error occured during the script" is produced in the output folder.
Thank you for all your help in advance. The script is found below:
'-------------------------------------------------------------------------------------------
'This script is used to zip files locally, copy them to a new location, verify that the
'files were copied correctly, and then delete the files from the original source.
'In it's current state it is being used as a means to zip event files and move them
'to a central location.
'Run with administrator priveleges.
'-----------------------------------------------------------------------------------------------------
Option Explicit
Dim sDirectoryPath, sLocalDestinationPath, sFinalDestinationPath, sOutputFilename, Shell, sFileExt, sFilePrefix
Set Shell = WScript.CreateObject("WScript.Shell")
'Specify Directory Path where files to be zipped are located
'Specify local destination for zipped files
'Specify final destination path for zippped files
'Specify file extension name to look for
'Specify prefix of filename to look for
sDirectoryPath = "C:\Testscripts\"
sLocalDestinationPath = "C:\ScriptOutput\"
sFinalDestinationPath = "E:\CopyTestFolder\" & sOutputFilename & "\"
sFileExt = ".evtx"
sFilePrefix = "Archive*"
sOutputFilename = shell.ExpandEnvironmentStrings("%COMPUTERNAME%") 'Environment variables needed for grabbing hostname
Dim ZipCommand, RobocopyCommand, RunCommand, filesys, filetext
Dim d : d = Date()
Dim dateStr : dateStr = Year(d) & "-" & Right("00" & Month(d), 2) & "-" & Right("00" & Day(d), 2) 'Date String
Dim t : t = Time()
Dim timeStr: timeStr = Hour(t) & "-" & Right("00" & Minute(t), 2) & "-" & Right("00" & Second(t), 2) 'Time String
Dim FullFileName
FullFileName = sOutputFilename & "-" & dateStr & "-" & timeStr & ".zip "
'Following command runs 7-zip and grabs the files to be zipped from your set sDirectoryPath, zips them into set sLocalDestinationPath
'and names the file with the localhost name and date/time
ZipCommand = """C:\Program Files\7-zip\7z.exe"" a " & sLocalDestinationPath & FullFileName & sDirectoryPath & sFilePrefix & sFileExt
RunCommand = Shell.Run(ZipCommand,0,true)
if err.Number <> 0 then
WScript.Echo "An error has occurred during the zip process, re-run Script." WScript.Quit
end if
Wscript.Sleep 2000
'The following command creates a folder named after the host computer where the files are being copied from
Dim newfolder, newfolderpath, filesys2
newfolderpath = "E:\CopyTestFolder\" & sOutputFilename & "\"
set filesys2 = CreateObject("Scripting.FileSystemObject")
If Not filesys2.FolderExists(newfolderpath) Then
Set newfolder = filesys2.CreateFolder(newfolderpath)
End If
'Following command runs Robocopy from command line, moves files from your set sLocalDestinationPath to your set sFinalDestinationPath
WScript.Echo "Robocopy.exe " & sLocalDestinationPath & " " & sFinalDestinationPath
RobocopyCommand = "Robocopy.exe " & sLocalDestinationPath & " " & sFinalDestinationPath
RunCommand = Shell.Run(RobocopyCommand,0,true)
if err.Number <> 0 then
WScript.Echo "An error has occured copying the files, re-run Script."
WScript.Quit
end if
Dim fso, FileToBeCompared1, FileToBeCompared2
Set fso = CreateObject("Scripting.FileSystemObject")
'Setting the Local file to be compared
Set FileToBeCompared1 = fso.GetFile(sLocalDestinationPath & FullFileName)
WScript.echo sFinalDestinationPath & FullFileName
'Setting the file copied to final destination to be compared
Set FileToBeCompared2 = fso.GetFile(sFinalDestinationPath & FullFileName)
If FileToBeCompared1.size = FileToBeCompared2.size then
fso.DeleteFile("C:\Testscripts\Archive*.evtx") 'This will be the path where events are being Archived to. (Non restricted path)
fso.DeleteFolder("C:\ScriptOutput") 'This deletes the archive folder that 7-zip builds each time this script is run
else
WScript.Echo "File sizes do not match, File was not fully copied, Re run script."
WScript.Quit
end if

Because fso.GetFile() will not automatically expand %COMPUTERNAME%, modify sFinalDestinationPath to use sOutputFilename like this:
sOutputFilename = shell.ExpandEnvironmentStrings("%COMPUTERNAME%")
sFinalDestinationPath = "E:\CopyTestFolder\" & sOutputFilename & "\"

Related

Unable to find file in VBScript

The VBE encoder section works (from prior experience but this time around it cannot find the required file. The file is in the %temp% folder so there are spaces in the path but I have used the "" as can be seen in the code. The MsgBox shows the correct file and I can confirm its existence but the code fails when fso.GetFile.
This is part of a larger script that is called with the target file (full path) as the argument. The target file is previously created by the calling script.
Main script (gets called with target file):
Set fso = CreateObject("Scripting.FileSystemObject")
Set wshShell = WScript.CreateObject("WScript.Shell")
textFile = WScript.Arguments(0)
GetExtension = fso.GetExtensionName(fso.GetFileName(textFile))
If LCase(GetExtension) = "vbs" Then
Set oFilesToEncode = WScript.Arguments
Set oEncoder = CreateObject("Scripting.Encoder")
For i = 0 To oFilesToEncode.Count - 1
file = """" & Trim(oFilesToEncode(i)) & """"
MsgBox file
If fso.FileExists(Left(file, Len(file) - 3) & "vbe") Then fso.DeleteFile(Left(file, Len(file) - 3) & "vbe")
Set oFile = fso.GetFile(file)
Set oStream = oFile.OpenAsTextStream(1)
sSourceFile = oStream.ReadAll
oStream.Close
sDest = oEncoder.EncodeScriptFile(".vbs", sSourceFile, 0, "")
sFileOut = Left(file, Len(file) - 3) & "vbe"
Set oEncFile = fso.CreateTextFile(sFileOut)
oEncFile.Write sDest
oEncFile.Close
Next
End If
WScript.Quit
Section of calling script:
Do While fso.FileExists(strTempVBS) = False
Loop
strKey = "HKEY_CLASSES_ROOT\Engineers-Toolbox\Multi-Tool\Installed\Path\"
value = wshShell.RegRead( strKey )
arg = " " & strTempVBS
running = "C:\Custom\Multi-Tool\Multi-Tool.exe " & """" & arg & """"
wshShell.Run running, True
I have tried using hard coding the path to the exe to get it going, 'value' contains the path to the main script.
Do not prematurely add quotes around paths. I'm always confused why people keep doing this, because it creates more problems than it solves. Add double quotes when they're actually required, but not before.
FileSystemObject methods can handle paths with spaces without the additional double quotes. In fact, they will interpret double quotes in a path string as part of the path and throw an error, because they can't find a file with a double quote in its name (which would be invalid anyway).
Your check for the existence of a file also doesn't work, because you don't account for the quotes you added to the path string:
file = """C:\some\folder\file.vbs"""
WScript.Echo file
WScript.Echo Left(file, Len(file) - 3) & "vbe"
The output of the above code snippet is
"C:\some\folder\file.vbs"
"C:\some\folder\file.vvbe
Change this:
file = """" & Trim(oFilesToEncode(i)) & """"
into this:
file = Trim(oFilesToEncode(i))
and the problem will disappear.
Ok, the solution is to (predictably) add the quotes in the calling script, that way the VBS to VBE encoder section can remain standard.
strTEMP = wshShell.ExpandEnvironmentStrings( "%UserProfile%" ) & "\AppData\Local\Multi-Tool\"
strTempVBS = strTEMP & "observe.vbs"
strKey = "HKEY_CLASSES_ROOT\Engineers-Toolbox\Multi-Tool\Installed\Path\"
value = wshShell.RegRead( strKey ) & " "
running = value & "" & chr(34) & strTempVBS & chr(34) & ""
wshShell.Run running ,True
Interesting was how the quotes are added. This made the called script find the required file even tho the full path contained spaces.

VBS zipping script

I found (apparently working for everybody) script which only needs to be modified (paths):
Sub NewZip(pathToZipFile)
'WScript.Echo "Newing up a zip file (" & pathToZipFile & ") "
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
Dim file
Set file = fso.CreateTextFile(pathToZipFile)
file.Write Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, 0)
file.Close
Set fso = Nothing
Set file = Nothing
WScript.Sleep 500
End Sub
Sub CreateZip(pathToZipFile, dirToZip)
'WScript.Echo "Creating zip (" & pathToZipFile & ") from (" & dirToZip & ")"
Dim fso
Set fso= Wscript.CreateObject("Scripting.FileSystemObject")
pathToZipFile = fso.GetAbsolutePathName(pathToZipFile)
dirToZip = fso.GetAbsolutePathName(dirToZip)
If fso.FileExists(pathToZipFile) Then
'WScript.Echo "That zip file already exists - deleting it."
fso.DeleteFile pathToZipFile
End If
If Not fso.FolderExists(dirToZip) Then
'WScript.Echo "The directory to zip does not exist."
Exit Sub
End If
NewZip pathToZipFile
dim sa
set sa = CreateObject("Shell.Application")
Dim zip
Set zip = sa.NameSpace(pathToZipFile)
'WScript.Echo "opening dir (" & dirToZip & ")"
Dim d
Set d = sa.NameSpace(dirToZip)
' Look at http://msdn.microsoft.com/en-us/library/bb787866(VS.85).aspx
' for more information about the CopyHere function.
zip.CopyHere d.items, 4
Do Until d.Items.Count <= zip.Items.Count
Wscript.Sleep(200)
Loop
End Sub
Can anybody give example how this script should look like with
real paths? I'm trying but it's not working for me.
This script consists solely of two subroutines and thus will never execute anything.
Add the following line to the bottom of the file and it should work (given that the code in the subs is sound, I have not tested):
CreateZip "c:\output\test.zip" "c:\input\"
This will do the following, in order:
Check to see if the output file exists. If it does, it will delete it.
Check to see if the input folder exists, if it does not, the script will exit.
Call the NewZip sub which just creates an "empty" .zip file.
Copy files to the zip file.
Pause for a while, probably to ensure you don't try to access the ZIP before it's done copying.
The contents of the input folder will now be in the zip file in the output folder.

VBScript Macro getParentFolder Name

I am trying to create a vbscript macro which would get the folder location in which the macro is stored and create the output files into the same folder. I am using the below code but its not getting the correct location
Set obj1FSO = CreateObject("Scripting.FileSystemObject")
folderLoc = obj1FSO.GetParentFolderName("\Cubes_Macro_V5.zmc")
It would then use the folderLoc variable and append the output file name to it in order to create the output file in the same folder as where the macro is stored.
Set repFso = CreateObject("Scripting.FileSystemObject")
Set repFile = repFso.CreateTextFile(folderLoc & "RCHT_OPTION4_REPORT.txt", True)
The Macro is stored in a folder in the D:\ drive but when I run the above segment of code it get the location for the desktop.
https://msdn.microsoft.com/en-us/library/22dyy47c%28v=vs.84%29.aspx
That is not how the method works - it extracts the "parent" from the string provided.
Option Explicit
Dim fso,GetTheParent
Set fso = CreateObject("Scripting.FileSystemObject")
GetTheParent = fso.GetParentFolderName("C:\Windows")
wscript.echo "Attempt 1:" & "'" & GetTheParent & "'"
GetTheParent = fso.GetParentFolderName("\Windows")
wscript.echo "Attempt 2:" & "'" & GetTheParent & "'"
GetTheParent = fso.GetParentFolderName("Windows")
wscript.echo "Attempt 3:" & "'" & GetTheParent & "'"
GetTheParent = fso.GetParentFolderName("C:\WINDOWS\system32")
wscript.echo "Attempt 4:" & "'" & GetTheParent & "'"
GetTheParent = fso.GetParentFolderName("\WINDOWS\system32")
wscript.echo "Attempt 5:" & "'" & GetTheParent & "'"
Results:
Attempt 1:'C:\'
Attempt 2:''
Attempt 3:''
Attempt 4:'C:\WINDOWS'
Attempt 5:'\WINDOWS'
There is a difference between the current directory ('where you are when you start the process') and the script's directory:
>> WScript.Echo 0, goFS.GetAbsolutePathName(".\")
>> WScript.Echo 1, goWS.CurrentDirectory
>> WScript.Echo 2, goFS.GetParentFolderName(WScript.ScriptFullName)
>>
0 C:\Documents and Settings\eh
1 C:\Documents and Settings\eh
2 M:\bin
(I called my REPL/Interactive VBS shell that resides in m:\bin from my home directory)
I don't know if "Cubes_Macro_V5.zmc" is a VBScript file (with a special extension that is loaded by whatever agent you use via w|cscript.exe), but check if WScript.ScriptFullName has the expected content and apply .GetParentFolderName.
If that fails, you need to determine the folder that your agent uses for macros and feed that directory to .BuildPath.
On second thought:
Voodoo but easy to test: Does
WScript.Echo 0, goFS.GetAbsolutePathName(".\Cubes_Macro_V5.zmc")
deliver the desired result?

Changing name of directory containing read-only files

I am trying to get this script to work, it gets 4 arguments and ends renaming the the folder (FDirectory) removing spaces and starting a batch file with the new arguments. The problem is that it returns an error "access denied" for folders containing read-only files. Is there a way to get this to work? Thanks in advance.
Set WshShell = CreateObject("WScript.Shell")
currentDirectory = left(WScript.ScriptFullName,(Len(WScript.ScriptFullName))-(len(WScript.ScriptName)))
length = Len(currentDirectory)
State = WScript.Arguments.item(0)
Directory = Left(WScript.Arguments.item(1),length+6)
FDirectory = Replace(WScript.Arguments.item(1)," ",".")
Kind = WScript.Arguments.item(2)
Message = WScript.Arguments.item(3)
'change folder name
If (kind = "multi") And (Directory = currentDirectory & "SFetch") then
Set FS = CreateObject("Scripting.FileSystemObject")
FS.MoveFolder WScript.Arguments.item(1),Replace(WScript.Arguments.item(1)," ",".")
END IF
currentDirectory = currentDirectory & "Rename.bat "
WshShell.RUN currentDirectory & State & " " & Directory & " " & FDirectory & " " & Kind & " " & Message, 0, True
Set WshShell = Nothing
Read-only files don't create an issue - but renaming a folder with open files inside it, or renaming the current working directory will create problems.

Beginner VBscript: script that zips log files

I am having a problem with my script not actually producing a zip file. When I test the script with the paths set to something like this:
C:\Users\Bob\Desktop\Folder1\Folder2
with the test log files in folder 1 being deleted if older than 7 days, and being zipped and moved to folder 2, it will run perfectly fine. It will produce the zipped file with all of the log files in it and have the proper naming set.
So I know that at least the logic of the script works for that.
My problem is that I need this script to go through the security logs on a machine and delete any older than 7 days, and then zip up any that are left and be sent to a mounted shared drive. When I change the path to something like:
C:\Windows\System32\Config (where the logs are located)
it will still delete any log files older than 7 days, but it does not produce a zip file with any that are left. It just does nothing even though the script produces no errors. I've been trying to figure this out with no luck going over my code. If anyone could take a look over what I've had and let me know where I've gone astray that would be extremely helpful.
Thank you in advance, the script is found below.
'READ FIRST
'------------------------------------------------------------------------------------------
'Lines 14-53 delete any log files older than 7 days. Changing the value in "iDaysOld =" will change the time frame in which files are kept or deleted.
'If files do not need to be deleted this part of the script can be taken out and the Archive/Move ability will still be intact
'Lines 57-102 contain the ability to Zip your log files and send them to a new folder. The zipped file is named after the localhost and a date/timestamp is appended to the file name.
'------------------------------------------------------------------------------------------
Option Explicit
Dim oFSO, oFolder, sDirectoryPath
Dim oFileCollection, oFile, sDir
Dim iDaysOld
' Specify Directory Path From Where You want to clear the old files
sDirectoryPath = "C:\Windows\System32\config"
' Specify Number of Days Old File to Delete
iDaysOld = 7
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFolder = oFSO.GetFolder(sDirectoryPath)
Set oFileCollection = oFolder.Files
For each oFile in oFileCollection
'Specify the Extension of file that you want to delete
'and the number with Number of character in the file extension
If LCase(oFSO.GetExtensionName(oFile.Name)) = "log" Then
If oFile.DateLastModified < (Date() - iDaysOld) Then
oFile.Delete(True)
End If
End If
Next
Set oFSO = Nothing
Set oFolder = Nothing
Set oFileCollection = Nothing
Set oFile = Nothing
WScript.Echo "Press to start zipping log files."
Dim objFile, objPath, objFolder, Command, PathLogs, RetVal
Dim objFSO: Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim objShell: Set objShell = CreateObject("WScript.Shell")
Dim d : d = Date()
Dim dateStr : dateStr = Year(d) & "-" & Right("00" & Month(d), 2) & "-" & Right("00" & Day(d), 2)
Dim t : t = Time()
Dim timeStr: timeStr = Hour(t) & "-" & Right("00" & Minute(t), 2) & "-" & Right("00" & Second(t), 2)
'Path where logs are located
PathLogs = "C:\Windows\System32\config"
'Loop through the logs and zip
Set objPath = objFSO.GetFolder(PathLogs)
For Each objFile In objPath.Files
If (LCase(objFSO.GetExtensionName(objFile)) = "log") Then
' zip files
Command = """C:\Program Files\7-zip\7z.exe"" a " & PathLogs & "%computername%" & "-" & dateStr & "-" & timeStr & ".zip " & PathLogs & objFile.Name
RetVal = objShell.Run(Command,0,true)
End If
Next
WScript.Echo "Zip Successful."
WScript.Echo "Now Moving Zipped Files into Archived Folder"
'move files
Set objFSO = CreateObject("Scripting.FilesystemObject")
objFSO.MoveFile "C:\Windows\System32\config\*.zip" , "C:\Testscripts\testfolder\Archived"
WScript.Echo "Move Successful."
I'd probably try echoing out the 7zip command line, checking that it looks right and running it manually from the same location as the script runs from. It might look wrong when you see it or 7zip might give you a message to indicate what's going on.

Resources