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
Related
I am trying to create a VBScript that kills 3 processes if they exist.
cscript.exe wscript.exe and cmd.exe
It needs to run a kill command and then check if the process still exists to verify that the previous command worked before continuing. I added a sleep command to give the script time to work before re-checking.
I need this in case I make another VBScript that loops a command that ends up getting stuck infinitely. I plan to link this script to a hotkey as a lifesaver should that happen.
How can I add more processes to this?
' TK CSCRIPT & WSCRIPT & CMD
Set objWMIService = GetObject ("winmgmts:")
foundProc = False
procName1 = "cscript.exe"
For Each Process in objWMIService.InstancesOf ("Win32_Process")
If StrComp(Process.Name,procName1,vbTextCompare) = 0 then
foundProc = True
procID = Process.ProcessId
End If
Next
If foundProc = True Then
Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process where ProcessId =" & procID)
For Each objProcess in colProcessList
objProcess.Terminate()
Next
WScript.Sleep(1000) 'wait 1 second before checking if the process still exists
Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process where ProcessId =" & procID)
If colProcessList.count = 0 Then
End If
End If
You can store what process did you want to kill into an Array like this code below :
Option Explicit
Dim Ws,fso,MyArray,LogFile,OutPut,count,MyProcess
Set Ws = CreateObject("Wscript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
MyArray = Array("cscript.exe","cmd.exe","wscript.exe","notepad.exe","mshta.exe")
LogFile = Left(Wscript.ScriptFullName,InstrRev(Wscript.ScriptFullName, ".")) & "log"
count = 0
If fso.FileExists(LogFile) Then fso.DeleteFile LogFile
Set OutPut = fso.OpenTextFile(LogFile,8,True)
For Each MyProcess in MyArray
Call Kill(MyProcess)
Next
OutPut.WriteLine String(50,"=")
OutPut.WriteLine count & " Process were killed !"
OutPut.WriteLine String(50,"=")
If fso.FileExists(LogFile) Then
ws.run LogFile 'To show the LogFile
End if
'---------------------------------------------------------------------------------------------------
Sub Kill(MyProcess)
On Error Resume Next
Dim colItems,objItem
Set colItems = GetObject("winmgmts:").ExecQuery("Select * from Win32_Process " _
& "Where Name like '%"& MyProcess &"%' AND NOT commandline like '%" & wsh.scriptname & "%'",,48)
For Each objItem in colItems
count= count + 1
OutPut.WriteLine Mid(objItem.CommandLine,InStr(objItem.CommandLine,""" """) + 2)
objItem.Terminate(0)
If Err <> 0 Then
OutPut.WriteLine Err.Description
End If
Next
End Sub
'---------------------------------------------------------------------------------------------------
I was able to piggyback off of Hackoo's response so a big thank you to him for helping me get in the right direction.
Option Explicit
Dim fso,myArray,procName,ws
Set ws = CreateObject("Wscript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
myArray = Array("cmd.exe","cscript.exe","wscript.exe")
For Each procName in myArray
Call Kill(procName)
Next
'---------------------------------------------------------------------------------------------------
Sub Kill(procName)
Dim colProcess,name,objWMIService,strComputer
strComputer = "."
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcess = objWMIService.ExecQuery ("Select * from Win32_Process Where Name like '" & procName & "'")
For Each name in colProcess
name.Terminate
Next
End Sub
'---------------------------------------------------------------------------------------------------
Im writing a batch script to help me collect some bandwidth data about numerous offices on our WAN. It uses random data file creator to help me avoid wan optimisers affecting the results.
How can I copy a file by spawning a standard windows copy window that shows transfer rate?
If i use the 'copy' method, it just copies silently in the cmd window and i cant see the rate.
if not exist "C:\temp\xfertest" mkdir C:\test\xfertest
rdfc C:\test\xfertest\random100.dat 100000000
copy C:\test\xfertest\random100.dat \\nat-srv-007\Deliver
exit
This vbscript wrappped in a batch file will do what you want. Save it with a .bat/.cmd extension. Or without the first line with a .vbs extension.
The technic used is based on com and works with every script language supporting it.
Just to see start/end date time, total bytes and bytes per/s it outputs these values to the console after the copy dialog window has vanished.
rem^ &#cscript //nologo //e:vbscript "%~f0" %* & exit /b
' Copy with the windows dialog box
Option Explicit
Dim cArgs : Set cArgs = WScript.Arguments
Dim iArgCnt : iArgCnt = cArgs.Count
Dim sSource : sSource = cArgs.Item(0)
Dim sDest : sDest = cArgs.Item(1)
Dim oFS : Set oFS = CreateObject("Scripting.FileSystemObject")
Dim oSH : Set oSH = CreateObject("shell.application")
Dim oFile, Size, dStart, dEnd
If iArgCnt <> 2 Then
Wscript.Echo "Wrong args, need SourceFile and DestFolder"
Wscript.Quit
End if
If oFS.FileExists(sSource) Then
Set oFile = oFS.GetFile(sSource)
Size = oFile.Size
If oFS.FolderExists(sDest) Then
dStart = Now()
Wscript.Echo "Copy : " & sSource & " " & sDest
Wscript.Echo "Start: " & dStart & " Size : " & Size
FolderCopyHere sSource, sDest
dEnd = Now()
Wscript.Echo "End : " & dEnd & " per/s: " & _
Int(Size / DateDiff("s", dStart, dEnd))
Else
Wscript.Echo "Destination Folder doesn't exist" & sDest
End if
Else
Wscript.Echo "Source file doesn't exist" & sSource
End if
Wscript.Quit
function FolderCopyHere(sSource,sDest)
dim oFld
set oFld = oSH.NameSpace(sDest)
if not oFld is nothing then
oFld.CopyHere(sSource)
end if
set oFld = nothing
end function
Returning this output on my pc
20:28:24 C:\Test________________________________________
> k:\Bat\CopyExpl.cmd c:\test\big.file Q:\Test
20:28:36 C:\Test________________________________________
> rem &
Copy : c:\test\big.file Q:\Test
Start: 2016-10-30 20:28:36 Size : 2147483648
End : 2016-10-30 20:29:10 per/s: 63161283
20:29:10 C:\Test________________________________________
The Rem stems from the wrapper the dialog box is widely known. HTH
this is my problem:
on a Windows 2003 server I've a folder (c:\test), and every day an application put 3 new files on it.
1° file:
31201610181207000100000000630001
31201610181213000100000000440001
31201610181227000100000000630001
....
2° file:
31201610181214000100000000380002
31201610181234000100000009830002
31201610181344000100000000380002
...
3° file:
31201610181826000100000000580003
31201610190722000100000000580003
31201610191801000100000000580003
...
My goal is to replace ONLY the last 4 characters on each file with a .bat or .vbs script (0001 --> 0031) (0002 --> 0032) (0003 --> 0033).
I've done a .vbs file who works, but it search on all string and not on the last 4 characters.
Option Explicit
Dim objFSO, strFolder, objFolder, objFile
Dim strOldValue1, strNewValue1, strNewValue2, strOldValue2, strNewValue3,
strOldValue3, objRead, strContents, objWrite
Const ForReading = 1
Const ForWriting = 2
strFolder = "c:\test"
strOldValue1 = "0001"
strNewValue1 = "0031"
strOldValue2 = "0002"
strNewValue2 = "0032"
strOldValue3 = "0003"
strNewValue3 = "0033"
' I take the folder
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(strFolder)
' I count the file on the folder
For Each objFile In objFolder.Files
' Read file with textstream object.
Set objRead = objFSO.OpenTextFile(objFile.Path, ForReading)
' Trap error if file is empty or cannot read.
On Error Resume Next
strContents = objRead.readall
If (Err.Number <> 0) Then
On Error GoTo 0
Wscript.Echo "Cannot read: " & objFile.Path
strContents = ""
End If
On Error GoTo 0
objRead.Close
' check what's is inside the folder
If (InStr(strContents, strOldValue1) > 0) Then
strContents = Replace(strContents, strOldValue1, strNewValue1)
Set objWrite = objFSO.OpenTextFile(objFile.Path, ForWriting)
objWrite.Write strContents
objWrite.Close
End If
If (InStr(strContents, strOldValue2) > 0) Then
strContents = Replace(strContents, strOldValue2, strNewValue2)
Set objWrite = objFSO.OpenTextFile(objFile.Path, ForWriting)
objWrite.Write strContents
objWrite.Close
End If
If (InStr(strContents, strOldValue3) > 0) Then
strContents = Replace(strContents, strOldValue3, strNewValue3)
Set objWrite = objFSO.OpenTextFile(objFile.Path, ForWriting)
objWrite.Write strContents
objWrite.Close
End If
next
Thanks for any help!!
Here is a short batch script, which immediately modifies all files C:\test\*.* accordingly:
for %%F in ("C:\test\*.*") do (
for /F "delims=" %%L in ('type "%%~F" ^& ^> "%%~F" rem/') do (
set "LINE=%%L"
setlocal EnableDelayedExpansion
set "LEFT=!LINE:~,-4!"
set "RIGHT=!LINE:~-4!"
if "!RIGHT!"=="0001" set "RIGHT=0031"
if "!RIGHT!"=="0002" set "RIGHT=0032"
if "!RIGHT!"=="0003" set "RIGHT=0033"
>> "%%~F" echo(!LEFT!!RIGHT!
endlocal
)
)
Using JREPL.BAT - a regular expression find/replace utility
for %%F in (c:\test\*) do call jrepl "000(?=[123]$)" "003" /f "%%F" /o -
The above looks at the end of each line for "000" before a "1", "2", or "3", and substitutes "003" for the "000".
JREPL is pure script (hybrid batch/JScript) that runs natively on any Windows machine from XP onward - No 3rd party exe file required.
Thank you very much!!!! it works!!
Also, if you're interested I've found how the make my script work:
I've to add the & VBCrlf to the variable, in this way the script will search for the value + the new line.
strOldValue1 = "0001" & VBCrlf
strNewValue1 = "0031" & VBCrlf
strOldValue2 = "0002" & VBCrlf
strNewValue2 = "0032" & VBCrlf
strOldValue3 = "0003" & VBCrlf
strNewValue3 = "0033" & VBCrlf
I got a very specific question regarding my code.
So I got a folder. In this folder there can be >=0 files.
My first script is running in the background, checking if file-count is >0.
As soon as it is >0, it activates a second script with the path+filename, and as soon as
a file is deleted/removed from the folder, it displays the lifetime of the file.
Everything works fine, but there is one problem:
If there are multiple Files in the folder simultaniously, it only "observers" the top one (filename,ascending). So if the first one gets deleted, it sure does observe the second, but the lifetime is wrong because it did not start until the first one got deleted.
Here are my two codes:
Script1.vbs:
Set fso =CreateObject("Scripting.FileSystemObject")
If WScript.Arguments.Count = 1 Then
pfadTiff0 = CStr(WScript.Arguments(0))
Else
msgbox "Bitte Argumente (Pfade) angeben"
WScript.Quit
End If
While True
Set ordnerTiff0 = fso.GetFolder(pfadTiff0)
Set filesTiff0 = ordnerTiff0.Files
anzFilesTiff0 = ordnerTiff0.Files.Count
If anzFilesTiff0 > 0 Then
For Each objFile in filesTiff0
CreateObject("WScript.Shell").Run "QueueTimeUP.vbs " & objFile.Name & " " & pfadTiff0, 0, True
Next
End If
WScript.Sleep 2000
WEnd
Script2.vbs:
filename = CStr(WScript.Arguments(0))
pfad = CStr(WScript.Arguments(1))
Set fso = CreateObject("Scripting.FileSystemObject")
startZeit = Timer()
komplett = pfad&"\"&filename
While fso.FileExists(komplett) = True
WScript.Sleep 100
WEnd
endZeit = Timer()
differenz = endZeit-startZeit
msgbox "Existenz von Job " & filename & " in Sekunden: " & differenz
Thanks for your help guys.
#Bond: Removing the while true loop is no option, since the program is not allowed to stop running. Even if there are no files at this time, there will always be new files later which have to be observed too. But your hint with the "false" parameter of the Run-Statement was great!
#Rob1991:
Good idea, that was actually my first idea before I put my question here.
I figured it out by myself with a different solution. Maybe it helps anybody:
Set fso =CreateObject("Scripting.FileSystemObject")
If WScript.Arguments.Count = 1 Then
pfadTiff0 = CStr(WScript.Arguments(0))
Else
msgbox "Bitte Argumente (Pfade) angeben"
WScript.Quit
End If
Set ordnerTiff0 = fso.GetFolder(pfadTiff0
Set filesTiff0 = ordnerTiff0.Files
letztesFile = "000a" // PART OF SOLUTION, IT´S "LAST FILE"
While True
For Each objFile in filesTiff0
If objFile.Name > letztesFile Then // PART OF SOLUTION
CreateObject("WScript.Shell").Run "QueueTimeUP.vbs " & objFile.Name & " " & pfadTiff0, 0, False // thanks Bond for "false"
letztesFile = objFile.Name // PART OF SOLUTION
End If
Next
WScript.Sleep 500
WEnd
This statement:
CreateObject("WScript.Shell").Run "QueueTimeUP.vbs " & objFile.Name & " " & pfadTiff0, 0, True
Uses a value of True as the last parameter. That specifies that you want to wait until the script completes (synchronous) before returning. So your main script is put in a wait state until your second script (QueueTimeUp.vbs) exits, which doesn't happen until the first file is deleted.
You should be able to use False as the last param, which doesn't wait for the second script to complete. Then remove your While True loop and just allow your main script to complete.
' Main script. Remove "While True" loop.
Set ordnerTiff0 = fso.GetFolder(pfadTiff0)
Set filesTiff0 = ordnerTiff0.Files
anzFilesTiff0 = ordnerTiff0.Files.Count
If anzFilesTiff0 > 0 Then
For Each objFile in filesTiff0
' Use False for last param to specify asynchronous call...
CreateObject("WScript.Shell").Run "QueueTimeUP.vbs " & objFile.Name & " " & pfadTiff0, 0, False
Next
End If
' Allow script to complete.
Now you'll have a QueueTimeUp.vbs script running for each file in your folder.
FYI: If you're familiar with scripting WMI via VBScript, it provides the __InstanceCreationEvent and __InstanceDeletionEvent classes that can notify your script when a file is created or deleted, respectively. Then you won't have to poll a folder every few seconds looking for changes.
I believe for each file it will load the vbs2, but will not start the next execution until vbs2 has ended. If i used the following code below it will not iterate until the instance of cmd has been ended
For Each objFile in colFiles
oShell.run "cmd /k CD C:\Program File" ,1 , true
Next
I think you would want to have a start timer in your first vbs, and then pipe it to the second vbs2. Which would mean the start time is only called once at the start of the programs execution
startZeit = Timer()
For Each objFile in filesTiff0
CreateObject("WScript.Shell").Run "QueueTimeUP.vbs " & objFile.Name & " " & pfadTiff0 & " " & startZeit , 0, True
Next
vbs 2
startZeit = CStr(WScript.Arguments(2))
Hope this helps
In my batch file, I am calling a VBScript and passing it 3 parameters. The parameters are "IPADDRESS" "PicName" and "Storage", as seen below:
Batch File:
set Pathname="C:\User\username\locationOfFile
cd /d %Pathname%
cscript.exe C:\User\username\locationOfFile\myScript.vbs IPADDRESS PicName Storage
In my VB6 program, the parameter values are defined.
Lets say for instance IPADDRESS = "170.190.xxx.xxx"
Is there a way I can have the batch file read and use the value of IPADDRESS based off the declaration inside the VB6 form? The variables IPADDRESS, PicName, and Storage will be constantly changing based off an outside application the VB6 program talks to so I cant statically set it up in the batch ( ....\myScript.vbs 170.190.xxx.xxx pic1 C:\Storage)
My VBScript is given below:
Option explicit
if WScript.Arguments.Count <> 3 then
WScript.Echo "Missing parameters"
else
Dim imageMagick
Set imageMagick = CreateObject("ImageMagickObject.MagickImage.1")
Dim cam_add
Dim annotate
Dim filename
Dim cmd
Dim WshShell
Dim return
cam_add = """http://" & WScript.Arguments(0) &"/image"""
annotate = """" & WScript.Arguments(1) & " - """ '& Date
filename = """" & WScript.Arguments(2) & WScript.Arguments(1) & ".jpg"""
cmd = "convert " & cam_add & " -fill gold -pointsize 45 -gravity southwest -annotate 0x0+25+25 " & annotate & " -trim +repage -verbose " & filename
WScript.Echo cmd
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.CurrentDirectory = "C:\Program Files\ImageMagick-6.8.0-Q16\"
return = WshShell.Run(cmd)
end if
In summation, I need to to have the batch set up like:
cscript.exe C:\User\username\locationOfFile\myScript.vbs IPADDRESS PicName Storage
so the parameter values can used according to what they are set to inside my VB6 form.
If you were to:
shell "the.bat " & IPADDRESS & " " & PicName & " " & Storage
then within the.bat each space delimited argument is available via %N where N is the ordinal number; so %1 would contain the value of IPADDRESS, %2 would contain PicName's value and so on.
To then forward to the VBScript:
cscript.exe C:\User\username\locationOfFile\myScript.vbs %1 %2 %3
(If any of the variables contain spaces, you will need to "quote" them before passing to the bat file)
(You could also probably just chdir(..) in VB6 then run CScript directly)
For something this simple there is no need for a batch file anyway. After all, you have a whole script to work with.
You can even set the CD from inside there, or set it in the VB6 program as here:
Option Explicit
Private Sub Main()
Dim CD As String
Dim IPADDRESS As String
Dim PicName As String
Dim Storage As String
Dim OrigCD As String
CD = "D:\Photo Archives"
IPADDRESS = "127.0.0.1"
PicName = "Fudd"
Storage = "C:\Storage"
'Cache CD so we can restore it.
'Change CD and drive so it is inherited.
OrigCD = CurDir$()
ChDir CD
ChDrive CD
Shell "cscript """ _
& App.Path & "\test.vbs "" """ _
& IPADDRESS & """ """ _
& PicName & """ """ _
& Storage & """", _
vbNormalFocus
'Restore CD and drive.
ChDir OrigCD
ChDrive OrigCD
'Rest of program.
End Sub
Script sample:
Option Explicit
Private CD
Private Sub Msg(ByVal Text)
With WScript
.StdOut.WriteLine Text
.StdOut.Write "Press ENTER to continue..."
.StdIn.ReadLine
End With
End Sub
If WScript.Arguments.Count <> 3 Then
Msg "Missing parameters"
WScript.Quit
End If
'Show the CD and the arguments.
With CreateObject("WScript.Shell")
CD = .CurrentDirectory
End With
With WScript.Arguments
Msg CD & vbNewLine _
& """" & .Item(0) _
& """ """ & .Item(1) _
& """ """ & .Item(2) & """"
End With
But it doesn't even look like the script is needed. You can build the command, set the CD/drive, and Shell() the built command string all from inside the VB6 program.