I am trying to make a pretty simple .vbs in Notepad that will do the following, but I am having a bit of trouble as I am a little new to scripting:
Execute a .bat if you select 'Yes', and close the window and do nothing if you select 'No'.
Display a message so you know why you're hitting 'Yes' or 'No'.
Display a window title.
Here's what I have tried to make myself so far:
x=msgbox("MESSAGE HERE",4,"WINDOW TITLE HERE")
const Hidden = 0
const WaitOnReturn = true
set WshShell = CreateObject("WScript.Shell")
WshShell.Run "%HOMEPATH%\Documents\FOLDER\FOLDER\EXAMPLE.BAT", Hidden, WaitOnReturn
WScript.Echo "Done"
It works just fine, however, even if I select 'No', it will still execute the .bat, which I do not want.
Try this code :
Option Explicit
Const Hidden = 0
Const WaitOnReturn = True
Dim Question,BatchFilePath,Message,Title,Result
Title = "Running a .bat through a .vbs"
Message = "Did you want to continue executing this script"
BatchFilePath = "%ProgramFiles%\FolderTest\Folder Name with spaces\EXAMPLE.BAT"
'We add the double quotes in this variable to bypass spaces issues in the path
BatchFilePath = DblQuote(BatchFilePath)
Question = Msgbox(Message,VbYesNo + VbQuestion,Title)
If Question = VbNo Then
MsgBox "You have chosen to quit this script !",vbExclamation,Title
WScript.Quit() ' We quit the script
Else
Result = Run(BatchFilePath,Hidden,WaitOnReturn)
End If
'*********************************************************************
Function Run(StrCmd,Console,bWaitOnReturn)
Dim ws,MyCmd,Result
Set ws = CreateObject("wscript.Shell")
'A value of 0 to hide the MS-DOS console
If Console = 0 Then
MyCmd = "CMD /C " & StrCmd & ""
Result = ws.run(MyCmd,Console,bWaitOnReturn)
If Result = 0 Then
MsgBox "Success",VbInformation,Title
Else
MsgBox "An unknown error has occurred!",16,"An unknown error has occurred!"
End If
End If
'A value of 1 to show the MS-DOS console
If Console = 1 Then
MyCmd = "CMD /K " & StrCmd & ""
Result = ws.run(MyCmd,Console,bWaitOnReturn)
If Result = 0 Then
MsgBox "Success",VbInformation,Title
Else
MsgBox "An unknown error has occurred!",16,"An unknown error has occurred!"
End If
End If
Run = Result
End Function
'*********************************************************************
Function DblQuote(Str)
DblQuote = Chr(34) & Str & Chr(34)
End Function
'*********************************************************************
Try this one:
Set obj = CreateObject("WScript.shell")
Answer = MsgBox("Content Here",vbYesNo,"Title Here")
If Answer = vbYes Then
obj.Run "PATH TO BATCH FILE"
Else
WScript.Quit 0
End If
Related
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
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
Apologies for the shabby formatting...
The following script refers to a simple single-line csv text file on my root directory containing server-name, username and password strings. I appreciate that it is probably the most inelegant, convoluted and inefficient piece of .vbs you've ever seen, but please bear with me, I'm learning. :P The script runs fine and performs all but one operation as expected. When the very last "elseif" statement is encountered it abruptly ends, no messagebox, nothing... I can't fathom how to get the array and iteration to cofunction... Please afford me your time, kindness and assistance, I will be immeasurably grateful.
dim objfso, objinputfile, filepath, searchstr, tmpstr, result, arr(2)
result = msgbox ("Please select" & vbCrLf & " " & vbCrLf & "Yes = Save password" & vbCrLf & "No = Load password ", vbyesnocancel, "Password Manager")
select case result
case vbyes
dim server, user, pass
set fso = createobject("scripting.filesystemobject")
do
server = inputbox ("Please enter server name", "Password manager")
if server = "" then
wscript.quit ()
end if
loop until server <> ""
do
user = inputbox ("Please enter username", "Password manager")
if user = "" then
wscript.quit ()
end if
loop until user <> ""
do
pass = inputbox ("Please enter password", "Password manager")
if pass = "" then
wscript.quit ()
end if
loop until pass <> ""
set file = fso.opentextfile("C:\passwords.txt",8,true)
file.write server & ", " & user & ", " & pass & ", "
file.close
msgbox "Entry added to C:\password.txt"
case vbno
set objfso = createobject("scripting.filesystemobject")
filepath = "C:\passwords.txt"
call SEARCH
sub SEARCH
if objfso.fileexists(filepath) then
do
searchstr = inputbox ("Please enter server name", "Password manager")
if searchstr = "" then
wscript.quit ()
end if
loop until searchstr <> ""
set objinputfile = objfso.opentextfile(filepath)
tmpstr = objinputfile.readline
if instr(lcase(tmpstr),lcase(searchstr)) <= 0 then
result = msgbox ("No matches", vbretrycancel, "Password Manager")
if result = 4 then
call SEARCH
elseif result = 2 then
wscript.quit ()
end if
elseif instr(lcase(tempstr),lcase(searchstr)) > 0 then
for i = 1 to 3
arr(i)
result = msgbox ("Match found" & vbCrLf & " " & vbCrLf & "Username = " & arr(0) & vbCrLf & "Password = " & arr(1), vbretrycancel, "Password Manager")
next
end if
else
result = msgbox ("C:\passwords.txt does not exist", vbokonly, "Password Manager")
end if
end sub
case vbcancel
wscript.quit ()
end select
You should get solution using option explicit statement to force explicit declaration of variables. In that last elseif I see a variable tempstr with no value assignment (should be tmpstr?).
Using proper indentation could help as well.
However, in your next construction:
if xx <= 0 then
' ...
elseif xx > 0 then
' here xx <= 0 is not valid thus always xx > 0 holds
' ...
end if
that elseif is redundant and harmful. Rather, use
if xx <= 0 then
' ...
else
' ...
end if
Another example:
result = msgbox ("No matches", vbretrycancel, "Password Manager")
if result = 4 then
call SEARCH
elseif result = 2 then
wscript.quit ()
else
'''''''''''''''''''''''''''''''''''
' else missing or elseif redundant?
'''''''''''''''''''''''''''''''''''
end if
Last not least: I'd recommend next simple script structure:
' VB Script Document
Option Explicit
On Error Goto 0
' declarations: variables declared by DIM at the script level are available
' to all procedures within the script
Dim arrNames(9) ' Declare an array with 10 elements
Dim dynNames() ' Declare a dynamic array
Dim strMyVar, intMyNum ' Declare two variables
'script code: statements, procedure calls
Wscript.Quit
' declarations: Function and Sub procedures
Sub example
' declarations: variables declared by DIM at the procedure level
' are available only within the procedure
' procedure code: statements, procedure calls
End Sub 'example
' declarations: constants for use in place of literal values
' various useful constants, e.g.
Const ForReading = 1 _
, ForWriting = 2 _
, ForAppending = 8
Const RabbitEars = """"
Const OpenAsDefault = -2 ' Opens the file using the system default.
Const OpenAsUnicode = -1 ' Opens the file as Unicode.
Const OpenAsUSAscii = 0 ' Opens the file as ASCII.
Const NoCreateFileIfNotExist = False
Const DoCreateFileIfNotExist = True
Your script is a complete mess (Sub definition intermixed with top level code); if you want to learn something, read a book about structured programming and start with something a bit more complicated than HelloWorld but much less ambicious that your program.
You don't use Option Explicit. That is why your elseif instr(lcase(tempstr),lcase(searchstr)) > 0 then fails: tmpstr <> tempstr.
The statement arr(i) looks like a stupid call of a Sub arr with a by value parameter i. As there is no such Sub, you'll get a Type Mismatch error on that line.
Instead of file.write server & ", " & user & ", " & pass & ", " you should use .WriteLine (to get a file of lines). The separator should be "," to adhere to the CSV standard.
You can use Split() on .ReadLine() to get your data back. That would give you an array of 3 elements. Those can be looked at - arr(0) = server/searchstr - and displayed - WScript.Echo/MsgBox Join(arr, ",").
Finally, after immense toil (trial, error, and lots of reading and learning in-between) I've managed to create a working script, it may not be elegant or efficient, but it works, and I understand it. As I learn more about vbs I will no doubt revisit this script, and perhaps even improve on it... I thought it maybe important to also include this link, where another friendly, critically constructive gentleman gave me useful pointers... https://social.technet.microsoft.com/Forums/scriptcenter/en-US/8aae30ac-0972-43dd-88fb-7d811d9b9a73#a8579428-f138-4c78-832a-12b6806b0e8c
Thanks again for your (plural) help, now to think of another basic project, to learn new aspects of vbs or solidify learnt ones. :P
option explicit
dim server, user, pass, input, file, txtfile, filepath, line, arr, returnval, searchstr
filepath = "C:\passwords.txt"
input = msgbox ("Please select" & vbCrLf & " " & vbCrLf & "Yes = Save username & password" & vbCrLf & "No = Load username & password ", vbyesnocancel, "Password Manager by CMJR1979")
select case input
case vbyes
do
server = inputbox ("Please enter server name", "Password manager")
if server = "" then
wscript.quit ()
end if
loop until server <> ""
do
user = inputbox ("Please enter username", "Password manager")
if user = "" then
wscript.quit ()
end if
loop until user <> ""
do
pass = inputbox ("Please enter password", "Password manager")
if pass = "" then
wscript.quit ()
end if
loop until pass <> ""
set file = createobject("scripting.filesystemobject")
set txtfile = file.opentextfile(filepath,8,true)
txtfile.writeline server & "," & user & "," & pass
txtfile.close
msgbox "Entry added to C:\password.txt"
case vbno
call SEARCH
case vbcancel
wscript.quit ()
end select
sub SEARCH
filepath = "C:\passwords.txt"
set file = createobject("scripting.filesystemobject")
if file.fileexists(filepath) then
do
searchstr = inputbox ("Please enter server name", "Password manager")
if searchstr = "" then
wscript.quit ()
end if
loop until searchstr <> ""
returnval = SEARCHSTRLINE(searchstr, filepath)
if isempty(returnval) then
input = msgbox ("No matches", vbretrycancel, "Password Manager")
if input = 4 then
call SEARCH
elseif input = 2 then
wscript.quit ()
end if
else
input = msgbox ("Match found" & vbCrLf & " " & vbCrLf & "Servername = " & returnval(0) & vbCrLf & "Username = " & returnval(1) & vbCrLf & "Password = " & returnval(2), vbokonly, "Password Manager")
end if
else
input = msgbox ("C:\passwords.txt does not exist", vbokonly, "Password Manager")
end if
end sub
function SEARCHSTRLINE(x,y)
x = lcase(x)
set file = CreateObject("Scripting.FileSystemObject")
set txtfile = file.opentextfile(y)
while not txtfile.atendofstream
line = txtfile.readline()
arr = split(line,",")
if lcase(arr(0)) = x then
SEARCHSTRLINE = arr
exit function
end if
wend
end function
My VBScript file:
If Not WScript.Arguments.Named.Exists("elevate") Then
Set objShellApp = CreateObject("Shell.Application")
objShellApp.ShellExecute(WScript.FullName, WScript.ScriptFullName & " /elevate", "", "runas", 0)
WScript.Quit 2
WScript.Echo("Done 1")
Else
I need a way to determine, whether the user clicked NO and then return an errorcode to a batch file. Does ShellExecute return any error codes or something?
The problem is that the errorcode returned to the bat is always the same (in this case 2), regardless of whether I clicked yes or no.
EDIT:
Dim objShell, objWMIService, servSpooler, objReg, objShellApp, result, oShell
Dim whoami, strWhoamiOutput, whoamiOutput
Const PrinterPort = "NUL:"
Const HKLM = &h80000002
If Not WScript.Arguments.Named.Exists("elevate") Then
Set objShellApp = CreateObject("Shell.Application")
objShellApp.ShellExecute WScript.FullName, WScript.ScriptFullName & " /elevate", "", "runas", 0
WScript.Quit 10
WScript.Echo("Done 1")
Else
Set oShell = CreateObject("WScript.Shell")
Set whoami = oShell.Exec("whoami /groups")
Set whoamiOutput = whoami.StdOut
strWhoamiOutput = whoamiOutput.ReadAll
If InStr(1, strWhoamiOutput, "S-1-16-12288", vbTextCompare) Then
Wscript.Echo("ADMIN")
WScript.Echo("Port")
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
set servSpooler = objWMIService.Get("Win32_Service.Name='spooler'")
Set objReg = GetObject("winmgmts:root\default:StdRegProv")
servSpooler.StopService
objReg.SetStringValue HKLM, "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports", PrinterPort, ""
servSpooler.StartService
WScript.Quit 1
End if
WScript.Echo("Done 2")
End If
WScript.Quit 2
WScript.Echo("Done 3")
It only ever returns the errorcode of the very first WScript.Quit, after getting the elevating rights. No matter whether I click no or yes. When I click yes, it runs the program as expected, and it does quit after starting the spooler, but the error code returned to the batch is still that of the first Wscript.Quit and not the one after the spooler.
I expect this to run as follows:
no elevated rights
get the elevation, if no, Quit with 10
if user clicked yes: run the script again
run the code in the ELSE block, quit with WScript.Quit 1
the code after the END IFs should never run
EDIT:
If Not WScript.Arguments.Named.Exists("elevate") Then
Set objShellApp = CreateObject("Shell.Application")
objShellApp.ShellExecute WScript.FullName, WScript.ScriptFullName & " /elevate", "", "runas", 0
WScript.Quit 10
WScript.Echo("Done 1")
Else
Dim fso, MyFile
Set fso = CreateObject("Scripting.FileSystemObject")
Set MyFile = fso.CreateTextFile("testfile.txt", True)
MyFile.WriteLine("This is a test.")
MyFile.Close
End If
WScript.Quit 2
WScript.Echo("Done 3")
When I run this from .../System32 it lets me create a file when I click yes. Still, the errorcode is always the same, whether I click yes or no.
Try to create a file in c:\windows\system32 and test the error code.
Only a program marked RequireAdmin will fail when executed. Everything else will start as a limited user.
For your method.
Return Value
No return value.
WScript has a two execute methods. Both have different features so read the docs.
object.Exec(strCommand)
The Exec method returns a WshScriptExec object, which provides status and error information about a script run with Exec along with access to the StdIn, StdOut, and StdErr channels.
object.Run(strCommand, [intWindowStyle], [bWaitOnReturn])
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).
One of your problems is that your code is not written correctly.
You must have On Error Resume Next or your script would have crashed. You use this statement for simple scripts that you want to keep going in case of error. In real scripts it indicates you are handling errors rather than vbs. So you need to code like this.
servSpooler.StartService
If err.number <> 0 then
'print error, exit script
wscript.echo err.number & " " & err.description & " in " & err.source
err.clear
wscript.quit
End If
But if you use vbs error handling it knows the line and column number.
Noooooooo - create the file in code.
On Error Resume Next
'Should fail for everyone so simulates being a user for an admin
Set fso = CreateObject("Scripting.FileSystemObject")
fso.CreateTextFile "C:\System Volume Information\test.txt", vbtrue
msgbox err.number & " " & err.description & " " & err.source
If err.number = 70 then
msgbox "access denied - not an admin"
err.clear
Elseif err.number <> 0 then
Msgbox "Unspecified error"
err.clear
Else
Msgbox "Is an admin"
End If
'Should succeed for admins
fso.CreateTextFile "c:\windows\system32\test.txt", vbtrue
msgbox err.number & " " & err.description & " " & err.source
If err.number = 70 then
msgbox "access denied - not an admin"
err.clear
Elseif err.number <> 0 then
Msgbox "Unspecified error"
err.clear
Else
Msgbox "Is an admin"
End If
I have to execute a batch file using run and get the output in a text file and search that file for a string the code snippet as below,
For running the bat file
Set objShell = WScript.CreateObject("WScript.Shell")
MsgBox("Compiling Source files..Please wait..")
objShell.Run CHR(34) & ".\lib\Compile.bat" & CHR(34) & " > compile.txt" & CHR(34), 0 ,True
I found out that the execution is not going to the next line after run, but if i end process of cmd.exe in task manager the execution happens.
I have mentioned true to wait for the process to get complete after this am reading like below,
Dim objFSO, strLine, objReadFile
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objReadFile = objFSO.OpenTextFile("./compile.txt", 1 , true)
Do Until objReadFile.AtEndOfStream
strLine = objReadFile.ReadLine
....
....
How ever the compile.bat is executing and compile.txt is getting created but the reading process doesn't happen. If i remove the "true" from run command am getting "compile.txt file doesn't exist" error.
I don't know where am making mistake please help me with it..
From all your questions I assume the the story behind your problem
goes something like this:
Your boss, Mr. D. Vader, asked you to develop the build system for
his Java application. "Ok", you said, "let's use Eclipse and/or Ant."
"No", said Mr. Vader, "we will have a modern BS with .BATs and one
button GUIs".
So you set up an experimental project:
tree /a /f .
E:\TRIALS\SOTRIALS\ANSWERS\19944721
|
+---vbs
| | javacompile.hta
| | javacompile.vbs
|
\---java
+---good
| Good.java
|
\---bad
Bad.java
Starting with a minimal Good.java:
class Good {
public static void main(String[] args) {
System.out.println("use Eclipse!");
}
}
you verified:
javac Good.java
- no news are good news --
echo %ERRORLEVEL%
0 <-- javac may set ERRORLEVEL
java Good
use Eclipse! <-- it works
Same procedure for the bad:
class Bad {
public static void main(String[] args) {
System.out.println("D. Vader says: 'Use .bat and one button GUI!'.");
}
javac Bad.java
Bad.java:4: reached end of file while parsing
}
^ <-- javac finds the missing }
1 error
echo %ERRORLEVEL%
1 <-- javac really sets ERRORLEVEL
Then you wrote the minimal GUI: javacompile.hta
<html>
<head>
<Title>JavaCompile</Title>
<hta:application id="javacompile" scroll = "no">
<script type="text/vbscript" src="javacompile.vbs"></script>
</head>
<body>
<form>
<input type="button" id="bttCheckBasics" value="Check Basics"/>
<form>
</body>
</html>
and the 'code behind' javacompile.vbs
Option Explicit
Dim goFS : Set goFS = CreateObject("Scripting.FileSystemObject")
' document.location: "file:///E:/trials/SoTrials/answers/19944721/vbs/javacompile.hta"
Dim gsVbsF : gsVbsF = Replace(goFS.GetParentFolderName(Mid(document.location, 9)), "/", "\")
Dim gsJavaF : gsJavaF = goFS.GetAbsolutePathName(goFS.BuildPath(gsVbsF, "..\java"))
Dim gsGoodF : gsGoodF = goFS.BuildPath(gsJavaF, "good")
Dim gsBadF : gsBadF = goFS.BuildPath(gsJavaF, "bad")
Sub bttCheckBasics_onclick()
MsgBox "Sub bttCheckBasics_onclick() was called."
MsgBox Join(Array("Known Folders:", gsVbsF, gsJavaF, gsGoodF, gsBadF), vbCrLf)
End Sub
and verified that the GUI knows where is what (and the auto-binding works).
(Copy from MessageBox)
Known Folders:
E:\trials\SoTrials\answers\19944721\vbs
E:\trials\SoTrials\answers\19944721\java
E:\trials\SoTrials\answers\19944721\java\good
E:\trials\SoTrials\answers\19944721\java\bad
---------------------------
OK
---------------------------
To get the ball rolling, you added a button to the .hta
<br/>
<input type="button" id="bttKiss" value="Keep It Simple, Stupid"/>
and some code to the vbs:
Sub bttKiss_onclick()
MsgBox "Sub bttKiss_onclick() was called."
KissCompile gsGoodF, "Good.java", "bgood.bat"
KissCompile gsBadF, "Bad.java", "bbat.bat"
End Sub
Sub KissCompile( sF, sJava, sBat)
goWSH.CurrentDirectory = sF
Dim sCmd : sCmd = Join(Array("javac", sJava))
Dim oExec : Set oExec = goWSH.Exec(sCmd)
Do Until cnWshFinished = oExec.Status : Loop
MsgBox Join(Array(qq(sCmd), "(javac) ExitCode:", oExec.ExitCode))
If 0 <> oExec.ExitCode Then MsgBox oExec.StdErr.ReadAll(), vbAbortRetryIgnore, "You messed it up, Mr. Vader!"
End Sub
Function qq(s)
qq = """" & s & """"
End Function
Now the GUI shows for two MessageBoxes for the bad case:
---------------------------
"javac Bad.java" (javac) ExitCode: 1
---------------------------
OK
---------------------------
---------------------------
You messed it up, Mr. Vader!
---------------------------
Bad.java:4: reached end of file while parsing
}
^
1 error
---------------------------
Mr. Vader is not amused: Black windows all over the place and not a single .BAT!
Your ingenious trick of setting goWSH.CurrentDirectory does not impress
him at all.
So you wrote bgood.bat:
#echo off
javac Good.java
IF ERRORLEVEL 1 GOTO :bingo
echo SUCCESS
GOTO :end
:bingo
echo FAILURE
:end
and a corresponding bbad.bat. Some tests:
bbad
Bad.java:4: reached end of file while parsing
}
^
1 error
FAILURE
JAVA E:\trials\SoTrials\answers\19944721\java\bad
echo %ERRORLEVEL%
1
Now the story changes to science fiction. You will follow my advice to
use my BTicks function slightly modified for a better handling of directories and minus a bug wrt to the deletion of log files. So util.vbs looks like
Option Explicit
Const cnWshRunning = 0 ' The job is still running.
Const cnWshFinished = 1 ' The job has completed.
Const SW_SHOWMINNOACTIVE = 7
Const ForReading = 1
Function qq(s)
qq = """" & s & """"
End Function
' BTicks - execute sCmd via WSH.Run
' aRet( 0 ) : goWSH.Run() result
' aRet( 1 ) : StdErr / error message
' aRet( 2 ) : StdOut
' aRet( 3 ) : command to run
Function BTicks(sExecF, sLogF, sCmd )
goWSH.CurrentDirectory = sExecF
Dim aRet : aRet = Array(-1, "", "", "")
Dim sFSpec1 : sFSpec1 = goFS.BuildPath(sLogF, goFS.GetTempName() )
Dim sFSpec2 : sFSpec2 = goFS.BuildPath(sLogF, goFS.GetTempName() )
aRet(3) = Join(Array( _
qq("%comspec%") _
, "/c" _
, qq(Join(Array( _
sCmd _
, "1>" & qq(sFSpec1) _
, "2>" & qq(sFSpec2) _
)))))
Dim aErr
On Error Resume Next
aRet(0) = goWSH.Run(aRet( 3 ), SW_SHOWMINNOACTIVE, True)
aErr = Array(Err.Number, Err.Description, Err.Source)
On Error GoTo 0
If 0 <> aErr(0) Then
aRet(0) = aErr(0)
aRet(1) = Join(Array(aErr(1), aErr(2), "(BTicks)"), vbCrLf)
BTicks = aRet
Exit Function
End If
Dim nIdx : nIdx = 1
Dim sFSpec
For Each sFSpec In Array(sFSpec2, sFSpec1)
If goFS.FileExists(sFSpec) Then
Dim oFile : Set oFile = goFS.GetFile(sFSpec)
If 0 < oFile.Size Then
aRet(nIdx) = oFile.OpenAsTextStream(ForReading).ReadAll()
End If
oFile.Delete
End If
nIdx = nIdx + 1
Next
BTicks = aRet
End Function
As this file has to be included and the 'old' buttons aren't needed
anymore, javacompile.hta changes to
<html>
<head>
<Title>JavaCompile</Title>
<hta:application id="javacompile" scroll = "no">
<script type="text/vbscript" src="javacompile.vbs"></script>
<script type="text/vbscript" src="util.vbs"></script>
</head>
<body>
<form>
<input type="button" id="bttBTicks" value="Use BTicks, Stupid"/>
<form>
</body>
</html>
and javacompile.vbs gets shorter too:
Option Explicit
Dim goFS : Set goFS = CreateObject("Scripting.FileSystemObject")
' document.location: "file:///E:/trials/SoTrials/answers/19944721/vbs/javacompile.hta"
Dim gsVbsF : gsVbsF = Replace(goFS.GetParentFolderName(Mid(document.location, 9)), "/", "\")
Dim gsJavaF : gsJavaF = goFS.GetAbsolutePathName(goFS.BuildPath(gsVbsF, "..\java"))
Dim gsGoodF : gsGoodF = goFS.BuildPath(gsJavaF, "good")
Dim gsBadF : gsBadF = goFS.BuildPath(gsJavaF, "bad")
Dim goWSH : Set goWSH = CreateObject( "WScript.Shell" )
Sub bttBTicks_onclick()
MsgBox "Sub bttUseBTicks_onclick() was called."
Dim aRet
aRet = BTicksCompile(gsGoodF, "javac Good.java")
aRet = BTicksCompile(gsGoodF, "bgood.bat")
aRet = BTicksCompile(gsBadF , "javac Bad.java")
aRet = BTicksCompile(gsBadF , "bbad.bat")
End Sub
Function BTicksCompile(sF, sCmd)
BTicksCompile = BTicks(sF, gsVbsF, sCmd)
MsgBox Join(BTicksCompile, vbCrLf & "--------" & vbCrLf)
End Function
Now there are no more black boxes and the last display (for bbad.bat) shows
the magic word FAILURE.
---------------------------
0
--------
Bad.java:4: reached end of file while parsing
}
^
1 error
--------
FAILURE
--------
"%comspec%" /c "bbad.bat 1>"E:\trials\SoTrials\answers\19944721\vbs\rad6CE21.tmp" 2>"E:\trials\SoTrials\answers\19944721\vbs\radC7CE6.tmp""
---------------------------
OK
---------------------------
Can you specify absolute paths?
If you use the true argument for objFSO.OpenTextFile then it will create the file if it's not found. I can't see why in your case you would want to do that, and this would explain why you are not "reading" the file. If you just created it somewhere, it would be empty.
If you know compile.bat is creating the text file, the next step is to figure out why OpenTextFile isn't finding it. If you use absolute paths, you can quickly resolve this.
If absolute paths are not an option, then use a MsgBox WScript.ScriptFullName or something to verify the path from where the script is running.
You might also do something like this, which would use the relative path of the script's running location
strPath = Replace(WScript.ScriptFullName,WScript.ScriptName,"")
objShell.Run ".\lib\Compile.bat" & " > " & strPath & "compile.txt", 0 ,True
Set objReadFile = objFSO.OpenTextFile(strPath & "compile.txt",1)