Launching additional Powershell instance with commands from a text file - powershell

I'm writing a Powershell script that takes in a text file as a parameter. The text file looks similar to this:
echo "1"
echo "2"
echo "3"
What I would want is for each line to be executed in a new Powershell instance. So in the example above, 3 additional instances would be created and each of the 3 would execute one line from the text file. I'm able to launch instances, but I cannot get the instances to treat the lines in the file as commands.
$textFile=$args[0] #File with Powershell commands
foreach($cmdd in get-content $textFile){
cmd /c start powershell -NoExit -command {param($cmdd) iex $cmdd} -ArgumentList $cmdd
}
Running this code opens the instances, prints a lot of information, and then immediately closes. It closes so quickly that I cannot see what the info is. However, since the text file is only composed of printing the numbers 1, 2, and 3, I don't think that it's working correctly. Is there also a way to keep the windows from closing after execution?

If you're launching additional instances of PowerShell from PowerShell, you won't need to call cmd. Try using Start-Process:
$textFile=$args[0] #File with Powershell commands
foreach($cmdd in get-content $textFile){
Start-Process -FilePath powershell -ArgumentList "-NoExit -Command $cmdd"
}
This will leave newly created instances open as you have asked.

Switch from CMD /C to CMD /K to leave the command session open after the command finishes.

Related

how to run several cmd command prompts from powershell

So I am trying to write a script that allows me to open several cmd command prompt and write in them the same command but with different variables.
The solution that I came with was to write a PowerShell script that calls inside a loop a cmd file and pass a variable each time to the cmd file but I'm stuck, the PowerShell script execute only one cmd.
Can someone help to figure this out ?
Thanks :)
You can use the following :
cmd.exe /c [command]
for example
$x = 1..100
foreach ($n in $x){cmd.exe /c ping 192.168.1.$n}
mohamed saeed's answer shows you to execute cmd.exe commands synchronously, in sequence in the current console window.
If, by contrast, you want to open multiple interactive cmd.exe sessions, asynchronously, each in its separate, new window, use cmd.exe's /k option and invoke cmd.exe via Start-Process:
# Open three new interactive cmd.exe sessions in new windows
# and execute a sample command in each.
'date /t', 'ver', "echo $PSHOME" | ForEach-Object {
# Parameters -FilePath and -ArgumentList implied.
Start-Process cmd.exe /k, $_
}
Note:
Unless your cmd.exe console windows have the Let the system position the window checkbox in the Properties dialog checked by default, all new windows will fully overlap, so that you'll immediately only see the last one opened.
The last new window opened will have the keyboard focus.
The commands passed to /k are instantly executed, but an interactive session is then entered.
If you would like to keep in purely batch, you can use the start command. The /k switch keeps the command line open. You would use /c if you want to carry out the command and terminate :
start "" %comspec% /k ping 192.168.1.1
From powershell, you can use the Start-Process command with an ArgumentList:
Start-Process cmd.exe -ArgumentList "/k ping 192.168.1.1"

Trying to run a headless executable command through Powershell that works on cmd line

I am trying to run an executable through powershell to run headless, to install a program onto a VM/LocalHost machine. I can get the wizard to open, but for whatever reason I cannot get it to run headless. Here is the cmd line that I run that works:
start /WAIT setup.exe /clone_wait /S /v" /qn"
This is my attempts in powershell
Start-Process .\setup.exe /S -Wait -PassThru
Start-Process .\setup.exe /S /v /qn -Wait -PassThru
Start-Process setup.exe -ArgumentList '/clone_wait /S /v /qn' -Wait
In the cmd line instance the application installs without issue - in the powershell instance the wizard opens and is on the first "Next" prompt. Any help would be appreciated!
I also attempted to add the additional parameters "/v" and "/qn" which return an error : Start-Process : A positional parameter cannot be found that accepts argument '/v'
The bottom attempt runs but it's not waiting for the installation to complete
You may be overthinking it. Remember that PowerShell is a shell. One of the purposes of a shell is to run commands that you type.
Thus: You don't need Start-Process. Just type the command to run and press Enter.
PS C:\> .\setup.exe /clone_wait /S /v /qn
Now if the executable (or script) you want to run contains spaces in the path or name, then use the call/invocation operator (&) and specify the quotes; for example:
PS C:\> & "\package files\setup.exe" /clone_wait /S /v /qn
(This behavior is the same no matter whether you are at the PowerShell prompt or if you put the command in a script.)
This worked for me. You need to quote the whole argumentlist, plus embed double quotes to pass what you want to /v.
start-process -wait SetupStata16.exe -ArgumentList '/s /v"/qb ADDLOCAL=core,StataMP64"'
Running the command normally and then using wait-process after might be a simpler alternative, if you're sure there's only one process with that name:
notepad
wait-process notepad
To follow-up to all that you have been given thus far. Running executables via PowerShell is a well-documented use case.
PowerShell: Running Executables
Solve Problems with External Command Lines in PowerShell
Top 5 tips for running external commands in Powershell
Using Windows PowerShell to run old command-line tools (and their
weirdest parameters)
So, from the first link provides more validation of what you've been given.
5. The Call Operator &
Why: Used to treat a string as a SINGLE command. Useful for dealing with spaces.
In PowerShell V2.0, if you are running 7z.exe (7-Zip.exe) or another command that starts with a number, you have to use the command invocation operator &.
The PowerShell V3.0 parser do it now smarter, in this case you don’t need the & anymore.
Details: Runs a command, script, or script block. The call operator, also known as the "invocation operator," lets you run commands that are stored in variables and represented by strings. Because the call operator does not parse the command, it cannot interpret command parameters
Example:
& 'C:\Program Files\Windows Media Player\wmplayer.exe' "c:\videos\my home video.avi" /fullscreen
Things can get tricky when an external command has a lot of parameters or there are spaces in the arguments or paths!
With spaces you have to nest Quotation marks and the result it is not always clear!
In this case it is better to separate everything like so:
$CMD = 'SuperApp.exe'
$arg1 = 'filename1'
$arg2 = '-someswitch'
$arg3 = 'C:\documents and settings\user\desktop\some other file.txt'
$arg4 = '-yetanotherswitch'
& $CMD $arg1 $arg2 $arg3 $arg4
# or same like that:
$AllArgs = #('filename1', '-someswitch', 'C:\documents and settings\user\desktop\some other file.txt', '-yetanotherswitch')
& 'SuperApp.exe' $AllArgs
6. cmd /c - Using the old cmd shell
** This method should no longer be used with V3
Why: Bypasses PowerShell and runs the command from a cmd shell. Often times used with a DIR which runs faster in the cmd shell than in PowerShell (NOTE: This was an issue with PowerShell v2 and its use of .Net 2.0, this is not an issue with V3).
Details: Opens a CMD prompt from within powershell and then executes the command and returns the text of that command. The /c tells CMD that it should terminate after the command has completed. There is little to no reason to use this with V3.
Example:
#runs DIR from a cmd shell, DIR in PowerShell is an alias to GCI. This will return the directory listing as a string but returns much faster than a GCI
cmd /c dir c:\windows
7. Start-Process (start/saps)
Why: Starts a process and returns the .Net process object Jump if -PassThru is provided. It also allows you to control the environment in which the process is started (user profile, output redirection etc). You can also use the Verb parameter (right click on a file, that list of actions) so that you can, for example, play a wav file.
Details: Executes a program returning the process object of the application. Allows you to control the action on a file (verb mentioned above) and control the environment in which the app is run. You also have the ability to wait on the process to end. You can also subscribe to the processes Exited event.
Example:
#starts a process, waits for it to finish and then checks the exit code.
$p = Start-Process ping -ArgumentList "invalidhost" -wait -NoNewWindow -PassThru
$p.HasExited
$p.ExitCode
#to find available Verbs use the following code.
$startExe = new-object System.Diagnostics.ProcessStartInfo -args PowerShell.exe
$startExe.verbs

Open a powershell window from an existing powershell window, and keep it open after running code

I can open a powershell window from an existing one and provide it code to run here
But I can't get the second window to stay open once the code has run
Here's what I want to run in the first powershell window, and I would like the powershell window that opens to stay open after running the code (currently, it closes immediately)
start powershell { ECHO "hi" }
Note
I tried some suggestions here but not having any luck
Also, I got a fix (of sorts) using something like start powershell { ECHO "hi"; TIMEOUT 20 } but that's not going to keep the window permanently open
PowerShell -Command {Write-Host "Test" } -NoExit
from about Powershell. To start the Powershell in a new window you can use:
start-process powershell.exe -ArgumentList "-noExit", "-command","Write-host 'TEST'; Write-Host 'Test2'"
Important -Command must be the last parameter (about Powershell):
When the value of Command is a string, Command must be the last parameter specified because any characters typed after the command are interpreted as the command arguments.
Generally:
If you pass a command (-Command) or script file (-File) to execute to PowerShell's CLI (powershell.exe in Windows PowerShell, pwsh.exe in PowerShell [Core] v6+), PowerShell by default executes the command / script and then exits.
With a command or script specified for execution, you need to add the -NoExit switch if you want the new session to remain open.
Caveat: (Unless you call directly from within PowerShell with a script block), a positional argument - i.e., one neither preceded by -Command nor -File - is implicitly bound to:
-Command in Windows PowerShell
-File in PowerShell [Core] v6+.
Therefore, it's advisable to use the target parameter name explicitly.
With Start-Process (whose built-in alias on Windows - but not on Unix - is start):
Note: The primary use of Start-Process is to launch an independent process asynchronously in a new window. However, the latter isn't supported on Unix-like platforms, where Start-Process's utility is therefore limited.
start powershell { ECHO "hi" } happens to work from PowerShell (except that the window closes right after executing the command), but it's important to note that you cannot actually pass script blocks to Start-Process, only strings.
Start-Process accepts an executable name (implied -FilePath parameter), and an array of string arguments (implied -ArgumentList / -Args parameter).
If you pass a script block ({ ... }), it is automatically stringified, meaning that its literal string contents are used (stripped of the { and }) as the (only) -ArgumentList string value.
Thus, bypassing the unnecessary script-block creation, your command - with -NoExit applied as desired - should be (with explicitly named parameters; note that -Command and its argument must come last):
Start-Process -FilePath powershell -ArgumentList '-NoExit -Command ECHO "hi"'
Note:
While passing arguments individually, as an array to -ArgumentList is arguably conceptually cleaner, it is actually better to pass all arguments as a single string, using embedded quoting as necessary, due to a longstanding bug - see GitHub issue #5576.
Trying to open an interactive shell in a new window as a different user, via the -Credential parameter, is broken up to at least PowerShell 7.1, resulting in keyboard input getting blocked both in the new window and in the caller's window - see this answer for a workaround with runas.exe and GitHub issue #12129.

I need to call .bat file from Powershell script

We are migrating perl script to powershell script.
In Perl the code is as shown below
$rc='D:\\EmailConnector\\run.bat> $EmailConnector_log;';
I tried as shown below but not working
StartProcess "cmd.exe" "/c D:\EmailConnector\run.bat> $EmailConnector_log"
When I tried as shown below the .bat script ran, but I want to update the log file. Could you help me on this.
StartProcess run.bat -workingdirectory "D:\EmailConnector"
The .bat file consist of jar file for email functionality. But we want to get log in log file.
Use the call operator (&), like this:
& 'D:\EmailConnector\run.bat' > $EmailConnector_log
The return value of the batch script is automatically put into the variable $LastExitCode.
Is that what you mean?
Start-Process "cmd" -ArgumentList '/c','D:\EmailConnector\run.bat' -WorkingDirectory "D:\EmailConnector"
or this one if you need another argument for logfile
Start-Process "cmd" -ArgumentList '/c','D:\EmailConnector\run.bat','EmailConnector_log' -WorkingDirectory "D:\EmailConnector"
Or, since there are no spaces in the path, you can just execute the batch file directly from PowerShell:
D:\EmailConnector\run.bat > $EmailConnector_log
This is one of the advantages of PowerShell being both a "shell" and a "scripting language". Execution of batch, cmd, vbs, exe files is straightforward - usually. Parameter passing can be an issue but these days that is easily solved with the stop parsing operator: --%.

VB equivalent to powershell

I am very new to powershell and sometimes this question may be so simple
Can please anybody please tell me what is the equivalent to the following(vbscript) in PowerShell
set obj = wscript.createobject( wscript.shell )
Obj.Run $smCmnd
What is the use of wscript.shell.
After a bit of search I found first line can be presented as;
$obj = New-Object -ComObject WScript.Shell
But have have no idea how to call Run method ($obj.run(...)???)
If I run cmd.exe with some commands as the smCmnd, How can I keep cmd.exe without close and to run another command later in same console??
EDIT
I am writing PS script and it will be call from another application. Basically it will do some folder creations and file coping etc. I would like to open CMD.exe and show all the commands running on that. How to use same cmd prompt through out my whole script.
Is smCmnd a string of shell commands? If so, you can call them directly from PowerShell, without trying to get a wscript.shell COM object to run them against like you'd need to do in VBScript.
VBScript wasn't a shell. Powershell is. You can write shell commands directly in .ps1 or .ps2 files, just like in a batch file.
I'm not a powershell expert here, but try doing
& $smCmnd
Try running $smCmnd directly. If that fails, use Invoke-Expression $smCmnd.
If you do need to use CMD.EXE (possibly because you want to run pre-existing BAT file), and you want all of the output in a single CMD window you can pipe all the input into cmd at once like this:
# Powershell script to execute existing BAT file
cmd.exe /k "cd c:\batchfiles & firstone.bat & second.bat & echo that's all folks"
# CMD will remain open (/k). User will have to type exit to return to powershell
# Or if you want user just to hit any key to leave CMD prompt:
cmd.exe /c "c:\batchfiles\mybatchfile.bat & pause"
# /C means CMD should close after is has executed the commands on the command line
However if you want to have something execute in CMD, then make a decision in your Powershell script about what to execute next in CMD then do something similar to the answer at the following link which pipes input and output between a powershell script and CMD.exe.
How to run interactive commands in another application window from powershell