Executing CMD Command from a PowerShell Script - powershell

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

Related

Executing scripts is the same as dot sourcing?

I saw some surprising behavior in powershell recently.
Consider the script c:\scripts\tst1.ps:
Set-location c:\
Now from powershell:
C:\scripts PS> .\tst1.ps1
C:\ PS>
Why does the calling shell change to “C:\” according to “set-location”? shouldnt the “set-location” run from a subshell according to normal scripting rules for other shells like bash?
I thought that you had to “dot source” the script to get this type of behavior??? That is: “. .\tst1.ps1”? What is happening here.
is my powershell misconfigured on my host computer or is this the actual behavior of powershell these days?
Is there a way to reconfigure powershell to get the old behavior that I expect that is similar to bash shell where the script runs in a sub shell and exits and the current directory is uneffected?
You can run your script with the new instance of powershell:
C:\scripts PS> powershell .\tst1.ps1

How to run powershell script on computer start-up

I am trying to run a PowerShell script Daily.ps1 on start-up, however, due to administrator settings (I cannot run as admin, that is not an option), I cannot run it through the Task Scheduler. For example, this is the contents of Daily.ps1:
if (1 -eq 1) {
"Hello there!"
}
So I tried to have a batch script Daily.cmd run on start up (through the start-up folder), which runs, but I cannot get it run the Daily.ps1, and I get a message saying running scripts is disabled. (Both files are in the same directory)
powershell C:\Users\Simon\Desktop\Daily.ps1
File C:\Users\Simon\Desktop\Daily.ps1 cannot be loaded because running scripts is disabled on this system
I then tried using this line of code from a trick I learned to bypass running scripts directly:
powershell cat Daily.ps1 | powershell invoke-expression
This works but only for one liners. So I added the -raw flag for
cat, which works when in powershell, but not in CMD. For some reason, Daily.ps1's text is still stored as an array of strings. (apologies for formatting)
cmdlet Invoke-Expression at command pipeline position 1
Supply values for the following parameters:
Command: if (1 -eq 1) {
invoke-expression : At line:1 char:14
if (1 -eq 1) {
Missing closing '}' in statement block or type definition.
At line:1 char:1
invoke-expression ~~~~~~~~~~~~~~~~~
So I tried to add this to Daily.cmd:
powershell
cat -raw Daily.ps1 | powershell-invoke-expression
However, the rest of the script doesn't get executed at all once I enter PowerShell.
I don't know to get Daily.ps1 to run through a batch command. Is there a way I missed, or is one of the ways I tried faulty (without admin rights)?
Edit: To clarify, ExecutionPolicy is set to Restricted, and that cannot be changed. Additionally, I can run PowerShell scripts fine through right clicking the file and running with PS.
Create a scheduled task to run at computer startup. Put powershell.exe in the field "program/script" and -File "C:\path\to\your.ps1" in the field "arguments" (you may want to avoid placing the script in a user profile). Set the task to run whether the user is logged on or not.
I found an answer!
After trying many different methods, I came across this line of code that allows you to run PS scripts if ExecutionProperty is set to restricted:
start powershell "cat -raw C:\Users\Simon\Desktop\Daily.ps1 | invoke-expression"
This runs powershell and uses the trick of piping the results of cat -raw [file.ps1] to invoke-expression. This is useful workaround if ExecutionProperty is set to restricted.
Then you can save this line to a .cmd or .bat file and use either Task Scheduler (more customizability) or put it in the startup folder.
P.S. for everyone who kept saying change the ExecutionProperty to something other than restricted. I clearly stated multiple times that I cannot do that(not admin), nor will the Sys Admin do that, nor will it ever happen(must stay restricted) :)

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.

How can I detect whether or not I am in powershell from a command line?

I am creating a standard windows BAT/CMD file and I want to make an IF statement to check whether or not this CMD file is run from PowerShell. How can I do that?
Edit: My underlying problem was that test.cmd "A=B" results in %1==A=B when run from CMD but %1==A and %2==B when run from PowerShell. The script itself is actually run as an old Windows Command line script in both cases, so checking for Get-ChildItem will always yield an error.
One way, it to see what your process name is, and then check its attributes:
title=test
tasklist /v /fo csv | findstr /i "test"
As long as you use a unique name in place of Test, there should be little room for error.
You will get back something like:
"cmd.exe","15144","Console","1","3,284
K","Running","GNCID6101\Athomsfere","0:00:00","test"
When I ran the above code from a bat file, my output was:
"powershell.exe","7396","Console","1","50,972
K","Running","GNCID6101\Athomsfere","0:00:00","
A potentially simpler approach that may work for you. If not, it may be suitable for others.
Create 2 separate script files: test.ps1 and test.cmd
Don't include extension when calling the script. I.e. call as <path>\test (or just test if folder is in the path environment variable.
This works because CMD prioritises which script to execute as: .bat > .cmd, whereas Powershell prioritises: .ps1 > .bat > .cmd.
The following is the output of a CMD session:
C:\Temp>copy con test.cmd
#echo cmd^Z
1 file(s) copied.
C:\Temp>copy con test.ps1
Write-Output "ps1"^Z
1 file(s) copied.
C:\Temp>.\test
cmd
C:\Temp>
And calling test from Powershell:
PS C:\Temp> .\test
ps1
PS C:\Temp>
Couldn't you try to execute a Get-ChildItem and then check %ERRORLEVEL% to see if it returns an exe not found?
http://ss64.com/nt/errorlevel.html

curl http://url/script.ps1 | powershell possible?

I just want to replicate the same behavior that I do on Linux systems
c:\> \{CURL_EQUIVALENT_ON_WINDOWS} - http://url/script | powershell
Is that possible?
Basically I want to execute a stream I download from a server.
IE: in steps:
1) Find out how to execute streams in a powershell.
Execute a stream (that I already have on the file system)
c:\> type script.ps1 | powershell -command -
but this doesn't work.
There is an option -File to execute a "File", and basically I want to execute the stream if possible.
2) Find out how to execute a stream I download from the server and pipe it in to a powershell.
Thanks to dugas I learn how to execute streams with powershell, and with this link http://blog.commandlinekungfu.com/2009/11/episode-70-tangled-web.html I understand how to get content as a stream from http with powershell.
So the final curl | powershell pipe looks like this:
PS C:\>(New-Object System.Net.WebClient).DownloadString("http://url/script.ps1") | powershell -command -
Thanks a lot to everyone that contribute to this question :-)
You can specify the command parameter of powershell with a hyphen to make it read its command from standard input. Below is an example:
"Write-Host This is a test" | powershell -command -
Example of using contents of a script file:
Get-Content .\test.ps1 | powershell -command -
From the powershell help menu:
powershell /?
-Command
Executes the specified commands (and any parameters) as though they were
typed at the Windows PowerShell command prompt, and then exits, unless
NoExit is specified. The value of Command can be "-", a string. or a
script block.
If the value of Command is "-", the command text is read from standard
input.