How to use CMD to backup files to .zip for archive? - windows

So this one's a multi-parter (Windows 7).
I have a folder structure as so:
C:
SyncFolder
Backups
[User]
FolderA
Subfolder1
Subfolder2
FolderB
Subfolder3
My aim is to use the folder 'SyncFolder' as a backup system for certain files (Sync folder is actually a folder placed there by a file syncing service).
At present, I have the following within the Sync folder:
a .bat file containing a ROBOCOPY command (which copies 1 file)
a .vbs file which is used to call the .bat file (to avoid the CMD window appearing). This VBS file is being called once per hour by Windows Task Scheduler
the file which is being copied
So here are my questions:
I'm looking for a code (preferably an edit to the existing .bat, as I'm not overly-technical) which can:
Copy Subfolder1 in its entirety into a .zip file, which is named YYYYMMDDHHMM_SubFolder1_Backup (where the date & time is automatically populated)
Move the newly-created .zip file to SyncFolder\Backups (or create it there in the first place?)
Deletes (or overwrites?) the previous backup
Repeats for each Subfolder specified (perhaps as an additional command line?) -- I'm not expecting the commands to identify the folders. I would specify the folders myself
Logs the details of the backup to a .log file located in SyncFolder (i.e. Name of .zip created, Date&Time of backup, size of .zip created)
I'm aware this might be a bit ambitious for CMD or a .bat, but I'm open to any suggestions, but please do bear in mind that I'm not highly technical, so any walk-throughs would be immensely appreciated!
Edit:
Here is my attempt with the .bat code:
#echo off
robocopy "C:\[USER]\[FolderA]\[SubFolder1]" "C:[SyncFolder]\Backups\BackupTest1.zip" *.* /dcopy:T /r:5 /w:5 /log+:"C:\[SyncFolder]\CopyLog.log" /bytes /ts /np
... I've tried this, without luck. This command works, but only creates a folder named BackupTest1.zip (which isn't actually a .zip).

Create a file using notepad, let's save it as ZipCMD.vbs then add the following code.
Set objArgs = WScript.Arguments
Set FS = CreateObject("Scripting.FileSystemObject")
InputFolder = FS.GetAbsolutePathName(objArgs(0))
ZipFile = FS.GetAbsolutePathName(objArgs(1))
CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)
Set objShell = CreateObject("Shell.Application")
Set source = objShell.NameSpace(InputFolder).Items
objShell.NameSpace(ZipFile).CopyHere(source)
wScript.Sleep 3000
Now you can run from cmdline
ZipCMD.vbs "C:\Frank\Folder A\Sub Folder 1" "C:\SyncFolder\Backups\BackupTest1.zip"
if you want to manually zip anything from cmd line.
If you want to schedule it, you can either just add the VBS file, or write a mybackup.cmd file and put the full string below in it and schedule that instead.
mybackup.cmd
ZipCMD.vbs "C:\Frank\Folder A\Sub Folder 1" "C:\SyncFolder\Backups\BackupTest1.zip"

Okay, so building on Gerhard's answer, I've got this:
In C:\SyncFolder, create ZipCMD.vbs using the following code in Notepad
Set objArgs = WScript.Arguments
Set FS = CreateObject("Scripting.FileSystemObject")
InputFolder = FS.GetAbsolutePathName(objArgs(0))
ZipFile = FS.GetAbsolutePathName(objArgs(1))
CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)
Set objShell = CreateObject("Shell.Application")
Set source = objShell.NameSpace(InputFolder).Items
objShell.NameSpace(ZipFile).CopyHere(source)
wScript.Sleep 3000
I've also created a Backups.bat in C:\Syncfolder using the following code in Notepad
#echo off
for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do set dt=%%a
set YYYY=%dt:~0,4%
set MM=%dt:~4,2%
set DD=%dt:~6,2%
set HH=%dt:~8,2%
set Min=%dt:~10,2%
set Sec=%dt:~12,2%
set stamp=%YYYY%%MM%%DD%%HH%%Min%
rem parameters set for use later
Del "C:\SyncFolder\*_BackupTest1.zip"
rem This line removes the old backup first (Not ideal. Open to suggestions)
ZipCMD.vbs "C:\Users\[USER]\[FolderA]\[SubFolder1]" "C:\[SyncFolder]\BackupTest1.zip"
rem This line copies files and folders from the Source to the Destination into a named .zip, without a date.
copy "C:\[SyncFolder]\BackupTest1.zip" "C:\[SyncFolder]\%stamp%_BackupTest1.zip"
rem This line creates a copy of the un-dated file, but appends a Date and Time from the parameters defined at the start of the file.
Del "C:\[SyncFolder]\BackupTest1.zip"
rem This line deletes the un-dated file, leaving only the current, dated backup.
Set File="*_BackupTest1.zip"
FOR /F "usebackq" %%A IN ('%file%') DO set size=%%~zA
rem These lines define a new parameter defined by the .zip's size
Echo %stamp%_BackupTest1.zip %Size% >>BackupLog.log
rem This last line appends a line to a log file containing the name of the .zip created (which contains its' date) and its' size.
The second section of the above .bat (after defining initial parameters) can be repeated for multiple folders.
Lastly, I create a RunBackups.vbs in C:\SyncFolder using the following code in Notepad
Set WshShell = CreateObject("WScript.Shell" )
WshShell.Run chr(34) & "C:\[SyncFolder]\Backups.bat" & Chr(34), 0
Set WshShell = Nothing
This runs the .bat without having the black CMD window appear (i.e. running in 'silent' mode), and is the file I call upon using Task Scheduler to automate the backup process.
Unfortunately, there are still some issues with this:
In the ZipCMD.vbs file, the wScript.Sleep 3000 line causes issues on any .zip files which would take longer than 3 seconds to create. This could be extended, but having it hard-coded may prove troublesome. Open to suggestions as to how to get around this?
In the Backups.bat file, the old backup is deleted prior to the creation of the new backup. This is because I use *_TestBackup1.zip to identify the old backup, which, if used after the backup's creation, would delete both new and old backups. Perhaps moving the first Del command to immediately after the first ZipCMD.vbs command would help, as a backup would always exist?

Related

Cmd file to run executable in a folder of an archived zip file

I have two files which I want to archive. I.e a zip file. Files contained in the archive would be a cmd file and a folder containing the file to run.
I want a cmd script to use to run the file in the folder when the archive file is opened and the cmd file is runned. Would prefer cmd to run silently with no pop up screen.
Can anyone help with the cmd script here?
Assuming that two (2) files are extracted into a directory.
RUNME.CMD
DOIT.EXE
The RUNME.CMD, if it is run, can refer to the directory where it is located.
#ECHO OFF
ECHO My directory is "%~dp0"
IF EXIST "%~dp0DOIT.EXE" ("%~dp0DOIT.EXE")
EXIT /B
Assuming that two (2) files are extracted into a directory.
RUNME.CMD
FOLDER with DOIT.EXE
The RUNME.CMD, if it is run, can refer to the directory where it is located.
#ECHO OFF
ECHO My directory is "%~dp0FOLDER"
IF EXIST "%~dp0FOLDER\DOIT.EXE" ("%~dp0FOLDER\DOIT.EXE")
EXIT /B
This is the Vbs script to use in running this file.
Run.vbs
file.exe
Run.vbs script should be like this.
dim shell
set shell=createobject("wscript.shell")
shell.run "file.exe"
set wshNetwork = CreateObject( "WScript.Network" )`enter code here`
strUserName = wshNetwork.UserName
WScript.Sleep (10000)
X=MSGBOX("File runs successfully" ,0, "Alert For: " & strUserName)
WScript.Interactive = true
Line 4 - 7 ain't compulsory for this task. Its just to locate the Computer Username and display on screen.

VBS file Freezes when run from a different directory in a Batch file

I have a batch file that is programmed to run a VBS file. In the VBS file, it is programmed to play Ping.mp3 hidden(Code below). And when the batch file is run, the VBS file freezes as well as the batch file as seen from the Screenshot below.
BAT Code:
#echo off
cls
pushd %~dp0
Files\Ping.vbs
pause
popd
VBS Code:
Set Sound = CreateObject("WMPlayer.OCX.7")
Sound.URL = "Ping.mp3"
Sound.Controls.play
do while Sound.currentmedia.duration = 0
wscript.sleep 100
loop
wscript.sleep (int(Sound.currentmedia.duration)+1)*1000
I checked to see if the issue was networked based, it was not.
I also checked to see if the issue was the pushd and the popd commands, it was not.
Any help would be appreciated.
I do not have the network stuff, but I replicated the "freeze" using your codes when the Ping.mp3 is in the 'File' directory, the directory where Ping.vbs is located. It played when the mp3 is in the same dir as the Batch file. It means that the "current directory" seen by the vbs is (still) the directory given by pushd %~dp0. So, I suggest replacing Sound.URL = "Ping.mp3" with Sound.URL = "File\Ping.mp3" if your Ping.mp3 is in the 'File' directory.
No need to use the batch, you don't have to cd to the folder.
If you do use the batch, make sure it's cscript.exe that starts the script and not wscript.exe.
Just use the full path in the URL.
If the file is not there you will get the "freeze".
It helps to show some info in the console so that you know where the script is pausing, a primitive debug..
The following works on my system.
Set Sound = CreateObject("WMPlayer.OCX")
Wscript.echo "Media player loaded"
Sound.settings.volume = 50
Sound.URL = "C:\Users\user\vbscript\mp3\ping.mp3"
Wscript.echo "start playing"
Sound.Controls.play
while Sound.Playstate <> 1
Wscript.echo Sound.currentmedia.duration
Wscript.sleep 100
wend

Creating a .zip backup using VBS, without hard-coded Wait timer (Windows 7) [duplicate]

This question already has an answer here:
Zipping a large folder fails
(1 answer)
Closed 5 years ago.
I'm having an issue populating a created .zip folder (used for backing up everything from C:\Source to a .zip located in C:\Destination). The issue arises in the ZipCMD.vbs file. I'll describe my whole process now, and at the end, in bold, I'll describe the issue, and my attempted (and failed) solutions.
There exists a folder containing test data, in C:\Source
In C:\Destination, create ZipCMD.vbs using the following code in Notepad (Credit to Gerhard Barnard)
Set objArgs = WScript.Arguments
Set FS = CreateObject("Scripting.FileSystemObject")
InputFolder = FS.GetAbsolutePathName(objArgs(0))
ZipFile = FS.GetAbsolutePathName(objArgs(1))
CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)
Set objShell = CreateObject("Shell.Application")
Set source = objShell.NameSpace(InputFolder).Items
objShell.NameSpace(ZipFile).CopyHere(source)
WScript.Sleep 3000
I've also created a Backups.bat in C:\Destination using the following code in Notepad
#echo off
for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do set dt=%%a
set YYYY=%dt:~0,4%
set MM=%dt:~4,2%
set DD=%dt:~6,2%
set HH=%dt:~8,2%
set Min=%dt:~10,2%
set Sec=%dt:~12,2%
set stamp=%YYYY%%MM%%DD%%HH%%Min%
rem Parameters set for use later
ZipCMD.vbs "C:\Source" "C:\Destination\BackupTest1.zip"
rem This line copies all files and folders from the Source to the Destination into a named .zip, without a date, by utilising the VBS created earlier.
Del "C:\Destination\*_BackupTest1.zip"
rem This line deletes the old backup (All **final** backups are named using 'YYYYMMDDhhmm_BackupTest1.zip'). The '_' prevents this command deleting the newly-created zip from before.
Rename C:\Destination\BackupTest1.zip %Stamp%_BackupTest1.zip
rem Renames newly-created zip file with datestamp and underscore (for information, and so that it can be identified for deletion next time this is run).
Set File="*_BackupTest1.zip"
FOR /F "usebackq" %%A IN ('%file%') DO set size=%%~zA
rem These lines define a new parameter defined by the created .zip's size
Echo %stamp%%Sec% %stamp%_BackupTest1.zip %Size%>>BackupLog.log
rem This last line appends a line to a log file containing the time the zip was created, the name of the .zip created, and its' size.
The second section of the above .bat (after defining initial parameters) can be repeated for multiple folders, but changing 'Source' each time.
Lastly, I create a RunBackups.vbs in C:\Destination using the following code in Notepad
Set WshShell = CreateObject("WScript.Shell" )
WshShell.Run chr(34) & "C:\[SyncFolder]\Backups.bat" & Chr(34), 0
Set WshShell = Nothing
This runs the .bat without having the black CMD window appear (i.e. running in 'silent' mode), and is the file I call upon using Task Scheduler to automate the backup process.
Problem: The WScript.Sleep 3000 line in ZipCMD.vbs is a bodge. If the entire .zip file can be created in <3 seconds, great. Otherwise, we've got a non-functional backup. Extending this timer can prove problematic for larger or multiple backups.
Solution attempt #1: In ZipCMD.vbs, replacing the 3000 wait, start a loop that checks whether a .zip has been created with name=ZipFile. This creates a .zip with the correct name, but contains no data (i.e. The backup process has created a .zip, but vbs has closed before it had a chance to populate any data/files)
Solution attempt #2: In ZipCMD.vbs, replacing the 3000 wait, count the number of files in Source, and wait (loop) until the .zip contains that number of files, with a 500ms delay between each check. Problem: This works perfectly for all files except the last one to be copied. If the last file can be copied in <500ms, this works. Otherwise, the last file doesn't get copied. Extending this timer can prove problematic for backups containing very large files.
Question: What can I replace the 'Wait' timer with, to ensure that the .zip is created fully each time (without just setting a massive timer), without using any non-default-windows functionality? (i.e. non-third-party (e.g. 7zip))
I've heard that Java/Javascript (?) might get around this issue, but am unsure how/if this would work? (due to limited technical knowledge)
Try this modified ZipCMD.vbs
Set objArgs = WScript.Arguments
Set FS = CreateObject("Scripting.FileSystemObject")
InputFolder = FS.GetAbsolutePathName(objArgs(0))
ZipFile = FS.GetAbsolutePathName(objArgs(1))
CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)
Set objShell = CreateObject("Shell.Application")
Set source = objShell.NameSpace(InputFolder).Items
numfolderitems = objShell.NameSpace(InputFolder).Items.count
objShell.NameSpace(ZipFile).CopyHere(source)
' wait until number of items in zip file is the same as in the folder we are zipping up
' also sometimes gets errors when getting folder object for zip file, probably because it is in use? so ignore these
On Error Resume Next
Do while True
numitemsinzip = objShell.NameSpace(ZipFile).Items.count
If Err.Number = 0 and numitemsinzip = numfolderitems Then
Exit Do
ElseIf Err.Number <> 0 then
Err.Clear
End If
wScript.Sleep 10
Loop
On Error Goto 0
This is basically your solution #2 of waiting until the zip file has all the items in it except I had to make it ignore errors that it would get occasionally. I tested it a few times and it seems to work OK. The only potential issue would be if the zipping operation gets stopped for some reason then the wscript.exe process would just run forever because all the files would never be put in the zip file.

Run batch CODE in a vbscript file

I am trying to make a vbscript file that can run batch code (Note: Not a batch file, but batch code)
The code, which works in a batch file:
IF EXIST "%appdata%\Microsoft\Windows\Start Menu\Programs\MyManufacturer\MyClickOnceApp.appref-ms" (
"%appdata%\Microsoft\Windows\Start Menu\Programs\MyManufacturer\MyClickOnceApp.appref-ms"
) ELSE (start /b "" cmd /c del "%~f0"&exit /b)
I can make the vbscript code almost do what I want using:
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "C:\myscript.bat" & Chr(34), 0
Set WshShell = Nothing
Now I would like to combine these two pieces of code into one file, so something along the lines of:
Set WshShell = CreateObject("WScript.Shell" )
WshShell.Exec "IF EXIST ""%appdata%\Microsoft\Windows\Start Menu\Programs\MyManufacturer\MyClickOnceApp.appref-ms"" (""%appdata%\Microsoft\Windows\Start Menu\Programs\MyManufacturer\MyClickOnceApp.appref-ms"") ELSE (start /b """" cmd /c del ""%~f0""&exit /b)"
Set WshShell = Nothing
However when I run this code I get The system cannot find the file specified. This is expected, since Exec (or Run, or Execute) runs a batch file and not batch code. So, is there a command similar to Exec that will run batch code and not a batch file?
Some extra info that I don't think is necessary to a solution (But included for the sake of completedness):
This code is placed in the startup folder
The code is created in C# in order to run a ClickOnce application on startup
The reason I want to use vbscript is that the batch file opens a cmd window for a second, which is undesirable. My understanding is that the line Set WshShell = Nothing will make the command run invisibly
I have tried including >nul at the end of each line of the batch file, since I read that it will stop the output. This did not work for me.
It is theoretically possible for this to work by using both a .bat and a .vbs file, but this would require putting the .bat file in some other directory and feels generally hackish
I am open to other solutions besides vbscript, provided they can check if the .appref file exists, run the file if so, and delete itself if the file doesn't exist. This may be trivial in vbscript but I've never used vbscript before.
EDIT:
According to #Jason's comment, I have modified the code as follows. Now it runs with no output and without running my app (AKA it doesn't do $#!+)
Set WshShell = CreateObject("WScript.Shell" )
WshShell.Run "cmd.exe /C ""IF EXIST ""%appdata%\Microsoft\Windows\Start Menu\Programs\MyManufacturer\MyClickOnceApp.appref-ms"" (""%appdata%\Microsoft\Windows\Start Menu\Programs\MyManufacturer\MyClickOnceApp.appref-ms"") ELSE (start /b """" cmd /c del ""%~f0""&exit /b)", 0
Set WshShell = Nothing
The problem are the string in the path ! like this it work :
Dim objShell
Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run "cmd /c if exist test1.txt (echo ok & del test1.txt & pause) else (echo ko & pause)"
Try to work with 8.3 format. To resolve the composed-name and don't use string.
But if you're programming in VBS why do you want to use batch code in it ?
If you want to use both make a .BAT file. Or generate it from you're VBS and call it.
Here is a example:
you have a batch called regex.bat :
#echo off &setlocal
for /f "tokens=1* delims=:" %%i in (
'netsh wlan show interfaces ^| findstr /rxc:"[ ]* SSID [ ]*: ..*"'
) do for /f "tokens=*" %%k in ("%%j") do set "SSID=%%k"
echo %SSID% > regex.txt
the vbs looks like this:
Set WshShell = WScript.CreateObject( "WScript.Shell" )
WshShell.Run "regex.bat",0,True
This works for me fine. No cmd-Windows comes up. Hope this helpes you

Windows Script to create folder in explorer using user prompted input

Thanks in advance for any help...I've done some coding in the past in C, matlab, Java, VHDL, Verilog, however I'm unfamiliar with batch files and how they are structured.
I'm trying to write a batch file in windows using notepad to create a new job folder in windows explorer with a name given by user prompted input and then create a new hierarchy of folders in this new folder. As of now I can right click anywhere in windows explorer and execute my script to create a hierarchy of folders however I've be unsuccessful in trying to get user input. I can get the command prompt to come up and ask the user to "Enter Job Name:" but cannot seem to discover the correct way to use this input to create the folder. I would prefer it to be a windows pane but command line is fine if it's too involved to use a windows pane. Lastly I would like to be able to give the user a choice of what type of job they wish to create and then create a different hierarchy of folders based on their selection however I haven't gotten this far yet. Here is what I have so far, I have commented out some things I've tried:
#strfolder = InputBox("Please enter a name for your new folder:")
#set objFSO = CreateObject("Scripting.FileSystemObject")
#objFSO.CreateFolder "Z:\" & strfolder
#set mydir = %cd%
#cd %mydir%
set /p jobName = Enter Job Name:
ECHO %jobName% /b
md %jobName%
#cd /d \%jobName%
cd %cd%\%jobName%
#set objFSO = CreateObject("Scripting.FileSystemObject")
#objFSO.CreateFolder "C:\Users\jarcher\Downloads\ins\test" & strfolder
md 1.Development
md 1.Development\1.Budgets
md 1.Development\2.Manufacturers
md "2.Plans and Specs"
md "2.Plans and Specs"\1.Plans
md "2.Plans and Specs"\2.Specs
md 3.Pricing
md 3.Pricing\1.Quotes
md 3.Pricing\2.Worksheets
md 4.Sumbittals
md 4.Sumbittals\"1.Submittal Reviews"
md 5.Orders
md 5.Orders\"1.Order Summaries"
md 5.Orders\"2.Confirmation Pages"
md 6.Closeout
md 6.Closeout\"1.O&M Manuals"
md 6.Closeout\2.Warranty
Remove the spaces around the =:
set /p jobName=Enter Job Name:
Otherwise a space is part of the name of the variable!

Resources