Batch Code (option 1)
I typically used this to simply call vbs from batch, no variables included.
#echo off
myVBSpath=\\UNC\path
set vbsFileName=myVBS.vbs
cscript "%myVBSpath%\%vbsFileName%"
pause
Batch Code (option 2)
I typically use this option when passing a variable from batch to VBS... including the variable name & value after the vbs file path and name.
#echo off
set myVBSpath=\\UNC\path
set vbsFileName=myVBS.vbs
cscript //NoLogo "%myVBSpath%\%vbsFileName%" /attachment: "%myAttachment%"
pause
Resulting Batch Error Message
Regardless of which option I use above, I get the following error message:
\\UNC\path\myVBS.vbs(11, 1) Microsoft VBScript runtime error: Argument
not optional
VBS Code
Dim xlApp
Dim xlBook
'Dim attachmentFullName
'attachmentFullName = WScript.Arguments.Named("attachment")
Set xlApp = CreateObject("Excel.Application")
Set xlBook = xlApp.Workbooks.Open("\\UNCpath\myExcelFile.xlsm", 0, True)
xlApp.DisplayAlerts = False
xlApp.Run "myMacro" ', Cstr(attachmentFullName)
xlApp.Quit
Set xlBook = Nothing
Set xlApp = Nothing
Troubleshooting
I do not require a variable to be passed to vbs, so batch code (option 1) should be the way to go, and its how I started. When I got the runtime error message above, I tried to pass a false variable using option 2 just to see if that provided the extra argument the cscript command is looking for. Unfortunately, option 2 gave the same error message.
This is a fairly straight forward batch script, so I'm really at a loss and feel like maybe I've just been staring at it too long, making it harder than it needs to be, and I'm just missing something simple.
Would any of you be kind enough to give me a fresh set of eyes and give me an idea of what is causing my runtime error?
Thank you!
My solution was likely a one off - but here is a quick summary of troubleshooting steps for those noticing this error in their batch script:
Check the cscript line to make sure no arguments are being accidentally passed (or not passed).
Check VBS to ensure the code is no longer requesting an argument variable (or is accepting one if passed) -- thanks #Hackoo
Check VBA to ensure the Sub is not requesting a variable -- thanks #DavyC!
Related
I would like to silent print a PDF file multiple times. I don't really mind what implementation is used, but due to being in a corporate environment I cannot easily install unsupported software :(.
I am currently using the following VBscript but could switch to any other implementation:
TargetFolder = "<path to folder>"
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace(TargetFolder)
Set colItems = objFolder.Items
For Each objItem In colItems
For i = 1 To 13
objItem.InvokeVerbEx ("Print")
Next
Next
This spools the job 13 times though. Is there a way to do this as a single job?
I also saw a suggestion for printing using adobe reader that looked like this:
AcroRd32.exe /t <file.pdf> <printer_name> <printer_driver> <printer_port>
But I couldn't find any reference material for passing the number of copies as a parameter.
I just found this questions which is essentially the same:
Programatically print multiple copies from command line
It appears that looping through and sending the file multiple times is the only solution without additional software.
I'm doing a mash between VbScript and CMD, i can call the VBScript easily with
cscript.exe //NoLogo "%~dp0TASK.vbs" >>"%~dp0output.txt"
But I need to disable the feature of users clicking on the VBScript and calling all sorts of errors, rather than it being called through a batch file.
My first attempt was a mess of setting a variable into a text file before i ran cscript.exe and use error handling in VBScript to tell if that variable could be collected, but it added too much time to the script.
Does VBScript have a way to tell whether it was started by CMD, or simply by double clicking, and able to act accordingly?
Here is a simple function, detecting the parent process caption. You can check if the process was started by CMD shell (the caption is cmd.exe) or by double-click (explorer.exe):
If LCase(GetParentProcessCaption()) <> "cmd.exe" Then WScript.Quit
' the rest part of your code here
Function GetParentProcessCaption()
With GetObject("winmgmts:\\.\root\CIMV2:Win32_Process.Handle='" & CreateObject("WScript.Shell").Exec("rundll32 kernel32,Sleep").ProcessId & "'")
With GetObject("winmgmts:\\.\root\CIMV2:Win32_Process.Handle='" & .ParentProcessId & "'")
With GetObject("winmgmts:\\.\root\CIMV2:Win32_Process.Handle='" & .ParentProcessId & "'")
GetParentProcessCaption = .Caption
End With
End With
.Terminate
End With
End Function
In the context of your question another method allowing to pass parameters from CMD shell process to WSH script child process may be useful. It uses environment variable and WScript.Shell object. Consider the below example.
There is code for task.cmd file:
set myvar=myvalue
wscript "%~dp0task.vbs"
And for task.vbs file:
WScript.Echo CreateObject("WScript.Shell").Environment("process").Item("myvar")
I have got the output as follows:
Note, process environment variables are accessible for child processes only.
One way is for your VBS file to check for the presence of parameters and if they do not exist then stop the execution.
In your VBS script:
If WScript.Arguments.Count = 0 then
' No parameters provided. Can stop here.
End If
When you call your VBS file, just passing any parameter will satisfy the condition:
REM This will work.
cscript.exe //NoLogo "%~dp0TASK.vbs" "hello world"
REM So will this.
cscript.exe //NoLogo "%~dp0TASK.vbs" 1 2 3 4
REM This will not.
cscript.exe //NoLogo "%~dp0TASK.vbs"
This will not stop people from running it manually (with a parameter) or creating a shortcut which has a parameter. It would only really stop running the VBS directly (as a parameter will not be passed).
When you double click on a .vbs file, the action is determined by the following registry key:
Computer\HKEY_CLASSES_ROOT\VBSFile\Shell\Open\Command
If you were to change the key, you will be changing the double click action, but you will not be affecting your ability to launch the command explicitly via invoking cscript.exe directly.
If the bat file will keep the cmd.exe open while the vbs file runs, you can try to detect the cmd process inside the vbs file to continue execution.
Put this at the start of your vbs file:
Set shell = CreateObject("WScript.Shell")
list_str = shell.Exec("tasklist").stdOut.ReadAll 'get a list of processes by calling the windows program 'tasklist.exe'
If InStr(list_str, "cmd.exe") = 0 Then WScript.Quit 'quit if process is not found
Is there a way to launch two Explorer windows side-by-side (vertically tiled) with a Batch script?
If not, how might I do this with VBS?
I have modified the VBS script above by Hackoo to do exactly what the OP wants...
The comments in the script explain exactly what it will do.
If the two windows don't set into correct position, increase the 'Sleep' time and try again.
If you want a horizontal split, use 'objShell.TileHorizontally'.
Option Explicit
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''' Launches two Explorer windows side-by-side filling the screen dimensions.
''' Minimizes all current open windows before launch; if this is not done,
''' the current open windows will also be resized along with our two windows.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim Calc,AppData,objShell
Calc = "%windir%\system32\calc.exe"
AppData = "%AppData%"
Set objShell = CreateObject("shell.application")
objShell.MinimizeAll
Call Explore(Calc)
WScript.Sleep 800
Call Explore(AppData)
WScript.Sleep 800
objShell.TileVertically
Set objShell = nothing
'*****************************************************
Function Explore(Path)
Dim ws
set ws = CreateObject("wscript.shell")
Explore = ws.run("Explorer /n,/select,"& Path &"")
End Function
'*****************************************************
This might be in the same category as your question. :)
How can a batch file run a program and set the position and size of the window?
Unfortunately it seems that its not possible without any external third part software in batch. Probably easier in VBS - if so the answer should be in the link.
Try this code :
Option Explicit
Dim Calc,AppData
Calc = "%windir%\system32\calc.exe"
AppData = "%AppData%"
Call Explore(Calc)
Call Explore(AppData)
'*****************************************************
Function Explore(Path)
Dim ws
set ws = CreateObject("wscript.shell")
Explore = ws.run("Explorer /n,/select,"& Path &"")
End Function
'*****************************************************
If this is a rookie mistake I apologize for wasting your time.
As part of a larger batch file to create a directory with today's date, copy and paste files to be backed up, change permissions and delete files older then X days I've run into a problem. Here's where it happens:
echo var D = new Date() > tmp.js
echo D = (D.getFullYear()*100+D.getMonth()+1)*100+D.getDate() >> tmp.js
echo WScript.Echo( 'set YYYYMMDD='+D ) >> tmp.js
echo #echo off > tmp.bat
cscript //nologo tmp.js >> tmp.bat
call tmp.bat
The command prompt spits back this error:
Input Error: There is no file extension in "C:\Users\name\Desktop\Error:".
So obviously the rest of the batch file fails but the weird thing is this works on one machine on the network but not the other.
Any help is greatly appreciated.
EDIT: there is one more line to that code that is returning the error, my mistake.
After I call tmp.bat:
mkdir "\\network\file\%YYYYMMDD%"
This code, as is, will not generate the indicated error
BUT, if the path to the batch file contains spaces, and the code is something like
cscript //nologo %~dp0\tmp.js
you will get the indicated error as the argument to cscript is incorrectly parsed because the space in the path to the js file. If this is the case (or something similar), quotes in the filename should solve it
cscript //nologo "%~dp0\tmp.js"
Also, the temporary batch file is not needed. Output from cscript can be directly read with the help of for command
set "tmpJS=%~dp0\tmp.js"
>"%tmpJS%" echo with(new Date()){WScript.StdOut.WriteLine(getFullYear()*10000+(getMonth()+1)*100+getDate())};
for /f %%D in ('cscript //nologo //B "%tmpJS%"') do set "YYYYMMDD=%%D"
Wow - that is a very convoluted way to get the current date in a variable.
This is not a direct answer to your question, but I think I can make your life much easier :-)
There really is no need for a temporary batch file. FOR /F could process the output of your temporary JS script directly.
But I have an even easier solution - GetTimeStamp.bat is a hybrid JScript/batch utility that can do nearly any date and time computation on a Windows machine.
The utility is pure script that will run on any modern Windows machine from XP forward - no 3rd party executable required.
Assuming getTimestamp.bat is in your current directory, or better yet, somewhere within your PATH, then the following simple call will define a YYYYMMDD variable containing today's date in YYYYMMDD format:
call getTimeStamp -f {yyyy}{mm}{dd} -r YYYYMMDD
There are a great many options for specifying the base date and time, many options for adding positive or negative offsets to the date and time, many options for formatting the result, and an option to capture the result in a variable. Both input and output can be directly expressed as local time, UTC, or any time zone of your choosing. Full documentation is embedded within the script.
Figured it out:
running cscript on tmp.js led to an error begin put into tmp.bat
call tmp.bat then returned the weird input error because of the error message inside of tmp.bat.
tmp.bat looked like this when editing
Cscript Error: Can't find script engine "JScript" for script "C:\Users\name\Desktop\tmp.js".
That's why calling tmp.bat returned this error message:
Input Error: There is no file extension in "C:\Users\name\Desktop\error:".
The problem ended up being with jscript.dll. It needed to be (re)registered.
regsvr32 %systemroot%\system32\jscript.dll
^Fixed my problem. Thank you all for the help.
I have a VBScript that is supposed to run a .bat or .vbs file, but it doesn't work!
It comes up with an error saying that the file could not be found, whether i put in a file path or not (it shouldn't matter anyway I think because it's in the same directory).
So my question is, how do I start a .bat file (or even better, a .vbs file) from within a VBScript?
The relevant code is bellow:
'*******This is the start of my open command that doesn't work*******
Do
If Hour(Now) >= 9 And Hour(Now) <= 18 And Minute(Now) = 34 And Second(Now) = 59 Then
Dim shell
Set shell = CreateObject("WScript.Shell")
shell.Run "F:\\EAS\Volume Up.vbs"
Set shell = Nothing
MsgBox "My De-bug Message Box which doesn' even get to open"
WScript.Sleep 2000
Set WshShell = CreateObject("WScript.Shell")
music = "C:\...\MYFILE.wav"
WshShell.Run "wmplayer """ & music & """", 0, True
WScript.Quit 1
Else
'*******This is the end*******
So what am I doing wrong? Is it the wrong way to open it? What should I put instead?
It would be good to see the contents of the .BAT File.
Your code seems fine as I am able to run the below script on my machine:
dim shell
set shell=createobject("wscript.shell")
shell.run "tester.bat"
You may not see what the .BAT File is doing as it happens so quickly, as a tester add the following command to the end of your .BAT Script:
pause
Then you will see the command prompt open. As per my VB code above, the .BAT file contents are below:
#echo OFF
#echo %time%
pause
This will show you the current time and then pause, leaving the command prompt open. Give this a go as a tester as it works fine for me.
putting triple quotes (as suggested by ToThePoint) around the path solved my vbs file error, where it was failed to find the file on specified path as file path was having spaces, like
D:\Main\My text Files\abc.txt.
thanks :)
The only thing i can think of is that it must be a typo in the file name.
Can you ensure the file name is spelled correct?
Or else please post the exact error you get.