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-Processis 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-Commandargument in""...""overall, which makes the above command a bit more readable.However, not doing so subjects what are then technically multiple arguments to
-Commandto 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-Processaccepts batch-file paths directly as executables, i.e. as the arguments to the (positionally implied)-FilePathparameter; 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
0as the value of the 2nd parameter (intWindowStyle) toobjShell.Run().To hide the indirectly launched process, via
Start-Process, pass-WindowStyle Hiddento 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
trueas 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-Waitto it.-PassThruswitch, which makesStart-Processoutput a process-information object whose.ExitCodeproperty you can access, and which you can pass toexitTherefore, if you want to combine invisible and synchronous execution, as well as capture the exit code: