I am trying to call a vbs file from another. The called file executes. However the control is not returning to the original vbs file. This file appears to be running as I see wscript process in task manager. But i don't see the output - the step after the run command. Any help/suggestion would be appreciated.
1.) vbs file 1 (original vbs file test3.vbs)
Set objShell = WScript.CreateObject ("WScript.shell")
strErrorCode = objShell.run("cmd /K C:\temp\a\test2.vbs", 0, True)
msgbox "complete test3"
Set objShell = Nothing
2.) vbs file 2 (called vbs file - test2.vbs)
msgbox "in test2"
WScript.Sleep 10000
msgbox "complete - test2"
3.) Expected output :
in test2
complete - test2
complete test3
4.) actual:
in test2
complete - test2
objShell.run("cmd /K C:\temp\a\test2.vbs", 0, True) never ends due to the /K switch:
cmd /?
Starts a new instance of the Windows command interpreter
CMD [/A | /U] [/Q] [/D] [/E:ON | /E:OFF] [/F:ON | /F:OFF] [/V:ON | /V:OFF]
[[/S] [/C | /K] string]
/C Carries out the command specified by string and then terminates
/K Carries out the command specified by string but remains
So cmd window remains open but it is hidden owing to the intWindowStyle parameter: 0 = Hides the window and activates another window, supposing the Run method syntax pattern as .Run(strCommand, [intWindowStyle], [bWaitOnReturn])
Use either
strErrorCode = objShell.run("cmd /C C:\temp\a\test2.vbs", 0, True)
or
strErrorCode = objShell.run("wscript.exe C:\temp\a\test2.vbs", 0, True)
or even
strErrorCode = objShell.run("C:\temp\a\test2.vbs", 0, True)
I need to write a diagnostic utility in VBS which i will package in my windows application installer.
I want the utility to run silently when the user is installing the application.
I tried:
Set pingCXS = objShell.Run("tracert -h 9 webaddress", 0, True)
Set pingCXSOutput = pingCXS.StdOut
strpingCXSOutput = pingCXSOutput.ReadAll
but it returns only the error code not the whole ping information.
When i use run method it gives a command window pop up:
Any other method to traceRT the webaddress without windows popup?
Also using a batch file is not a good option for me, as i have to use some WMI queries in the utility, which will require admin rights in batch file...
Please help out
Try this code :
Option Explicit
Dim ws,fso,TmpLogFile,Logfile,MyCmd,Webaddress,Param
Set ws = CreateObject("wscript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
TmpLogFile = "TmpFile.txt"
LogFile = Left(Wscript.ScriptFullName,InstrRev(Wscript.ScriptFullName, ".")) & "log"
If fso.FileExists(LogFile) Then fso.DeleteFile LogFile
webaddress = "www.stackoverflow.com"
Param = "-h 9"
MyCmd = "Tracert " & Param & " " & Webaddress & " >> "& TmpLogFile &_
" & cmd /U /C Type " & TmpLogFile & " > " & LogFile & " & Del " & TmpLogFile & ""
Call Run(MyCmd,0,True)
ws.run LogFile
'**********************************************************************************************
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"
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"
Else
MsgBox "An unknown error has occurred!",16,"An unknown error has occurred!"
End If
End If
Run = Result
End Function
Is there a way to display a message box from a batch file (similar to how xmessage can be used from bash-scripts in Linux)?
First of all, DOS has nothing to do with it, you probably want a Windows command line solution (again: no DOS, pure Windows, just not a Window, but a Console).
You can either use the VBScript method provided by boflynn or you can mis-use net send or msg. net send works only on older versions of windows:
net send localhost Some message to display
This also depends on the Messenger service to run, though.
For newer versions (XP and onward, apparently):
msg "%username%" Some message to display
It should be noted that a message box sent using msg.exe will only last for 60 seconds. This can however be overridden with the /time:xx switch.
I would make a very simple VBScript file and call it using CScript to parse the command line parameters.
Something like the following saved in MessageBox.vbs:
Set objArgs = WScript.Arguments
messageText = objArgs(0)
MsgBox messageText
Which you would call like:
cscript MessageBox.vbs "This will be shown in a popup."
MsgBox reference if you are interested in going this route.
Might display a little flash, but no temp files required. Should work all the way back to somewhere in the (IIRC) IE5 era.
mshta javascript:alert("Message\n\nMultiple\nLines\ntoo!");close();
Don't forget to escape your parentheses if you're using if:
if 1 == 1 (
mshta javascript:alert^("1 is equal to 1, amazing."^);close^(^);
)
This will pop-up another Command Prompt window:
START CMD /C "ECHO My Popup Message && PAUSE"
Try :
Msg * "insert your message here"
If you are using Windows XP's command.com, this will open a message box.
Opening a new cmd window isn't quite what you were asking for, I gather.
You could also use VBScript, and use this with your .bat file. You would open it from the bat file with this command:
cd C:\"location of vbscript"
What this does is change the directory command.com will search for files from, then on the next line:
"insert name of your vbscript here".vbs
Then you create a new Notepad document, type in
<script type="text/vbscript">
MsgBox "your text here"
</script>
You would then save this as a .vbs file (by putting ".vbs" at the end of the filename), save as "All Files" in the drop down box below the file name (so it doesn't save as .txt), then click Save!
Few more ways.
1) The geekiest and hackiest - it uses the IEXPRESS to create small exe that will create a pop-up with a single button (it can create two more types of pop-up messages). Works on EVERY windows from XP and above:
;#echo off
;setlocal
;set ppopup_executable=popupe.exe
;set "message2=click OK to continue"
;
;del /q /f %tmp%\yes >nul 2>&1
;
;copy /y "%~f0" "%temp%\popup.sed" >nul 2>&1
;(echo(FinishMessage=%message2%)>>"%temp%\popup.sed";
;(echo(TargetName=%cd%\%ppopup_executable%)>>"%temp%\popup.sed";
;(echo(FriendlyName=%message1_title%)>>"%temp%\popup.sed"
;
;iexpress /n /q /m %temp%\popup.sed
;%ppopup_executable%
;rem del /q /f %ppopup_executable% >nul 2>&1
;pause
;endlocal
;exit /b 0
[Version]
Class=IEXPRESS
SEDVersion=3
[Options]
PackagePurpose=InstallApp
ShowInstallProgramWindow=1
HideExtractAnimation=1
UseLongFileName=0
InsideCompressed=0
CAB_FixedSize=0
CAB_ResvCodeSigning=0
RebootMode=N
InstallPrompt=%InstallPrompt%
DisplayLicense=%DisplayLicense%
FinishMessage=%FinishMessage%
TargetName=%TargetName%
FriendlyName=%FriendlyName%
AppLaunched=%AppLaunched%
PostInstallCmd=%PostInstallCmd%
AdminQuietInstCmd=%AdminQuietInstCmd%
UserQuietInstCmd=%UserQuietInstCmd%
SourceFiles=SourceFiles
[SourceFiles]
SourceFiles0=C:\Windows\System32\
[SourceFiles0]
%FILE0%=
[Strings]
AppLaunched=subst.exe
PostInstallCmd=<None>
AdminQuietInstCmd=
UserQuietInstCmd=
FILE0="subst.exe"
DisplayLicense=
InstallPrompt=
2) Using MSHTA. Also works on every windows machine from XP and above (despite the OP do not want "external" languages the JavaScript here is minimized). Should be saved as .bat:
#if (true == false) #end /*!
#echo off
mshta "about:<script src='file://%~f0'></script><script>close()</script>" %*
goto :EOF */
alert("Hello, world!");
or in one line:
mshta "about:<script>alert('Hello, world!');close()</script>"
or
mshta "javascript:alert('message');close()"
or
mshta.exe vbscript:Execute("msgbox ""message"",0,""title"":close")
3) Here's parameterized .bat/jscript hybrid (should be saved as bat). It again uses JavaScript despite the OP request but as it is a bat it can be called as a bat file without worries. It uses POPUP which allows a little bit more control than the more popular MSGBOX. It uses WSH, but not MSHTA like in the example above.
#if (#x)==(#y) #end /***** jscript comment ******
#echo off
cscript //E:JScript //nologo "%~f0" "%~nx0" %*
exit /b 0
#if (#x)==(#y) #end ****** end comment *********/
var wshShell = WScript.CreateObject("WScript.Shell");
var args=WScript.Arguments;
var title=args.Item(0);
var timeout=-1;
var pressed_message="button pressed";
var timeout_message="timed out";
var message="";
function printHelp() {
WScript.Echo(title + "[-title Title] [-timeout m] [-tom \"Time-out message\"] [-pbm \"Pressed button message\"] [-message \"pop-up message\"]");
}
if (WScript.Arguments.Length==1){
runPopup();
WScript.Quit(0);
}
if (args.Item(1).toLowerCase() == "-help" || args.Item(1).toLowerCase() == "-h" ) {
printHelp();
WScript.Quit(0);
}
if (WScript.Arguments.Length % 2 == 0 ) {
WScript.Echo("Illegal arguments ");
printHelp();
WScript.Quit(1);
}
for (var arg = 1 ; arg<args.Length;arg=arg+2) {
if (args.Item(arg).toLowerCase() == "-title") {
title = args.Item(arg+1);
}
if (args.Item(arg).toLowerCase() == "-timeout") {
timeout = parseInt(args.Item(arg+1));
if (isNaN(timeout)) {
timeout=-1;
}
}
if (args.Item(arg).toLowerCase() == "-tom") {
timeout_message = args.Item(arg+1);
}
if (args.Item(arg).toLowerCase() == "-pbm") {
pressed_message = args.Item(arg+1);
}
if (args.Item(arg).toLowerCase() == "-message") {
message = args.Item(arg+1);
}
}
function runPopup(){
var btn = wshShell.Popup(message, timeout, title, 0x0 + 0x10);
switch(btn) {
// button pressed.
case 1:
WScript.Echo(pressed_message);
break;
// Timed out.
case -1:
WScript.Echo(timeout_message);
break;
}
}
runPopup();
4) and one jscript.net/.bat hybrid (should be saved as .bat) .This time it uses .NET and compiles a small .exe file that could be deleted:
#if (#X)==(#Y) #end /****** silent jscript comment ******
#echo off
::::::::::::::::::::::::::::::::::::
::: compile the script ::::
::::::::::::::::::::::::::::::::::::
setlocal
::if exist "%~n0.exe" goto :skip_compilation
:: searching the latest installed .net framework
for /f "tokens=* delims=" %%v in ('dir /b /s /a:d /o:-n "%SystemRoot%\Microsoft.NET\Framework\v*"') do (
if exist "%%v\jsc.exe" (
rem :: the javascript.net compiler
set "jsc=%%~dpsnfxv\jsc.exe"
goto :break_loop
)
)
echo jsc.exe not found && exit /b 0
:break_loop
call %jsc% /nologo /out:"%~n0.exe" "%~f0"
::::::::::::::::::::::::::::::::::::
::: end of compilation ::::
::::::::::::::::::::::::::::::::::::
:skip_compilation
::
::::::::::
"%~n0.exe" %*
::::::::
::
endlocal
exit /b 0
****** end of jscript comment ******/
import System;
import System.Windows;
import System.Windows.Forms
var arguments:String[] = Environment.GetCommandLineArgs();
MessageBox.Show(arguments[1],arguments[0]);
5) and at the end one single call to powershell that creates a pop-up (can be called from command line or from batch if powershell is installed):
powershell [Reflection.Assembly]::LoadWithPartialName("""System.Windows.Forms""");[Windows.Forms.MessageBox]::show("""Hello World""", """My PopUp Message Box""")
6) And the dbenham's approach seen here
start "" cmd /c "echo(&echo(&echo Hello world! &echo(&pause>nul"
7) For a system tray notifications you can try this:
call SystemTrayNotification.bat -tooltip warning -time 3000 -title "Woow" -text "Boom" -icon question
This way your batch file will create a VBS script and show a popup. After it runs, the batch file will delete that intermediate file.
The advantage of using MSGBOX is that it is really customaziable (change the title, the icon etc) while MSG.exe isn't as much.
echo MSGBOX "YOUR MESSAGE" > %temp%\TEMPmessage.vbs
call %temp%\TEMPmessage.vbs
del %temp%\TEMPmessage.vbs /f /q
Here's a PowerShell variant that doesn't require loading assemblies prior to creating the window, however it runs noticeably slower (~+50%) than the PowerShell MessageBox command posted here by #npocmaka:
powershell (New-Object -ComObject Wscript.Shell).Popup("""Operation Completed""",0,"""Done""",0x0)
You can change the last parameter from "0x0" to a value below to display icons in the dialog (see Popup Method for further reference):
0x10 Stop
0x20 Question Mark
0x30 Exclamation Mark
0x40 Information Mark
Adapted from the Microsoft TechNet article PowerTip: Use PowerShell to Display Pop-Up Window.
echo X=MsgBox("Message Description",0+16,"Title") >msg.vbs
–you can write any numbers from 0,1,2,3,4 instead of 0 (before the ‘+’ symbol) & here is the meaning of each number:
0 = Ok Button
1 = Ok/Cancel Button
2 = Abort/Retry/Ignore button
3 = Yes/No/Cancel
4 = Yes/No
–you can write any numbers from 16,32,48,64 instead of 16 (after the ‘+’ symbol) & here is the meaning of each number:
16 – Critical Icon
32 – Warning Icon
48 – Warning Message Icon
64 – Information Icon
Msg * "insert your message here"
works fine, just save as a .bat file in notepad or make sure the format is set to "all files"
msg * /time:0 /w Hello everybody!
This message waits forever until OK is clicked (it lasts only one minute by default) and works fine in Windows 8.1
In order to do this, you need to have a small program that displays a messagebox and run that from your batch file.
You could open a console window that displays a prompt though, but getting a GUI message box using cmd.exe and friends only is not possible, AFAIK.
Following on #Fowl's answer, you can improve it with a timeout to only appear for 10 seconds using the following:
mshta "javascript:var sh=new ActiveXObject( 'WScript.Shell' ); sh.Popup( 'Message!', 10, 'Title!', 64 );close()"
See here for more details.
You can invoke dll function from user32.dll i think
Something like
Rundll32.exe user32.dll, MessageBox (0, "text", "titleText", {extra flags for like topmost messagebox e.t.c})
Typing it from my Phone, don't judge me... otherwise i would link the extra flags.
I use a utility named msgbox.exe from here:
http://www.paulsadowski.com/WSH/cmdprogs.htm
You can use Zenity, which posts regular releases on download.gnome.org. Zenity allows for the execution of dialog boxes in command-line and shell scripts. More info can also be found on Wikipedia.
It is cross-platform, but I couldn't find a recent win32 build. Unfortunately placella.com went offline. A Windows installer of v3.20 (from March 2016) can be found here.
This application can do that, if you convert (wrap) your batch files into executable files.
Simple Messagebox
%extd% /messagebox Title Text
Error Messagebox
%extd% /messagebox Error "Error message" 16
Cancel Try Again Messagebox
%extd% /messagebox Title "Try again or Cancel" 5
4) "Never ask me again" Messagebox
%extd% /messageboxcheck Title Message 0 {73E8105A-7AD2-4335-B694-94F837A38E79}
Here is my batch script that I put together based on the good answers here & in other posts
You can set title timeout & even sleep to schedule it for latter & \n for new line
Name it popup.bat & put it in your windows path folder to work globally on your pc
For example popup Line 1\nLine 2 will produce a 2 line popup box
(type popup /? for usage)
Here is the code
<!-- : Begin CMD
#echo off
cscript //nologo "%~f0?.wsf" %*
set pop.key=[%errorlevel%]
if %pop.key% == [-1] set pop.key=TimedOut
if %pop.key% == [1] set pop.key=Ok
if %pop.key% == [2] set pop.key=Cancel
if %pop.key% == [3] set pop.key=Abort
if %pop.key% == [4] set pop.key=Retry
if %pop.key% == [5] set pop.key=Ignore
if %pop.key% == [6] set pop.key=Yes
if %pop.key% == [7] set pop.key=No
if %pop.key% == [10] set pop.key=TryAgain
if %pop.key% == [11] set pop.key=Continue
if %pop.key% == [99] set pop.key=NoWait
exit /b
-- End CMD -->
<job><script language="VBScript">
'on error resume next
q =""""
qsq =""" """
Set objArgs = WScript.Arguments
Set objShell= WScript.CreateObject("WScript.Shell")
Popup = 0
Title = "Popup"
Timeout = 0
Mode = 0
Message = ""
Sleep = 0
button = 0
If objArgs.Count = 0 Then
Usage()
ElseIf objArgs(0) = "/?" or Lcase(objArgs(0)) = "-h" or Lcase(objArgs(0)) = "--help" Then
Usage()
End If
noWait = Not wait()
For Each arg in objArgs
If (Mid(arg,1,1) = "/") and (InStr(arg,":") <> 0) Then haveSwitch = True
Next
If not haveSwitch Then
Message=joinParam("woq")
Else
For i = 0 To objArgs.Count-1
If IsSwitch(objArgs(i)) Then
S=split(objArgs(i) , ":" , 2)
select case Lcase(S(0))
case "/m","/message"
Message=S(1)
case "/tt","/title"
Title=S(1)
case "/s","/sleep"
If IsNumeric(S(1)) Then Sleep=S(1)*1000
case "/t","/time"
If IsNumeric(S(1)) Then Timeout=S(1)
case "/b","/button"
select case S(1)
case "oc", "1"
button=1
case "ari","2"
button=2
case "ync","3"
button=3
case "yn", "4"
button=4
case "rc", "5"
button=5
case "ctc","6"
button=6
case Else
button=0
end select
case "/i","/icon"
select case S(1)
case "s","x","stop","16"
Mode=16
case "?","q","question","32"
Mode=32
case "!","w","warning","exclamation","48"
Mode=48
case "i","information","info","64"
Mode=64
case Else
Mode=0
end select
end select
End If
Next
End If
Message = Replace(Message,"/\n", "°" )
Message = Replace(Message,"\n",vbCrLf)
Message = Replace(Message, "°" , "\n")
If noWait Then button=0
Wscript.Sleep(sleep)
Popup = objShell.Popup(Message, Timeout, Title, button + Mode + vbSystemModal)
Wscript.Quit Popup
Function IsSwitch(Val)
IsSwitch = False
If Mid(Val,1,1) = "/" Then
For ii = 3 To 9
If Mid(Val,ii,1) = ":" Then IsSwitch = True
Next
End If
End Function
Function joinParam(quotes)
ReDim ArgArr(objArgs.Count-1)
For i = 0 To objArgs.Count-1
If quotes = "wq" Then
ArgArr(i) = q & objArgs(i) & q
Else
ArgArr(i) = objArgs(i)
End If
Next
joinParam = Join(ArgArr)
End Function
Function wait()
wait=True
If objArgs.Named.Exists("NewProcess") Then
wait=False
Exit Function
ElseIf objArgs.Named.Exists("NW") or objArgs.Named.Exists("NoWait") Then
objShell.Exec q & WScript.FullName & qsq & WScript.ScriptFullName & q & " /NewProcess: " & joinParam("wq")
WScript.Quit 99
End If
End Function
Function Usage()
Wscript.Echo _
vbCrLf&"Usage:" _
&vbCrLf&" popup followed by your message. Example: ""popup First line\nescaped /\n\nSecond line"" " _
&vbCrLf&" To triger a new line use ""\n"" within the msg string [to escape enter ""/"" before ""\n""]" _
&vbCrLf&"" _
&vbCrLf&"Advanced user" _
&vbCrLf&" If any Switch is used then you must use the /m: switch for the message " _
&vbCrLf&" No space allowed between the switch & the value " _
&vbCrLf&" The switches are NOT case sensitive " _
&vbCrLf&"" _
&vbCrLf&" popup [/m:""*""] [/t:*] [/tt:*] [/s:*] [/nw] [/i:*]" _
&vbCrLf&"" _
&vbCrLf&" Switch | value |Description" _
&vbCrLf&" -----------------------------------------------------------------------" _
&vbCrLf&" /m: /message:| ""1 2"" |if the message have spaces you need to quote it " _
&vbCrLf&" | |" _
&vbCrLf&" /t: /time: | nn |Duration of the popup for n seconds " _
&vbCrLf&" | |<Default> untill key pressed" _
&vbCrLf&" | |" _
&vbCrLf&" /tt: /title: | ""A B"" |if the title have spaces you need to quote it " _
&vbCrLf&" | | <Default> Popup" _
&vbCrLf&" | |" _
&vbCrLf&" /s: /sleep: | nn |schedule the popup after n seconds " _
&vbCrLf&" | |" _
&vbCrLf&" /nw /NoWait | |Continue script without the user pressing ok - " _
&vbCrLf&" | | botton option will be defaulted to OK button " _
&vbCrLf&" | |" _
&vbCrLf&" /i: /icon: | ?/q |[question mark]" _
&vbCrLf&" | !/w |[exclamation (warning) mark]" _
&vbCrLf&" | i/info|[information mark]" _
&vbCrLf&" | x/stop|[stop\error mark]" _
&vbCrLf&" | n/none|<Default>" _
&vbCrLf&" | |" _
&vbCrLf&" /b: /button: | o |[OK button] <Default>" _
&vbCrLf&" | oc |[OK and Cancel buttons]" _
&vbCrLf&" | ari |[Abort, Retry, and Ignore buttons]" _
&vbCrLf&" | ync |[Yes, No, and Cancel buttons]" _
&vbCrLf&" | yn |[Yes and No buttons]" _
&vbCrLf&" | rc |[Retry and Cancel buttons]" _
&vbCrLf&" | ctc |[Cancel and Try Again and Continue buttons]" _
&vbCrLf&" ---> | ---> |The output will be saved in variable ""pop.key""" _
&vbCrLf&"" _
&vbCrLf&"Example:" _
&vbCrLf&" popup /tt:""My MessageBox"" /t:5 /m:""Line 1\nLine 2\n/\n\nLine 4""" _
&vbCrLf&"" _
&vbCrLf&" v1.9 By RDR # 2020"
Wscript.Quit
End Function
</script></job>
Bat file:
#echo off
echo wscript.Quit((msgbox("question?",4+32+256, "title")-6) Mod 255) > %temp%\msgbox.vbs
start /wait %temp%\msgbox.vbs
rem echo wscript returned %errorlevel%
if errorlevel 1 goto error
echo We have Yes
goto end
:error
echo We have No
:end
del %temp%\msgbox.vbs /f /q
I would create a batch subroutine MSGBOX like shown below which you can call then via
call :MSGBOX "Test-Message 1" "Test-Title 1"
as often you want.
For example:
#ECHO OFF
:: call message box sub-routine
call :MSGBOX "Test-Message 1" "Test-Title 1"
call :MSGBOX "Test-Message 2" "Test-Title 2"
:END
EXIT /B
::::::::::::::::
:: sub-routines
:MSGBOX
:: 1. parameter: message
:: 2. parameter: title
:: find temporary name for VBS file
:uniqueLoop
set "uniqueFileName=%tmp%\msgbox~%RANDOM%.vbs"
if exist "%uniqueFileName%" goto :uniqueLoop
:: write to temporary VBS file, execute, delete file
echo msgbox"%~1",vbInformation , "%~2"> %uniqueFileName%
%uniqueFileName%
erase %uniqueFileName%
EXIT /B
msg * /server:127.0.0.1 Type your message here
A better option
set my_message=Hello world&& start cmd /c "#echo off & mode con cols=15 lines=2 & echo %my_message% & pause>nul"
Description:
lines= amount of lines,plus 1
cols= amount of characters in the message, plus 3 (However, minimum must be 15)
Auto-calculated cols version:
set my_message=Hello world&& (echo %my_message%>EMPTY_FILE123 && FOR %? IN (EMPTY_FILE123 ) DO SET strlength=%~z? && del EMPTY_FILE123 ) && start cmd /c "#echo off && mode con lines=2 cols=%strlength% && echo %my_message% && pause>nul"
it needs ONLY to popup when inside a vm, so technically, there should be some code like:
if %machine_type% == virtual_machine then
echo message box code
else
continue normal installation code