Please check what is wrong with the below code. I'm trying to zip the file of one folder and placing it in other folder. I have 94 files but out of that only 80 to 82 or like that some files are zipping. I am using a .bat file:
#setlocal
#echo off
set TIMESTAMP = %DATE:~4,2%-%DATE:~7,2%-%DATE:~10,4%
::CD C:\Desktop\Batchscripts\TESTZIP
::md C:\Desktop\Batchscripts\TESTZIP\%TIMESTAMP%
ECHO ------- BEGIN zip ----------------
CScript "C:\Desktop\Batchscripts\TESTZIP\zip.vbs" "C:\Desktop\Batchscripts\%TIMESTAMP%\" C:\Desktop\Batchscripts\TESTZIP\%TIMESTAMP%.zip
ECHO All production export xml files are completed. please find the location C:\Desktop\Batchscripts\TESTZIP\%TIMESTAMP%.zip
Pause
IF NOT %ERRORLEVEL% EQU 0 (goto :error)
ECHO ------- END zip------------------
which is calling a VBScript:
'Get command-line arguments.
Set objArgs = WScript.Arguments
InputFolder = objArgs(0)
ZipFile = objArgs(1)
'Create empty ZIP file.
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)
'Required!
wScript.Sleep 2000
Most likely your VBScript doesn't wait long enough. Try increasing the value to 5000 or 10000 milliseconds.
The Problem with the CopyHere method is that it runs asynchronously, i.e. it returns immediately instead of waiting until the operation is finished. However, the Shell.Application object is automatically destroyed when the script exits, thus terminating an ongoing CopyHere operation. If that operation wasn't completed at that point, your zip archive will be a couple files short.
Related
i wanted to know if there is some way of doing music with batch, not just opening a mp3 file from cmd, but commands to do notes or something like that. If there really isn't how to do it, i understand.
batch can play music by creating and starting a vbs script to Leverage the internal windows media player.
Note: In all the below scripts, the variable %sounds% refers to the folder your sound scripts are located, and must be defined.
The core of playing music is the following Batch Script:
#Echo off & REM MusicPlayer.bat
Set "MusicPath=%~1" & REM Full Path for the music file
Set "vol=%~2" & REM Volume as number between 0 and 100
Set "LoopTF=%~3" & REM 'paramater 3 as 'true' or 'false' determines if the track is to be looped.
(
PUSHD %sounds%
%= Change to the directory your sound files are located =%)
::: Ensure no Conflict with the Previous Script.
IF exist PlayMusic.vbs (
DEL PlayMusic.vbs
)
::: Creates a vbs Script to launch the music (Occurs without any visual indication or prompting)
(
echo Set Sound = CreateObject("WMPlayer.OCX.7"^)
echo Sound.URL = "%MusicPath%"
echo Sound.settings.volume = %vol%
echo Sound.settings.setMode "loop", %LoopTF%
echo Sound.Controls.play
echo While Sound.playState ^<^> 1
echo WScript.Sleep 100
echo Wend
echo Sound objTS = Nothing 'Destroy the object.
)>PlayMusic.vbs
start /min PlayMusic.vbs
(
POPD
%= Return to your Previous Directory =%)
::: Exit the Launcher and return to Previous batch program.
GOTO :EOF
The above script is called with 3 parameters as Remarked.
Another Vbs can be used to Monitor the batch's status and call a batch script to stop the music when the batch is closed:
#Echo off & REM Monitor.bat
(
ECHO Set objWMIService = GetObject ("winmgmts:"^)
ECHO Set proc = objWMIService.ExecQuery("select * from Win32_Process Where Name='cmd.exe'"^)
ECHO DO while proc.count ^> 0
ECHO Set proc = objWMIService.ExecQuery("select * from Win32_Process Where Name='cmd.exe'"^)
ECHO if proc.count ^< 1 then exit do
ECHO wscript.sleep 1500
ECHO loop
ECHO Set WshShell=createobject("wscript.shell"^)
ECHO WshShell.run "%sounds%\KillMusic.bat", 0, true
)>%sounds%\MusicMonitor.vbs
start %sounds%\MusicMonitor.vbs
Goto :EOF
The above script creates a hidden vbs that fetches the number of instances of cmd.exe via the objWMIService.ExecQuery. This occurs during a loop, with the break condition being 0 open cmd.exe windows. A sleep is built into the loop to reduce the frequency of calls to the WMI service, as these are very resource intensive. When the loop break occurs, it starts the killmusic.bat program in a hidden state.
The below script "KillMusic.bat" is called either directly in your quit label or by the vbs monitor when it determines Cmd.exe is no longer running. DoMonitor is a variable that is changed in your main script prior to killmusic being called. 1 indicates the monitor should be restarted, and is used when killmusic.bat stops a currently playing song to start a new song. Monitor is a Variable containing the path to Monitor.bat
#ECHO OFF & REM KillMusic.bat
taskkill /pid WScript.exe /f /t >nul
IF exist "%sounds%\PlayMusic.vbs" (
DEL /Q "%sounds%\PlayMusic.vbs"
)
Timeout 1 > nul
IF "%DoMonitor%"=="1" GOTO reset
GOTO :EOF
:reset
CALL "%Monitor%"
GOTO :EOF
These three programs can be seen in effect here.
I'm currently working with an old script for a process that was in place before I took a look at it, the premise is to automatically create a folder and copy the contents of a flash drive into a C: drive. Below is the portion of the script I am concerned with:
xcopy "E:\directory" "c:\directory" /s /y
This is the script as I have it now, currently I need to change the first directory entry almost every time I plug into a new device as the drive letter as it appears in the script is sometimes different then what is on the local device. For example, the UBS drive would be D: on a laptop, but E: on most desktops, or some other letter in the case of a device with multiple peripherals.
Previously the script looked something like:
xcopy "...\directory" "c:\directory" /s /y
This doesn't function as the .bat file would come back with an inability to locate said directory on the UBS drive. When I manually change the .bat file to hard set the USB drive letter everything flows fine, all directories copy and the subsequent scripts run fine.
My question, any ideas on how to set the xcopy script to recognize the dynamic USB drive letter and allow for copying without having to change the script on each device?
Thanks!
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
Set evtDevice = objWMIService.ExecNotificationQuery ("SELECT * FROM Win32_VolumeChangeEvent")
Wscript.Echo "Waiting for events ..."
Do
Set objReceivedEvent = evtDevice.NextEvent
'report an event
Wscript.Echo " Win32_Device Changed event occurred" & VBNewLine
If objReceivedEvent.EventType = 1 Then
Wscript.Echo "Type = Config Changed"
ElseIf objReceivedEvent.EventType = 2 Then
Wscript.Echo "Type = Device Arrived"
Set colItems = objWMIService.ExecQuery("Select * From Win32_Volume")
For Each objItem in colItems
If objitem.DriveType = 2 then
Wscript.Echo objItem.DriveType & " " & objItem.Name & " " & objItem.driveletter
Set objShell = CreateObject("Shell.Application")
Set Ag=Wscript.Arguments
set WshShell = WScript.CreateObject("WScript.Shell")
Set SrcFldr=objShell.NameSpace(objitem.driveletter)
Set DestFldr=objShell.NameSpace("c:\test\")
Set FldrItems=SrcFldr.Items
DestFldr.CopyHere FldrItems, &H214
Wscript.Echo "Finished Copying"
Wscript.sleep 2000
End If
Next
ElseIf objReceivedEvent.EventType = 3 Then
Wscript.Echo "Type = Device Left"
ElseIf objReceivedEvent.EventType = 4 Then
Wscript.Echo "Type = Computer Docked"
End If
Loop
This vbs script waits for a USB to be inserted then copies it to a folder.
Remove all the debugging wscript.echo lines. Change the destination folder.
It copies all attached USB drives.
despite the previous answer from Noodles
#echo off
set "destDrive="
for /F "usebackq tokens=1,2 delims==" %i in (`"wmic logicaldisk get caption, drivetype"`) do (
if %%j EQU 2 set "destDrive=%%i"
)
if "%destDrive%" EQU "" (
echo No pendrive found
) else (
echo copying
xcopy "%destDrive%\directory\*.*" "c:\directory\*.*" /s /y
echo done...
)
Why not modify the batch file to ask for the drive letter before the copy begins?
SET /P USB=Enter USB Drive Letter (C:, D:, E: etc):
XCOPY "%USB%\directory" "C:\directory" /s /y
This thread outlines how to code batch hybrids that may include a combination of several scripting languages, such as batch, VBS, JScript, PowerShell, etc. The question is, whether a batch hybrid treats "foreign" language blocks as "functions", meaning calls to these blocks may include arguments like regular and delayed expansion batch variables, that are referenced as usual arguments like %1, %2, etc?
Example below shows the approach in the task of unzipping a file, while using this file unzip code, but it gives an error in Win10 64-bit - why? Note, the linked file unzip code gives an error as well when run in Win 10, but a different one.
<!-- : Begin batch script
#echo off
set "dir=C:\Temp\" & set "file=%USERPROFILE%\Downloads\archive.zip\"
cscript //nologo "%~f0?.wsf" "%dir%" "%file%"
exit /b
----- Begin wsf script --->
<job><script language="VBScript">
set fso = CreateObject("Scripting.FileSystemObject")
If NOT fso.FolderExists(%1) Then
fso.CreateFolder(%1)
End If
set objShell = CreateObject("Shell.Application")
set FilesInZip = objShell.NameSpace(%2).items
objShell.NameSpace(%1).CopyHere(FilesInZip)
set fso = Nothing
set objShell = Nothing
</script></job>
:: Error
..\test.bat?.wsf(9, 8) Microsoft VBScript compilation error: Invalid character
In vbscript the first argument is : wscript.Arguments(0)
the second argument is : wscript.Arguments(1)
So,you should write it like that :
`
----- Begin wsf script --->
<job><script language="VBScript">
set fso = CreateObject("Scripting.FileSystemObject")
If NOT fso.FolderExists(wscript.Arguments(0)) Then
fso.CreateFolder(wscript.Arguments(0))
End If
set objShell = CreateObject("Shell.Application")
set FilesInZip = objShell.NameSpace(wscript.Arguments(1)).items
objShell.NameSpace(wscript.Arguments(0)).CopyHere(FilesInZip)
set fso = Nothing
set objShell = Nothing
</script></job>
I have a process where an incoming file is csv and has trailing commas after the last entry.
I need to process this and send it out sans that final comma as it causes a verification error with the phantom "empty column"
Currently I've got this piece of code to write each line into a new file:
for /f "tokens=* delims=" %%x in (file.csv) do echo %%i >> test.txt
And I've been trying to use something like echo %string:~0,-1% to remove the trailing comma in conjunction but I'm not having much luck. I don't think %%i can be used the same as a string would be referenced with the above. I've tried writing %%i into a string but seems I've got that syntax wrong too.
[edit]
I do run the file through a vbs script to replace the commas with pipes (, = |) so if there's an easier way to do it as part of that process, in my searching of stackoverflow to try and resolve this prior to asking I found this line which I thought may help:
strNewText = strNewText.Substring(0,strNewText.Length-1)
strNewText being the variable holding the updated data, doesn't work though, now the find and replace text section doesn't actually run when I add that in:
rem CREATE Find And Replace Text VBS SCRIPT
echo Const ForReading = 1 > "%tmp%\fart.vbs"
echo Const ForWriting = 2 >> "%tmp%\fart.vbs"
echo strFileName = Wscript.Arguments(0) >> "%tmp%\fart.vbs"
echo strOldText = Wscript.Arguments(1) >> "%tmp%\fart.vbs"
echo strNewText = Wscript.Arguments(2) >> "%tmp%\fart.vbs"
echo Set objFSO = CreateObject("Scripting.FileSystemObject") >> "%tmp%\fart.vbs"
echo Set objFile = objFSO.OpenTextFile(strFileName, ForReading) >> "%tmp%\fart.vbs"
echo strText = objFile.ReadAll >> "%tmp%\fart.vbs"
echo objFile.Close >> "%tmp%\fart.vbs"
echo strNewText = Replace(strText, strOldText, strNewText) >> "%tmp%\fart.vbs"
echo strNewText = strNewText.Substring(0,strNewText.Length-1) >> "%tmp%\fart.vbs"
echo Set objFile = objFSO.OpenTextFile(strFileName, ForWriting) >> "%tmp%\fart.vbs"
echo objFile.WriteLine strNewText >> "%tmp%\fart.vbs"
echo objFile.Close >> "%tmp%\fart.vbs"
(all the echo's are because I generate the vbs during the batch runtime, I tend to find things easier when everything's done in the one file, this vbs file is then deleted later in the process).
#if (#This==#IsBatch) #then
#echo off
rem **** batch zone *********************************************************
type inputfile.csv | cscript //nologo //e:javascript "%~f0" > outputfile.csv
exit /b
#end
// **** Javascript zone *****************************************************
while (!WScript.StdIn.AtEndOfStream) WScript.StdOut.WriteLine(WScript.StdIn.ReadLine().replace(/,[\s,]+$/,''));
This is an hybrid batch/javascript file. Save as batch file, execute and the inputfile.csv file will be piped into cscript.exe that will execute the javascript code included in the same batch file, iterating over the piped data and deleting all commas and final spaces from last comma to end of line. Output from pipe is sent to outputfile.csv
EDITED - As stated in comments, maybe i missunderstood the question, and it is not necessary to remove commaS at the end of the lines, but only the final comma. In this case, the replace expression should be
... .replace(/,$/,''));
Probably the simplest solution for your problem would be sed for Windows:
C:\>sed "s/,$//" <in.csv >out.csv
You could also write a simple VBScript that does the same thing:
Set re = New RegExp
re.Pattern = ",$"
Do Until WScript.StdIn.AtEndOfStream
WScript.Echo re.Replace(WScript.StdIn.ReadLine, "")
Loop
Usage:
C:\>cscript //NoLogo script.vbs <in.csv >out.csv
PowerShell would be an even better option:
PS C:\> (Get-Content 'in.csv') -replace ',$' | Out-File 'out.csv'
I would not recommend using batch for this.
I'm not sure this will work, but since you only want the code to apply for the last line, I've tried implementing the code differently from your average for loop.
#echo off
setlocal enabledelayedexpansion
set previous=
set current=
ren file.csv file.tmp
3<file.tmp (
:loop
set previous=!current!
set /p current=<&3
if "!current!" == "!previous!" (
Echo !current:~0,-1! >> file.csv
) Else (
Echo !current! >> file.csv
goto :loop
)
)
type file.csv
Echo. &Echo Only delete if file.csv is not corrupt
del /p file.tmp
Endlocal
And that should about do what you want.
Mona.
What I am looking to do is create a batch file to replace teh cert8.db file in a users application data folder as well as insert a line of text into one of the prefs.js file. Normally this would be easy, the issue is that there is a good chance some of my users have multiple firefox profiles so I would like to have a script to to replace all cert8.db files in the firefox/profiles folder and insert 1 line of next into all prefs.js files in the firefox/profiles folder.
Can this be done? I am willing to use vb if possible.
You could do something like this:
Set fso = CreateObject("Scripting.FileSystemObject")
profilesFolder = "C:\Users"
firefoxProfiles = "AppData\Roaming\Mozilla\Firefox\Profiles"
For Each fldr In fso.GetFolder(profilesFolder)
profilePath = fso.BuildPath(fldr.Path, firefoxAppdata)
If fso.FolderExists(profilePath) Then
For Each profile In fso.GetFolder(profilePath)
certdb = fso.BuildPath(profile, "cert8.db")
prefs = fso.BuildPath(profile, "prefs.js")
If fso.FileExists(certdb) Then
'replace cert8.db
End If
If fso.FileExists(prefs) Then
'modify prefs.js
End If
Next
End If
Next
The code for replacing the DB file and modifying the preferences depends on where the replacement DB comes from and what you want to add or update in the preferences.
FOR /D %%i IN (C:\Users\*.*) Do FOR /D %%j IN (%%i\AppData\Roaming\Mozilla\Firefox\Profiles\*.*) Do (
CALL :ReplaceDB "%%j\cert8.db"
CALL :ChangeJS "%%j\prefs.js"
)
:ReplaceDB
IF NOT EXIST %1 GOTO :EOF
MOVE /Y %1 "%~1.old"
COPY C:\firefox\cert8.db %1
GOTO :EOF
:ChangeJS
IF NOT EXIST %1 GOTO :EOF
ECHO user_pref("network.proxy.autoconfig_url", "pac.pe.lan/pac/proxy.pac") >> %1
GOTO :EOF
EDIT: Added second FOR to search profiles.
EDIT: Added code for replacing DB and appending line to JS.