How can I start an interactive console for VBS? - vbscript

Very similar to this question:
How can I start an interactive console for Perl?
I just want to be able to start entering VBS statements, one at a time, and have them evaluated straight away, like Python's IDLE.

I wrote this a couple years ago. It's based on this blog post (archived here), but with a couple enhancements. Essentially it's a REPL (Read, Execute, Print, Loop) using the Execute statement:
If Not LCase( Right( WScript.FullName, 12 ) ) = "\cscript.exe" Then
For Each Arg In WScript.Arguments
If InStr( Arg, " " ) Then Arg = """" & Arg & """"
Str = Str & " " & Arg
Next
WshShell.Run "cscript """ & WScript.ScriptFullName & """" & Str, 1
WScript.Quit
End If
Do While True
WScript.StdOut.Write(">>> ")
line = Trim(WScript.StdIn.ReadLine)
If LCase(line) = "exit" Then Exit Do
On Error Resume Next
Execute line
If Err.Number <> 0 Then
WScript.StdErr.WriteLine Err.Description
End If
On Error Goto 0
Loop
I usually start it with a batch file of the same name (i.e. "vbs.vbs" and "vbs.bat"), like this:
#cscript.exe //NoLogo %~dpn0.vbs

You may try to make a debugger (cscript //X your.vbs) work for you, or to start a project of your own - perhaps based on these (first 3?) proposals

Related

Use VBS to run a program with parameters

I'm a total vbs novice trying to perform the supposedly simple task of using a vbscript to run a single program (with parameters).
The path the to program is:
C:\Program Files (x86)\SpeedyFox\speedyfox.exe
and the parameter switch that must go with it is:
/Firefox:C:\Program Files\Firefox\Data\profile
If I wrap both sections in quotes (due to the spaces in their paths) it gives the following combined single command:
"C:\Program Files (x86)\SpeedyFox\speedyfox.exe" "/Firefox:C:\Program Files\Firefox\Data\profile"
If I then paste this into Start > Run it works exactly as I want.
I'm just trying to achieve the same thing from a vbs script instead of manually pasting into the Run box.
I do not want the command to run within a CMD console (as other questions on here have asked). All I am trying to do is to get "C:\Program Files (x86)\SpeedyFox\speedyfox.exe" "/Firefox:C:\Program Files\Firefox\Data\profile" to work with the shell.ShellExecute line of the script below.
Set objShell = Wscript.CreateObject ("Wscript.shell")
set shell=CreateObject("Shell.Application")
shell.ShellExecute ** WHAT DO I PUT HERE? **
set shell=nothing
but try as I might, I just keep getting WSH "Expected end of statement" error messages.
1.First : I recommend you Make it a habit to use this quote function
to make it easy for you to quote variables in these situations !
2. Second : You should use MsgBox or Wscript.echo in order to show
and debug your variables easily !
Wscript.echo DblQuote("Hello World !")
Function DblQuote(Str)
DblQuote = Chr(34) & Str & Chr(34)
End Function
So, I downloaded this application (speedyfox.exe) and i tested it on my Windows 10 (32bits)
So, here is what i tested and it works like a charm on my side :
Option Explicit
Dim objShell,MyCommand,strProgramFiles,SpeedyFoxfile,Title
Title = "Execute SpeedyFox in Commandline"
Set objShell = CreateObject("Shell.Application")
strProgramFiles = GetProgramFilesPath()
SpeedyFoxfile = strProgramFiles & "\SpeedyFox\speedyfox.exe"
MsgBox "Without Double Quotes" & vbCrlf & SpeedyFoxfile,vbInformation,Title
MsgBox "With Double Quotes" & vbCrlf & DblQuote(SpeedyFoxfile),vbInformation,Title
MyCommand = "CD /D "& DblQuote(strProgramFiles &"\SpeedyFox\") &"&"& DblQuote(SpeedyFoxfile) & " " & DblQuote("/Firefox:default") & " " & DblQuote("/Chrome:Default")
MsgBox MyCommand,vbInformation,Title
Call Execute(MyCommand)
'-----------------------------------------
Function Execute(StrCmd)
Dim ws,MyCmd,Result
Set ws = CreateObject("wscript.Shell")
MyCmd = "CMD /K " & StrCmd & ""'
Result = ws.run(MyCmd,1,True)
Execute = Result
End Function
'-----------------------------------------
Function DblQuote(Str)
DblQuote = Chr(34) & Str & Chr(34)
End Function
'-----------------------------------------
Function GetProgramFilesPath()
Dim ws,OsType,strProgramFiles
Set ws = createObject("WScript.Shell")
OsType = ws.RegRead("HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\PROCESSOR_ARCHITECTURE")
If OsType = "x86" then
strProgramFiles = ws.ExpandEnvironmentStrings("%PROGRAMFILES%")
elseif OsType = "AMD64" then
strProgramFiles = ws.ExpandEnvironmentStrings("%PROGRAMFILES(x86)%")
end if
GetProgramFilesPath = strProgramFiles
End Function
'-----------------------------------------
Sigh, reminds me of my vbscript days, now I use Ruby and it's just as simple as
´my_shell_command params´
However, back to your question: the shortest way to use ShellExecute is
CreateObject("Shell.Application").ShellExecute "application", "parameters", "dir", "verb", window
See this documentation for explanation of the parameters.
EDIT:
You have to pay attention at the quotes, they need to be passed to the shell also by using two quotes
eg CreateObject("Shell.Application").ShellExecute "C:\Program Files (x86)\SpeedyFox\speedyfox.exe", """/Waterfox:C:\Program Files\Waterfox\Data\profile"""

Open multiple .vbs one by one

i want .vbs script, to open multiple large files .vbs [i want to Open .vbs one by one] that do not make me, lag in PC.
0001.vbs, 0002.vbs, 0003.vbs, 0004.vbs
is can be different names like:
Anna.vbs, Diana.vbs, Antony.vbs, Andy.vbs
Example:
run C:\0001.vbs
MsgBox "0001.vbs IS END"
Next Open run C:\0002.vbs
MsgBox YES NO
MsgBox "0002.vbs IS END"
Next Open run C:\0003.vbs
MsgBox YES NO
MsgBox "0003.vbs IS END"
Next Open run C:\0004.vbs
MsgBox YES NO
MsgBox "0004.vbs IS END"
Thank you for you help.
Set Shell = CreateObject("WScript.Shell")
For i = 1 To 4
strFile = Right("0000" & i, 4) & ".vbs"
If MsgBox("Would you like to run " & strFile & "?", vbYesNo Or vbQuestion) = vbYes Then
Shell.Run "c:\" & strFile, 1, True
MsgBox strFile & " IS END"
End If
Next
Just make sure you pass True as the last parameter to Shell.Run so that this script waits until the others are done before reporting that they've ended.
Edit: To answer your comment about using names, you can loop through an array created on-the-fly.
For Each strName In Array("Anna", "Diana", "Antony", "Andy")
Next
To not make you wait for each sub process/.vbs before you start the next, don't use the 3rd/wait/true parameter to the .Run method:
a.vbs
Option Explicit
Dim oWSH : Set oWSH = CreateObject("WScript.Shell")
Dim v
For v = 0 To 1
oWSH.Run "cscript.exe " & v & ".vbs", 0, False
Next
MsgBox WScript.ScriptName & " done. " & Now()
0.vbs, 1.vbs
Option Explicit
Randomize
WScript.Sleep Rnd() * 1000
MsgBox WScript.ScriptName & " done. " & Now()
Evidence:
As you can see, a.vbs is finished first and 0.vbs and 1.vbs terminate in random/not in call order.
We have
0001.vbs, 0002.vbs, 0003.vbs, 0004.vbs
Assuming that you have this script file with the after mentioned files in the same directory.
If not, just modify the full path of your vbs files you want to run.
Instead of
WshShell.Run ".\0001.vbs"
You use for example:
WshShell.Run "c:\indel\0001.vbs"
This is the script:
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run ".\0001.vbs"
WshShell.Run ".\0002.vbs"
WshShell.Run ".\0003.vbs"
WshShell.Run ".\0004.vbs"
What you need to do is make this code
do
msgbox("haha you cant close this")
CreateObject ("WScript.Shell").Run(".\Duplicate.vbs")
loop

'for Each objDrive in colDrives' creating function syntax error

I am trying to create a .vbs that will check is a dvd drive exists (if objdrive.drivetype= 4) while ignoring other drives such as hard drives (else if cdrive = 1 then -no statement- ect.).
However this line is causing me grief: "For Each objDrive in colDrives". When it exists it causes a syntax error, yet when it is removed it causes an error saying "object required: objdrive". The script uses a hta/vbs hybrid that offers the user to cancel the search for media, and this is achieved by using a function so putting this in a sub and calling this would be useless. Here is my code, please help.
Set shell=CreateObject("wscript.shell")
Set objShell = Wscript.CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set colDrives = objFSO.Drives
For Each objDrive in colDrives
if objdrive.drivetype= 4 then
select case 1
case 1
if objdrive.isready then
'continue statement here
else
select case 2
case 2
with HTABox("#F2F2F2", 115, 300, 700, 400)
.document.title = "Waiting..."
.msg.innerHTML = "Waiting for playable media...<b>"
end with
function HTABox(sBgColor, h, w, l, t)
Dim IE, HTA
randomize : nRnd = Int(1000000 * rnd)
sCmd = "mshta.exe ""javascript:{new " _
& "ActiveXObject(""InternetExplorer.Application"")" _
& ".PutProperty('" & nRnd & "',window);" _
& "window.resizeTo(" & w & "," & h & ");" _
& "window.moveTo(" & l & "," & t & ")}"""
with CreateObject("WScript.Shell")
.Run sCmd, 1, False
do until .AppActivate("javascript:{new ") : WSH.sleep 10 : loop
end with ' WSHShell
For Each IE In CreateObject("Shell.Application").windows
If IsObject(IE.GetProperty(nRnd)) Then
set HTABox = IE.GetProperty(nRnd)
IE.Quit
HTABox.document.title = "Waiting"
HTABox.document.write _
"<HTA:Application contextMenu=no border=thin " _
& "minimizebutton=no maximizebutton=no sysmenu=no />" _
& "<body scroll=no style='background-color:" _
& sBgColor & ";font:normal 10pt Arial;" _
& "border-Style:normal;border-Width:0px'" _
& "onbeforeunload='vbscript:if (done.value or cancel.value) then " _
& "window.event.cancelBubble=false:" _
& "window.event.returnValue=false:" _
& "cancel.value=false: done.value=false:end if'>" _
& "<input type=hidden id=done value=false>" _
& "<input type=hidden id=cancel value=false>" _
& "<center><span id=msg> </span><br>" _
& " <center><input type=button id=btn1 value=Cancel
' "_
& "onclick=self.close><center></body>"
exit function
End If
Next
MsgBox "HTA window not found."
wsh.quit
End Function
end select
end select
else if objdrive.drivetype = 1 then
else if objdrive.drivetype = 2 then
else if objdrive.drivetype = 3 then
else if objdrive.drivetype = 5 then
end if
The syntax error is most likely caused by the missing Next keyword that would close the loop. I think the conditional if objdrive.isready then is missing a closing End If too (between the two End Select). Add the missing keywords and the error should go away.
However, you're doing this whole thing upside down. Why are you creating an HTA on the fly from a VBScript? Just write the HTA and embed whatever VBScript code you need in it. See this tutorial for an introduction. Also, I would strongly recommend avoiding nested function definitions. They will cause you maintenance headaches at some point and they're not even generally allowed in VBScript. And what are your Select statements supposed to do? A construct
Select Case 1
Case 1
'instruction
End Select
is utterly pointless, because there is no selection in the first place. It's the exact same as running the instruction directly. Another thing to avoid are empty actions in conditionals. They just make your code harder to read and to maintain without generating you any benefit.
Its possible your issue may be due to the Upper Case D in "objDrive" in your For statement and then you later reference the name with a lower case "d" objdrive.isready within the loop. You may want to declare 'Option Explicit' at the top to find all undeclared variables.
Can you test the below code and see if it performs properly.
Set objFSO = CreateObject("Scripting.FileSystemObject")
For Each objDrive in objFSO.Drives
If objDrive.DriveType = 4 Then
If objDrive.IsReady Then
MsgBox "The appropriate media is inserted and ready for access"
Else
MsgBox "The Drive Is Not Ready"
End If
End If
Next
Also, I'm not sure the code snippet you provided is your full code but there appear to be several missing End statements. If so, these may also cause you problems.

VBScript execting wScript not executing properly

Attempting to automate loading in my IIS logs into MSSQL, I have written the following function.
Executing this function causes a cmd prompt to pop up to execute the logparser.exe and then it immediately closes. It stays open long enough for me to see the logparser help menu.
However, if I remove the " >> test.out" portion, it works as expected.
Any idea why? As you see I am outputting the shell string which comes out formed properly as expected.
Function RunLogParser(logFile)
Dim oShell, iRC, ShellString
WScript.Echo "Importing File " + logFile + vbCrLf
ShellString = """C:\Program Files\Log Parser 2.2\LogParser.exe"" ""SELECT * INTO weblog FROM " + logFile + """ " + " -i:W3C -o:SQL -server:localhost -database:testdb -driver:""SQL Server"" -createTable:OFF" + " >> test.out"
WScript.Echo vbTab + "Shell String " + ShellString + vbCrLf
Set oShell = WScript.CreateObject("WScript.Shell")
iRC = oShell.Run(Shellstring, 1, True)
RunLogParser = (iRC=0)
RunLogParser = False
End Function
To use a shell feature (>> redirection) you need a shell; so prepend "%comspec% /c " to your ShellString. Due to the complexity of this command, further tinkering with quotes may be necessary.

Force a VBS to run using cscript instead of wscript

What is the stackoverflow approved (and hence correct) method to force a VBS to run using cscript instead of wscript - irrespective of what the user tries?
A quick Google search shows plenty of examples, but some of them simply don't work and those which do often don't handle the fact that it may have been run with arguments so I'm keen to know what the best way is.
Here is one example which doesn't handle arguments:
sExecutable = LCase(Mid(Wscript.FullName, InstrRev(Wscript.FullName,"\")+1))
If sExecutable <> "cscript.exe" Then
Set oShell = CreateObject("wscript.shell")
oShell.Run "cscript.exe """ & Wscript.ScriptFullName & """"
Wscript.Quit
End If
I appreciate that this could probably be easily modified to handle arguments, but realise that this may not be the best way to approach the problem.
Background: I'm writing a script which can run by double clicking or (most likely) from either a DOS batch file or as a scheduled task. It can contain one or more optional command line arguments.
My Lord, what unadulterated rubbish. It makes me cry to see such cruddy coding (no offense to anybody, lol). Seriously, though, here's my 2 pence:
Sub forceCScriptExecution
Dim Arg, Str
If Not LCase( Right( WScript.FullName, 12 ) ) = "\cscript.exe" Then
For Each Arg In WScript.Arguments
If InStr( Arg, " " ) Then Arg = """" & Arg & """"
Str = Str & " " & Arg
Next
CreateObject( "WScript.Shell" ).Run _
"cscript //nologo """ & _
WScript.ScriptFullName & _
""" " & Str
WScript.Quit
End If
End Sub
forceCScriptExecution
It handles arguments, AND checks for spaces in said arguments -- so that in the case of a filename passed to the original script instance that contained spaces, it wouldn't get "tokenized" when passed to cscript.exe.
Only thing it doesn't do is test for StdIn (e.g., in the case where someone piped something to the script via the command line, but forgot to use "cscript script.vbs") -- but if it was executed by WScript.exe, WScript.StdIn's methods all return Invalid Handle errors, so there's no way to test that anyway.
Feel free to let me know if there's a way to "break" this; I'm willing to improve it if necessary.
Two small additions to forceCScriptExecution let me see its Window after termination and handle its return code.
Sub forceCScriptExecution
Dim Arg, Str
If Not LCase( Right( WScript.FullName, 12 ) ) = "\cscript.exe" Then
For Each Arg In WScript.Arguments
If InStr( Arg, " " ) Then Arg = """" & Arg & """"
Str = Str & " " & Arg
Next
**ret =** CreateObject( "WScript.Shell" ).Run **("cmd /k** cscript //nologo """ & WScript.ScriptFullName & """ " & Str**,1,true)**
WScript.Quit **ret**
End If
End Sub
Notes: "cmd /k" let the windows stay after execution. Parameter "1" activates the window. Parameter "true" waits for termination, so variable "ret" can return the error code.
Here's a similar one in JScript for making .js files run in CScript:
(function(ws) {
if (ws.fullName.slice(-12).toLowerCase() !== '\\cscript.exe') {
var cmd = 'cscript.exe //nologo "' + ws.scriptFullName + '"';
var args = ws.arguments;
for (var i = 0, len = args.length; i < len; i++) {
var arg = args(i);
cmd += ' ' + (~arg.indexOf(' ') ? '"' + arg + '"' : arg);
}
new ActiveXObject('WScript.Shell').run(cmd);
ws.quit();
}
})(WScript);
WScript.echo('We are now in CScript. Press Enter to Quit...');
WScript.stdIn.readLine();
https://gist.github.com/4482361
One approach might be to give it another extension instead of .vbs. Say .cvbs for example. Associate .cvbs with cscript.exe not wscript.exe, that way executing or double clicking a .cvbs file will never invoke the wscript.exe.
Here is my code snippet i use for some of my scripts. It handles Arguments as well. All you have to do is replace the {EnterWorC} with either a "w" or "c" WITH quotes
Dim WorC, Command, Arguments, I
WorC={EnterWOrC} 'Make sure you replace "{EnterWOrC}" with a "w" or a "c" and BE SURE TO PUT QUOTES AROUND THE LETTER.
WorC=LCase (WorC)
If lcase (WorC)="w" Or lcase (WorC)="c" Then
If LCase (Right (WScript.FullName,11))<> WorC & "script.exe" Then
command=WScript.ScriptFullName
Arguments=""
For I=0 To UBound (WScript.Arguments)
Arguments=Arguments & Chr (34) & WScript.Arguments(I) & Chr (34) & Space (1)
Next
CreateObject("Wscript.Shell").Run WorC & "script.exe " & Chr (34) & command & Chr (34) & Space (1) & Arguments, 1
WScript.Quit
End If
WorC=Empty
Command=Empty
I=Empty
Arguments=Empty
End If
Here you will have to replace the 2nd line (2nd NON-blank line)
WorC={EnterWOrC} 'Make sure you replace "{EnterWOrC}" with a "w" or a "c" and BE SURE TO PUT QUOTES AROUND THE LETTER.
For Wscript: WorC="W"
For CScript: WorC="C"
It is NOT case Sensitive.

Resources