I'd like to learn to execute a PowerShell command from another shell or language, eg Python os.system()
. What I want to achieve is the following:
I think this gives an idea of what I would like to achieve, assuming to use cmd.exe as the caller environmnet:
powershell -NoProfile -command "& { cat foo.txt | Tee-Object ps-log.txt; exit $LASTEXITCODE }"
echo %errorlevel%
There are some problems here. First, I cannot use quotations in the command, eg :
powershell -NoProfile -command "& { cat `"foo bar.txt`" | Tee-Object ps-log.txt; exit $LASTEXITCODE }"
The cat
argument seems to be passed unquoted and so cat
looks for a 'bar.txt' parameter.
I think $LASTEXITCODE
is expanded soon, that is before cat
is executed.
&
is inconvenient to use, because it does not accept a single command line string including arguments. An alternative to &
is iex
, however I cannot use it from cmd.exe. In fact:
powershell -NoProfile -command {iex cat foo.txt}
returns:
iex cat foo.txt
From cmd.exe
, use the following ( -c
is short for -Command
):
C:\>powershell -NoProfile -c "Get-Content \"foo bar.txt\" | Tee-Object ps-log.txt; exit -not $?"
There's no reason to use & {... }
in a string passed to -Command
- just use ...
instead.
Escape embedded "
chars. as \"
(PowerShell (Core) 7+ also accepts ""
).
'...'
(single-quoting) inside the "..."
string passed to -Command
/ -c
, assuming that no string interpolation is required. Since only PowerShell-native commands are involved in the command (on Windows, cat
is simply an alias of Get-Content
), $LASTEXITCODE
is not set, as it only reflects the exit code of external programs . Instead, the automatic $?
variable applies, which is a Boolean that indicates whether any errors were emitted by the commands in the most recently executed pipeline.
-not
means that $true
is converted to $false
and $false
to $true
, and these values are converted to integers for the outside, with $false
mapping to 0
and $true
to 1
.Powershell supports single quotes, which saved me in such situations quite a lot of times. The good thing about it: They are unambiguous and easy to read. But mind that variable expansion won't work inside single-quoted strings.
powershell -NoProfile -command "cat 'foo bar.txt' | tee ps-log.txt"
Apart from that, have a look at the useful advice in mklement0's answer.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.