I develop a PowerShell application. I use for example
Start-Process "cmd.exe" "/c some_command"
#rest of the source code
But when I run this, it is not waiting for cmd.exe to close before executing the rest of the source code.
How can I get cmd.exe "exit event" return to continue to run my PowerShell script?
Or other way to sleep PowerShell script while cmd.exe is running?
I found the answer is to use -wait
Start-Process "cmd.exe" "/c some_command" -wait
You can invoke CMD directly from PowerShell:
cmd.exe /c some_command
In case the executable is provided as a string rather than a bare word you must prefix the statement with the call operator (otherwise using the operator is optional):
& 'cmd.exe' /c some_command
This kind of invocation automatically runs synchronously.
Start-Process invocation is asynchronous by default. You can change the behaviour to synchronous by adding the parameter -Wait.
In addition to using -Wait, you could also check the exit code to verify command success:
[int]$ExitCode = (Start-Process "cmd.exe" "/c some_command" -Wait).ExitCode
# Check exit code
if ($ExitCode -ne 0) {
throw "Something went wrong.
}
This is useful for debugging and checking cmd success.
Related
Using the .bat file code below, I can get the value returned after running the program.
"C:\Program Files\www\www.exe" /start "/My app/abc" && echo %ERRORLEVEL% > c:\ResultCode.txt"
How to use the powershell code to achieve the same functionality
I use the code below and I didn't get the result.
Start-Process -FilePath "C:\Program Files\www\www.exe" -ArgumentList "/start `"/My Processes/abc`"" -RedirectStandardError "c:\ResultCode.txt"
Please let me know how to call .cmd file as administrator from PowerShell script:
The second line below should open as Administrator from a PowerShell script:
Set-Location "C:\client\service"
Invoke-Item "C:\client\service\_install.cmd"
Then the command prompt should wait after execution. This needs to handle in PowerShell script not possible to write in _install.cmd file.
Batch-scripts runs in CMD.exe, so you need to start a CMD.exe process as admin.
Start-Process -FilePath "C:\Windows\System32\cmd.exe" -ArgumentList "/k","C:\client\service\_install.cmd" -Verb RunAs -Wait
Start-Process is the cmdlet to start a process
-FilePath "C:\Windows\System32\cmd.exe" starts cmd.exe process
-ArgumentList "/k","C:\client\service\_install.cmd" tells cmd to leave the console open after running the script (is this what you wanted? if not, replace with /c so the cmd-window will close when done). The second argument is your script.
-Verb RunAs tells Start-Process to start the process as admin (you will recieve a UAC-window if enabled)
-Wait tells Start-Process to wait until the process is finished. With cmd /k this means after you exited the command prompt. If you've changed that to cmd /c, then it waits until the script is done.
If you need to change the working directory inside the cmd-file, then you need to modify the .cmd, or write a wrapper-script, like:
#echo off
cd /d C:\client\service
C:\client\service\_install.cmd
I am trying to execute an external command using powershell, without having the second program to popup, I need to execute this program within the same PowerShell window and output both the log and the errors.
I started with this:
$outcome = Start-Process -Wait -FilePath "cmd.exe" -ArgumentList "dir" -NoNewWindow 2>&1
$outcome
But it doesn't work as expected. I still see the new window popping up with DOS and no redirect at all about the output, the errors and so on.
Am I doing something wrong?
Does this work for you?
$outcome = Invoke-Expression "cmd.exe /c dir"
$outcome
My suggestion is to use the call operator
& cmd.exe /c dir
You can just run it. You're missing "/c".
$outcome = cmd /c dir
With the added complication of start-process, you'd have to save the output to a file.
Start-Process -Wait -FilePath "cmd.exe" -ArgumentList "/c","dir" -NoNewWindow 2>&1 -RedirectStandardOutput cmd.log
I have a powershell script were I need to execute first to invoke .cmd file to complete a network download and then I need to process on that downloaded data. Below is my command
Runas /savecred /profile /user:myuser "cmd /c C:\Users\myuser\myfile.cmd"
ECHO $Hello
From the above command, myfile.cmd downloads a file and then I need to process it. Here powershell does not waits for the file to download and starts executing below commands. How can I make it wait for the file to download?
You need to wait for runas:
$cmd = 'runas'
$args = '/savecred','/profile','/user:myuser','cmd /c C:\Users\myuser\myfile.cmd'
Start-Process $cmd $args -Wait
Runas.exe doesn't wait for its child process to exit, so there is no straight-forward way to do this.
There are workarounds using SysInternals' pslist or something similar in a loop, but those solutions will derail if there's more than one process with the same name.
Something along this line:
runas /savecred /profile /user:user "X:\Path\MyProgram.exe"
do {
Start-Sleep -Seconds 1
pslist MyProgram >$null 2>&1
} while ($LASTEXITCODE -eq 0)
I can run this fine:
$msbuild = "C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe"
start-process $msbuild -wait
But when I run this code (below) I get an error:
$msbuild = "C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe /v:q /nologo"
start-process $msbuild -wait
Is there a way I can pass parameters to MSBuild using start-process? I'm open to not using start-process, the only reason I used it was I needed to have the "command" as a variable.
When I have
C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe /v:q /nologo
on a line by itself, how does that get handled in Powershell?
Should I be using some kind of eval() kind of function instead?
you are going to want to separate your arguments into separate parameter
$msbuild = "C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe"
$arguments = "/v:q /nologo"
start-process $msbuild $arguments
Using explicit parameters, it would be:
$msbuild = 'C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe'
start-Process -FilePath $msbuild -ArgumentList '/v:q','/nologo'
EDIT: quotes.
Warning
If you run PowerShell from a cmd.exe window created by Powershell, the 2nd instance no longer waits for jobs to complete.
cmd> PowerShell
PS> Start-Process cmd.exe -Wait
Now from the new cmd window, run PowerShell again and within it start a 2nd cmd window:
cmd2> PowerShell
PS> Start-Process cmd.exe -Wait
PS>
The 2nd instance of PowerShell no longer honors the -Wait request and ALL background process/jobs return 'Completed' status even thou they are still running !
I discovered this when my C# Explorer program is used to open a cmd.exe window and PS is run from that window, it also ignores the -Wait request.
It appears that any PowerShell which is a 'win32 job' of cmd.exe fails to honor the wait request.
I ran into this with PowerShell version 3.0 on windows 7/x64
I've found using cmd works well as an alternative, especially when you need to pipe the output from the called application (espeically when it doesn't have built in logging, unlike msbuild)
cmd /C "$msbuild $args" >> $outputfile
Unless the OP is using PowerShell Community Extensions which does provide a Start-Process cmdlet along with a bunch of others. If this the case then Glennular's solution works a treat since it matches the positional parameters of pscx\start-process : -path (position 1) -arguments (positon 2).