Running external binary in PowerShell opens process in new cmd window but only when not using relative path - powershell

If I cd into a folder where I have an executable binary and type its name in PowerShell, it returns standard output back into PowerShell.
PS C:\Users\User\AppData\Roaming\npm> mybinary This does not open cmd window and executes inside PowerShell window.
But if I try to call from somewhere else, when I am not in the directory where the binary is, it creates a new cmd window and it runs there. Why? I want to run it inside the existing PowerShell window.
PS C:\Users\User> & "C:\Users\User\AppData\Roaming\npm\mybinary" Opens a new cmd window and runs there.

Where are you running this from? consolehost/ISE/VSCode other?
PowerShell is doing exactly what you asked it to do. What does the executable do? What do you expect to get back? Try your use case with any other built-in Windows Executable.
# Examples: all of which send results back to the PowerShell console without popping a new window.
PS C:\Scripts> & "C:\Windows\system32\nslookup.exe"
# Results
<#
Default Server: L...
Address: 172...
#>
PS C:\Scripts> nslookup stackoverflow.com
# Results
<#
Server: L...
Address: 172...1
Non-authoritative answer:
Name: stackoverflow.com
Addresses: 151...
#>
PS C:\Scripts> & 'nslookup' 'stackoverflow.com'
# Results
<#
Server: L...
Address: 172...
Non-authoritative answer:
Name: stackoverflow.com
Addresses: 151...
#>
PS C:\Scripts> & "nslookup" "stackoverflow.com"
# Results
<#
Server: L...
Address: 172...
Non-authoritative answer:
Name: stackoverflow.com
Addresses: 151....
#>
PS C:\Scripts> & "nslookup stackoverflow.com"
# Results
<#
& : The term 'nslookup stackoverflow.com' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
#>
PowerShell does not run executables, cmd.exe does.
Note that the Powershell_ISE actively blocks interactive executables
PowerShell ISE Limitations (Windows) | Microsoft Docs
https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/mt708811(v=vs.85)
$psUnsupportedConsoleApplications
# Results
<#
wmic
wmic.exe
cmd
cmd.exe
diskpart
diskpart.exe
edit.com
netsh
netsh.exe
nslookup
nslookup.exe
powershell
powershell.exe
#>
Running an executable in the PowerShell console, as long as you pass it all it needs, under the covers calls cmd.exe, cmd.exe runs the executable, and STDOUT is returned to the calling console.
References:
• PowerShell: Running Executables
https://social.technet.microsoft.com/wiki/contents/articles/7703.powershell-running-executables.aspx
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 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
Via VSCode, you can get different responses depending on whether you are using VSCodes' integrated console (the ISE-like environment) or the consolehost (the normal PowerShell console).

Related

Calling EXE file inside powershell file

I've tried the following:
Start-Process "C:\Tool\alert.exe" -WindowStyle Hidden
when attempting to run this ps1 file inside powershell ise then I got the following the popup message.
The Publisher could not be verified. Are you sure you want to run this software
my question is : how can I get rid of "The Publisher could not be verified. Are you sure you want to run this software"?
This is due to a setting in Windows that flags .exe files as 'high-risk'. You can unblock them using the Unblock-File command before running the executable.
Get-ChildItem "C:\Tool\alert.exe" | Unblock-File
you can read more about it here: https://winaero.com/blog/how-to-unblock-files-downloaded-from-internet-in-windows-10/
1 - Running external executables is a well-documented use case directly from Microsoft.
2 - You must make sure the exe is not marked as from an untrusted source, meaning, you downloaded this from the internet and it is marked with the internet alternate data stream (ADS). You need to remove this stuff on internet-based downloads, using the cmdlet...
Unblock-File
... or open Windows Explorer, right-click, select properties, unblock. See the help files for details and examples.
'PowerShell running executables'
hit(s)
PowerShell: Running Executables
<#
5. The Call Operator &
Technet Jump
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
<#
7. Start-Process (start/saps)
Technet Jump
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

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

Compile Micro Focus Net Express 5.1 Cobol in Powershell

I am hoping someone might be able to help me with writing a COBOL MF Net Express 5.1 compile command in Powershell. I have the command as it was used in the original batch script. I am currently working on reworking this in Powershell as a build script.
COBOL.EXE "%%inFile%%" OUTDD NOERRQ NOFLAGQ NOQUERY noALTER noanim nobound checkdiv COMP errlist list() FASTLINK omf"gnt" perform-type"osvs" SCHEDULER TARGET"PENTIUM" noTRUNC vsc2(1) listpath"","%%OUTPUT%%";,;,;
My attempt at converting this to Powershell has been like this:
$cobolExe = ".\COBOL.EXE"
$expression = "& $cobolExe `"$($inputfile)`" OUTDD NOERRQ NOFLAGQ NOQUERY noALTER noanim nobound checkdiv COMP errlist list() FASTLINK omf`"gnt`" perform-type`"osvs`" SCHEDULER TARGET`"PENTIUM`" noTRUNC vsc2(1) listpath`"`", `"$binPath\`";,;,;"
Invoke-Expression $expression
Invoke-Expression:
Line |
1 | Invoke-Expression $expression
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| At line:1 char:97 + … GQ NOQUERY noALTER noanim nobound checkdiv COMP errlist list() FASTLI … + ~
An expression was expected after '('. At line:1
| char:221 + … NTIUM" noTRUNC vsc2(1) listpath"", "C:\dev\dimensions\test\bin\";,;,; + ~
Missing expression after unary operator ','. At line:1
| char:223 + … NTIUM" noTRUNC vsc2(1) listpath"", "C:\dev\dimensions\test\bin\";,;,; + ~
Missing expression after unary operator ','.
I successfully have this working with CBLLINK.EXE, but it does not require as many parameters.
$cobolFile = "$Path\cobol.dir"
$cbllinkExe = ".\CBLLINK.EXE"
$expression = "$cbllinkExe -s -o$($outputFile) `"$($inputFile)`" adis adisinit adiskey -u`"$cobolFile`""
Invoke-Expression $expression
Anyone who might have any insight and could provide some assistance, I would very much appreciate it. Please let me know if I can provide anything else?
Calling external exe's/cmd's via PowerShell requires specific attention. It is a well-documented thing.
See these details from Microsoft and others: ---
PowerShell: Running Executables
The Call Operator &
# 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
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
Using Windows PowerShell to run old command line tools (and their
weirdest parameters)
Solution 2A: Use CMD /C
As with the first problem, you can run CMD.EXE itself and pass your
command and its parameters in quotes. Efficiency aside, this will work
fine, since PowerShell will not try to parse the string in quotes.
CMD.EXE /C "ICACLS.EXE C:TEST /GRANT USERS:(F)"
<#
# Results
processed file: C:TEST
Successfully processed 1 files; Failed processing 0 files
#>
..there are more like these.

Executing CMD Command from a PowerShell Script

I have seen many similar questions but none of them is related to the execution of a CMD command such as ipconfig from a PS script (.ps1).
If you type those commands on the PS console they work fine but once on a script they don't, below you can see an example:
PS C:\Users\TestQro> adb devices
List of devices attached
PS C:\Users\TestQro> adb devices | Select-String -Quiet List
True
returns True because the Select-String finds the word "List" in the response of the command "adb devices" which is the expected behavior. But if I go and put the same command into a .ps1 script file PS answers when running:
PS C:\TesterInfo> ./TunnerApp.ps1
cmdlet Write-Output at command pipeline position 1
Supply values for the following parameters: InputObject[0]:
How should I type the normal CMD commands inside of a script?
Why is it waiting for parameters on script but right in the console it works fine?
Based on your output there
PS C:\TesterInfo> ./TunnerApp.ps1
cmdlet Write-Output at command pipeline position 1
Supply values for the following parameters: InputObject[0]:
It looks like you have a Write-Output statement somewhere in your PowerShell script that does not have any input. Look for an empty Write-Output statement somewhere
What you're referring to as CMD commands are actually executables in the Windows or System32 folders (or some other PATH environment variable path). As such, you can call them like you would any executable using the call operator:
& "$Env:SystemRoot\System32\IPCONFIG.exe"
about_Operators

Running CMD command in PowerShell

I am having a bunch of issues with getting a PowerShell command to run. All it is doing is running a command that would be run in a CMD prompt window.
Here is the command:
"C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\i386\CmRcViewer.exe" PCNAME
I have tried the following with no success (I have tried many iterations of this to try and get one that works. Syntax is probably all screwed up):
$TEXT = $textbox.Text #$textbox is where the user enters the PC name.
$CMDCOMMAND = "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\i386\CmRcViewer.exe"
Start-Process '"$CMDCOMMAND" $TEXT'
#iex -Command ('"C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\i386\CmRcViewer.exe"' $TEXT)
The command will just open SCCM remote connection window to the computer the user specifies in the text box.
Try this:
& "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\i386\CmRcViewer.exe" PCNAME
To PowerShell a string "..." is just a string and PowerShell evaluates it by echoing it to the screen. To get PowerShell to execute the command whose name is in a string, you use the call operator &.
To run or convert batch files externally from PowerShell (particularly if you wish to sign all your scheduled task scripts with a certificate) I simply create a PowerShell script, e.g. deletefolders.ps1.
Input the following into the script:
cmd.exe /c "rd /s /q C:\#TEMP\test1"
cmd.exe /c "rd /s /q C:\#TEMP\test2"
cmd.exe /c "rd /s /q C:\#TEMP\test3"
*Each command needs to be put on a new line calling cmd.exe again.
This script can now be signed and run from PowerShell outputting the commands to command prompt / cmd directly.
It is a much safer way than running batch files!
One solution would be to pipe your command from PowerShell to CMD. Running the following command will pipe the notepad.exe command over to CMD, which will then open the Notepad application.
PS C:\> "notepad.exe" | cmd
Once the command has run in CMD, you will be returned to a PowerShell prompt, and can continue running your PowerShell script.
Edits
CMD's Startup Message is Shown
As mklement0 points out, this method shows CMD's startup message. If you were to copy the output using the method above into another terminal, the startup message will be copied along with it.
For those who may need this info:
I figured out that you can pretty much run a command that's in your PATH from a PS script, and it should work.
Sometimes you may have to pre-launch this command with cmd.exe /c
Examples
Calling git from a PS script
I had to repackage a git client wrapped in Chocolatey (for those who may not know, it's a package manager for Windows) which massively uses PS scripts.
I found out that, once git is in the PATH, commands like
$ca_bundle = git config --get http.sslCAInfo
will store the location of git crt file in $ca_bundle variable.
Looking for an App
Another example that is a combination of the present SO post and this SO post is the use of where command
$java_exe = cmd.exe /c where java
will store the location of java.exe file in $java_exe variable.
You must use the Invoke-Command cmdlet to launch this external program. Normally it works without an effort.
If you need more than one command you should use the Invoke-Expression cmdlet with the -scriptblock option.