any idea to fix the following that I have with my script?
Set objShell = CreateObject("Wscript.Shell")
objShell.Run("powershell -Command "Start-Process 'cmd' -Verb RunAs -ArgumentList '/c "C:\Temp\CAL.bat"'"")
Error: Expected ')'
I took the idea from Running Powershell from vbs with command as parameter, but my little experience with these things does not help me.
You need to satisfy VBScript's own syntax rules first:
"
chars. embedded inside"..."
must be escaped as""
The resulting string must satisfy PowerShell's syntax, which has two aspects:
Needing to
\
-escape"
chars. that should be considered a verbatim part of the command(s) passed to the-Command
(-c
) parameter ofpowershell.exe
, the Windows PowerShell CLI."
chars. are assumed to have purely syntactic function on the command line, and are removed during command-line parsing.Needing to ensure that the resulting string - with the
\
before"
removed - is valid PowerShell syntax.Thus, use
\""
Start-Process
is another PowerShell instance launched with (possibly implied)-Command
(rather than a batch file, as in this case), two layers of escaping are required in the inner call:\\\""
Therefore:
Note:
Since
objShell.Run()
does not call viacmd.exe
, there is no strict need to enclose the-Command
argument in""...""
overall, which makes the above command a bit more readable.However, not doing so subjects what are then technically multiple arguments to
-Command
to whitespace normalization (runs of multiple spaces are folded into a single space); while that is typically not a problem, it can be, namely if such multi-space runs must be preserved as part of what PowerShell should see as a string literal.In your specific case, since you're calling a batch file, you can further simplify your command for that reason:
Start-Process
accepts batch-file paths directly as executables, i.e. as the arguments to the (positionally implied)-FilePath
parameter; therefore, omitting all optional quoting, the simplest formulation of your specific command is:If you want the entire invocation to run invisibly, there are two aspects:
To hide the immediately launched process, pass
0
as the value of the 2nd parameter (intWindowStyle
) toobjShell.Run()
.To hide the indirectly launched process, via
Start-Process
, pass-WindowStyle Hidden
to it.Therefore:
Separately, if you want the processes to run synchronously, i.e. if you want the
object.Run()
call to wait until all launched processes have finished:Pass
true
as the value of the 3rd parameter (bWaitOnReturn
) toobjShell.Run()
to make the immediately launched process execution synchronous.Note: Doing so makes
object.Run()
return the exit code of that process; to capture it in VBScript code, use(...)
around the arguments and assign the return value to a variable:To also execute the indirectly launched process synchronously, i.e. the elevated one launched via
Start-Process -Verb RunAs
, pass-Wait
to it.-PassThru
switch, which makesStart-Process
output a process-information object whose.ExitCode
property you can access, and which you can pass toexit
Therefore, if you want to combine invisible and synchronous execution, as well as capture the exit code: