Get variable from bat file called from within vbs - batch-file

Solved, scroll down to Clean up #2.
Goal: get the filename variable out of the bat file, passing it back to the calling vbs so it can be used to copy the log file to a central repository.
The test.bat sets variables to establish a file name. It has to end and have the log file closed, before the log file can be copied.
---- vbs to call a bat file in silent mode - works
Set WshShell = CreateObject("WScript.Shell" )
rem Next line, exit with %mFileName% from test.bat
WshShell.Run chr(34) & "C:\hgis\test.bat" & Chr(34), 0
Set WshShell = Nothing
rem MsgBox (%mFullName%) - doesn't work
WScript.Sleep 60000
Dim filesys
set filesys=CreateObject("Scripting.FileSystemObject")
filesys.CopyFile "C:\hgis\%mFullName%", "C:\t\" - doesn't work, a simple file copy does
---- test.bat - works
#echo off
echo Processing test, please wait....
set "mTimestamp=%time:~-8,2%%time:~-5,2%%time:~-2,2%"
set "mDatestamp=%date:~-4,4%%date:~-7,2%%date:~-10,2%"
set "mFileName=%USERNAME%-%mDatestamp%-%mTimestamp%-hgsd.pd.txt"
set "mFullName=c:\hgis\%mFileName%"
echo Opened new log file. >%mFullName%
echo === Starting Time Stamp ============= >>%mFullName%
time /t >>%mFullName%
rem actions
time /t >>%mFullName%
echo.
echo Test completed.
exit /b %mFileName%
Moved into this direction: (now I'm trying to pass arg to test.bat)
Set WshShell = CreateObject("WScript.Shell" )
Set objNetwork = CreateObject("Wscript.Network")
arg = timeStamp()
MsgBox (arg)
rem WScript.Sleep 5000
WshShell.Run chr(34) & "test.bat" & Chr(34), 0
Set WshShell = Nothing
rem WScript.Sleep 60000
rem Dim filesys
rem set filesys=CreateObject("Scripting.FileSystemObject")
rem filesys.CopyFile "C:\hgis\%mFullName%", "C:\t\"
rem filesys.CopyFile "C:\hgis\dummybatch.bat", "C:\t\"
Function timeStamp()
Dim t
t = Now
timeStamp = Year(t) & "-" & _
Right("0" & Month(t),2) & "-" & _
Right("0" & Day(t),2) & "_" & _
Right("0" & Hour(t),2) & _
Right("0" & Minute(t),2) ' '& _ Right("0" & Second(t),2)
timeStamp = objNetwork.UserName & "-" & timeStamp & "-hgsd.pd.txt"
End Function
--- Now its working, but its no longer silent and a DOS window opens
-------- Edit: added ",0" at the end of the WshShell.Run line - runs silently
public param1
Set objNetwork = CreateObject("Wscript.Network")
Set WshShell = CreateObject("WScript.Shell" )
param1 = timeStamp()
WshShell.Run "c:\hgis\test.bat " + param1,0
Set WshShell = Nothing
WScript.Sleep 6000
Dim filesys
set filesys=CreateObject("Scripting.FileSystemObject")
filesys.CopyFile "C:\hgis\" + param1, "C:\t\"
Function timeStamp()
Dim t
t = Now
timeStamp = Year(t) & "-" & _
Right("0" & Month(t),2) & "-" & _
Right("0" & Day(t),2) & "_" & _
Right("0" & Hour(t),2) & _
Right("0" & Minute(t),2) ' '& _ Right("0" & Second(t),2)
timeStamp = objNetwork.UserName & "-" & timeStamp & "-hgsd.pd.txt"
End Function
----- Cleaned up
Public mFilename, mDir
Set objNetwork = CreateObject("Wscript.Network")
Set WshShell = CreateObject("WScript.Shell" )
mDir = "c:\hgis\"
mFilename = objNetwork.UserName & "-" & timeStamp() & "-hgsd.pd.txt"
WshShell.Run mDir + "test.bat " + mFilename,0
Set WshShell = Nothing
WScript.Sleep 3000
Dim filesys
set filesys=CreateObject("Scripting.FileSystemObject")
filesys.CopyFile mDir + mFilename, "C:\t\"
Function timeStamp()
Dim t
t = Now
timeStamp = Year(t) & "-" & _
Right("0" & Month(t),2) & "-" & _
Right("0" & Day(t),2) & "_" & _
Right("0" & Hour(t),2) & _
Right("0" & Minute(t),2) ' '& _ Right("0" & Second(t),2)
End Function
---- Clean up #2
Public filesys, mDir, mFilename
Set filesys = CreateObject("Scripting.FileSystemObject")
Set objNetwork = CreateObject("Wscript.Network")
Set WshShell = CreateObject("WScript.Shell" )
mDir = "c:\hgis\"
mFilename = objNetwork.UserName & "-" & timeStamp() & "-hgsd.pd.txt"
WshShell.Run mDir + "test.bat " + mFilename,0
Set WshShell = Nothing
WScript.Sleep 3000
filesys.CopyFile mDir + mFilename, "C:\t\"
Function timeStamp()
Dim t
t = Now
timeStamp = Year(t) & "-" & _
Right("0" & Month(t),2) & "-" & _
Right("0" & Day(t),2) & "_" & _
Right("0" & Hour(t),2) & _
Right("0" & Minute(t),2) ' '& _ Right("0" & Second(t),2)
End Function
--- As reference --- test.bat
#echo off
set mFullName=%1
echo Open new log file. >%mFullName%
echo === Starting Time Stamp ============= >>%mFullName%
time /t >>%mFullName%
ipconfig >>%mFullName%
time /t >>%mFullName%
echo === Ending Time Stamp =============== >>%mFullName%
exit

When a parent process execute a child one and waits for it to terminate, there is no way that the parent get an environment variable created by the child. The child environment is local to it and it is released when the child process terminate. You need to use a different way to return the value to the parent; for example, via a disk file or redirected Stdin/Stdout.
I used this method, but in the opposite relation: a Batch file that execute a VBS script as child and read its result via Stdout output:
for /F "delims=" %%a in ('Cscript //nologo VBScript.vbs') do set result=%%a
In previous line the VBS program just write the result to Stdout.
I also wrote a Batch-JScript hybrid script with this scheme:
The Batch file is executed from the command-line.
The Batch file execute the JScript code.
The JScript code create some environment variables with PROCESS type.
The JScript code does NOT terminate, but re-execute the Batch file again!
The Batch file have a method to know if it is executed the first time (from the command prompt) or re-executed from the JScript code. In the second case, it can use the environment variables created by the JScript code.

Related

How to open exe file with parameters

I have batch file & vbs file that runs exe application in hidden mode.
Now I would like to open this exe applicatio, but with parameters passed to it.
Batch file:
wscript.exe "C:\~some path~\invisible2.vbs" "C:\~some path~\Rserve_d.exe"
invisible2.vbs:
CreateObject("Wscript.Shell").Run """" & WScript.Arguments(0) & """", 0, False
Above code makes sure it runs hidden. But now I need to pass this parameter to the Rserve_d.exe when starting it:
--RS-conf "E:\~some path~\Rconf.cfg"
Please advise. I've tried with adjustments, but it seems, that there is always something wrong in the syntax.
Build the arguments string for your command from the arguments to the script:
Function qq(str)
qq = """" & str & """"
End Function
args = ""
For i = 1 To WScript.Arguments.Count - 1
If InStr(WScript.Arguments(i), " ") > 0 Then
args = " " & qq(WScript.Arguments(i))
Else
args = " " & WScript.Arguments(i)
End If
Next
CreateObject("Wscript.Shell").Run qq(WScript.Arguments(0)) & args, 0, False
Ansgar Wiechers posted his answer before I did so he should deserve the credits. Unfortunately, I had already made the effort of posting an answer as well. To provide some additional functionality to your batch script, you could also check for the return value of the executed VBScript.
Batch file:
setlocal
set "script=c:\~some path~\invisible2.vbs"
set "program=c:\~some path~\rserve_d.exe"
set "params=--RS-conf "e:\~some path~\rconf.cfg""
cscript "%script%" //nologo "%program%" %params%
:: %errorlevel% = 0 - VBScript was executed successfully
:: %errorlevel% = 1 - Missing arguments
:: %errorlevel% = 2 - Shell object creation failed
:: %errorlevel% = 3 - Run method was unable to execute the program
VBScript:
Option Explicit
On Error Resume Next
Dim objShell,_
strCmdLine,_
intCount
If (WScript.Arguments.Count < 1) Then
WScript.Quit(1)
End If
Set objShell = WScript.CreateObject("WScript.Shell")
If (Err.Number <> 0) Then
WScript.Quit(2)
End If
For intCount = 1 To WScript.Arguments.Count - 1
strCmdLine = strCmdLine & " " & """" & WScript.Arguments.Item(intCount) & """"
Next
objShell.Run """" & WScript.Arguments.Item(0) & """" & strCmdLine, 0, False
If (Err.Number <> 0) Then
WScript.Quit(3)
End If

Script that detect usb when it is inserted and copy files from usb to computer

I am trying to write a windows batch script that will run all the time and when a usb flash drive will be inserted it will copy files from usb to computer.
I've found a lot of script that do different parts of it but none of them works as I want.
Can sombody help me ?
I posted before a vbscript here to do what you want just take a look and try it !
Vbscript to copy files with specific extension from usb when plugged in
Edit on 19/07/2016 #10:42 :
I improved this vbsript to run as admin, and to let executing just one insctance of this script.
AutoSave_USB_SDCARD.vbs to copy into My Documents folder
Option Explicit
' Run as Admin
If Not WScript.Arguments.Named.Exists("elevate") Then
CreateObject("Shell.Application").ShellExecute WScript.FullName _
, WScript.ScriptFullName & " /elevate", "", "runas", 1
WScript.Quit
End If
' To let executing just one insctance of this script
If AppPrevInstance() Then
MsgBox "There is an existing proceeding !" & VbCrLF &_
CommandLineLike(WScript.ScriptName),VbExclamation,"There is an existing proceeding !"
WScript.Quit
Else
Do
Call AutoSave_USB_SDCARD()
Pause(30)
Loop
End If
'**************************************************************************
Function AppPrevInstance()
With GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2")
With .ExecQuery("SELECT * FROM Win32_Process WHERE CommandLine LIKE "_
& CommandLineLike(WScript.ScriptFullName) & _
" AND CommandLine LIKE '%WScript%' OR CommandLine LIKE '%cscript%'")
AppPrevInstance = (.Count > 1)
End With
End With
End Function
'**************************************************************************
Function CommandLineLike(ProcessPath)
ProcessPath = Replace(ProcessPath, "\", "\\")
CommandLineLike = "'%" & ProcessPath & "%'"
End Function
'*************************AutoSave_USB_SDCARD()****************************
Sub AutoSave_USB_SDCARD()
Dim Ws,WshNetwork,NomMachine,MyDoc,strComputer,objWMIService,objDisk,colDisks
Dim fso,Drive,NumSerie,volume,cible,Amovible,Dossier,chemin,Command,Result
Set Ws = CreateObject("WScript.Shell")
Set WshNetwork = CreateObject("WScript.Network")
NomMachine = WshNetwork.ComputerName
MyDoc = Ws.SpecialFolders("Mydocuments")
cible = MyDoc & "\"
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colDisks = objWMIService.ExecQuery _
("SELECT * FROM Win32_LogicalDisk")
For Each objDisk in colDisks
If objDisk.DriveType = 2 Then
Set fso = CreateObject("Scripting.FileSystemObject")
For Each Drive In fso.Drives
If Drive.IsReady Then
If Drive.DriveType = 1 Then
NumSerie=fso.Drives(Drive + "\").SerialNumber
Amovible=fso.Drives(Drive + "\")
Numserie=ABS(INT(Numserie))
volume=fso.Drives(Drive + "\").VolumeName
Dossier=NomMachine & "_" & volume &"_"& NumSerie
chemin=cible & Dossier
Command = "cmd /c Xcopy.exe " & Amovible &" "& chemin &" /I /D /Y /S /J /C"
Result = Ws.Run(Command,0,True)
end if
End If
Next
End If
Next
End Sub
'**************************End of AutoSave_USB_SDCARD()*******************
Sub Pause(Sec)
Wscript.Sleep(Sec*1000)
End Sub
'************************************************************************
This waits for the volumes to change, then copies the USB to c:\test. Lots of message boxes so you can see what's happening. Remove them for production.
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
Wscript.Echo objitem.DriveType
If objitem.DriveType = 2 then
Wscript.Echo objItem.DriveType & " " & objItem.Name & " " & objItem.driveletter
Wscript.Echo "Starting Copying"
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"
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
Try this:
#echo off
set backupcmd=xcopy /s /c /d /e /h /i /r /y /
%backupcmd% "%USERPROFILE%\Pictures" "%drive%\all\My pics"
%backupcmd% "%USERPROFILE%\Favorites" "%drive%\all\Favorites"
%backupcmd% "%USERPROFILE%\Videos" "%drive%\all\Vids"
%backupcmd% "%USERPROFILE%\Documents" "%drive%\all\Docs"
%backupcmd% "%USERPROFILE%\OneDrive" "%drive%\all\Onedrive"
%backupcmd% "%USERPROFILE%\Desktop" "%drive%\all\Desktop"
%backupcmd% "%USERPROFILE%\Network" "%drive%\all\Other devices"

Batch script: I want to run a batch script after giving the print command

I want a script to be executed after 10 seconds of giving the print command from any application.
#echo off
echo.
echo Purging the print queue...
net stop Spooler
echo Deleting all print jobs...
ping localhost -n 4 > nul
del /q %SystemRoot%\system32\spool\printers\*.*
net start Spooler
echo Done!
ping localhost -n 4 > nul
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & _
"." & "\root\cimv2")
Set colMonitoredEvents = objWMIService.ExecNotificationQuery _
("Select * From __InstanceCreationEvent Within 5 Where " _
& "Targetinstance Isa 'CIM_DirectoryContainsFile' and " _
& "TargetInstance.GroupComponent= " _
& "'Win32_Directory.Name=""c:\\\\Windows\\\\System32\\\\Spool\\\\Printers""'")
Do
Set objLatestEvent = colMonitoredEvents.NextEvent
Wscript.Echo objLatestEvent.TargetInstance.PartComponent
Loop
Adapted from http://www.codeproject.com/Articles/42212/WMI-and-File-System-Monitoring
Also this starts a service
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_Service")
For Each objItem in colItems
If Lcase(objitem.Name) = "spooler" Then
msgbox objitem.name & " " & objitem.status & " " & objitem.state
objitem.StartService
End If
Next
And this deletes files in the printers folder
On error resume next
Set fso = CreateObject("Scripting.FileSystemObject")
Set fldr = fso.GetFolder("c:\windows\system32\spool\Printers")
For each f in fldr.files
f.delete
Next
I'm at vwork and my computer broke at home. Something like this.
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & _
"." & "\root\cimv2")
Set colMonitoredEvents = objWMIService.ExecNotificationQuery _
("Select * From __InstanceCreationEvent Within 5 Where " _
& "Targetinstance Isa 'CIM_DirectoryContainsFile' and " _
& "TargetInstance.GroupComponent= " _
& "'Win32_Directory.Name=""c:\\\\Windows\\\\System32\\\\Spool\\\\Printers""'")
Do
wscript.scleep 1000
On error resume next
Set fso = CreateObject("Scripting.FileSystemObject")
Set fldr = fso.GetFolder("c:\windows\system32\spool\Printers")
For each f in fldr.files
f.delete
Next
Loop

When a file is deleted, write this to logfile (BATCH)

Supposedly I want to delete logfiles from the C:\ drive. (XXX-Log1.log XXX-Log2.log)
Question: if a file is deleted (I'm just using the del /f /q C:\*.log command), there's obviously no output.
How can I write output to a logfile when a file is deleted and only then? I know for writing to a logfile you can use >>"D:\What\Ever\Deleted.log", but I'd like to have displayed which files were deleted, if any.
If the folder does not have any subdirectories, then this will work:
#echo off
setlocal enableextensions
del /s "c:\folder\*.log" >file.log
pause
Here is a vbscript you can use to monitor a folder for deletion events. This might do what you want. Just call it with cscript like cscript /nologo monitorfolder.vbs You'll need to edit it to monitor in your path. I just used my C:\temp folder for testing.
MonitorFolder()
Function MonitorFolder()
intInterval = "2"
strDrive = "C:"
strFolder = "\\temp\\"
strComputer = "."
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objFile = objFS.CreateTextFile("C:\temp\Deleted.log")
Set objWMIService = GetObject( "winmgmts:" & _
"{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\cimv2" )
strQuery = _
"Select * From __InstanceOperationEvent" _
& " Within " & intInterval _
& " Where Targetinstance Isa 'CIM_DataFile'" _
& " And TargetInstance.Drive='" & strDrive & "'" _
& " And TargetInstance.Path='" & strFolder & "'"
Set colEvents = objWMIService.ExecNotificationQuery (strQuery)
WScript.Echo "Monitoring events...[Ctl-C] to end"
Do
Set objEvent = colEvents.NextEvent()
Set objTargetInst = objEvent.TargetInstance
Select Case objEvent.Path_.Class
Case "__InstanceDeletionEvent"
objFile.WriteLine(objTargetInst.Name)
End Select
Loop
End Function

The batch changes the vbs code making it unreadable for the vbs to use

The batch changes the vbs code making it unreadable for the vbs to use. How do i fix this?
Batch code:
echo Const HIGH = 128 >> prio.vbs
echo strComputer = "." >> prio.vbs
echo Set objWMIService = GetObject("winmgmts:" _ >> prio.vbs
echo & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") >> prio.vbs
echo Set colProcesses = objWMIService.ExecQuery _ >> prio.vbs
echo ("Select * from Win32_Process Where Name = 'file.exe'") >> prio.vbs
echo For Each objProcess in colProcesses >> prio.vbs
echo objProcess.SetPriority(HIGH) >> prio.vbs
echo Next >> prio.vbs
VBS orginal:
Const HIGH = 128
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcesses = objWMIService.ExecQuery _
("Select * from Win32_Process Where Name = 'file.exe'")
For Each objProcess in colProcesses
objProcess.SetPriority(HIGH)
Next
VBS After :
Const HIGH = 128
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
Set colProcesses = objWMIService.ExecQuery _
("Select * from Win32_Process Where Name = 'file.exe'")
For Each objProcess in colProcesses
objProcess.SetPriority(HIGH)
Next
help please
& characters have a special meaning in CMD (command-chaining), so you have to escape them to get literal ampersands:
echo ^& "{impersonationLevel=impersonate}!\\" ^& strComputer ^& "\root\cimv2") >> prio.vbs
The same is also true for closing parenthesis ')' and '<', '>'
You don't need to create another file, also, don't need any escaping to do it if you can save your vbs code with bat hybrid format:
<!-- :
#echo off && mode 050,03 && title <nul && title .\%~nx0
for /f ^tokens^=* %%i in ('%__APPDIR__%wScript.exe "%~dpnx0?.wsf" ^& cls')do exit /b 2>nul >nul
--> <job> <script language = "vbscript">Const HIGH = 128 : strComputer = ".": Set objWMIService = GetObject("winmgmts:" &_
"{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2"): Set colProcesses = objWMIService.ExecQuery ("Select *"&_
"from Win32_Process Where Name = 'file.exe'"): For Each objProcess in colProcesses: objProcess.SetPriority(HIGH): Next </script></job>
So, don't need any escaping, just execute in command line or click then!
About layout:
<!-- :
#echo off && mode 050,03 && title <nul && title .\%~nx0
for /f ^tokens^=* %%i in ('%__APPDIR__%wScript.exe "%~dpnx0?.wsf" ^& cls')do exit /b 2>nul >nul
--> <job> <script language = "vbscript">
:: your vbs code here ::
</script></job>

Resources