I'm attempting to check the RelayForAuth setting for my Windows SMTP Server using the below commands. Powershell appears to display the correct result 'False' but when running the same command via command prompt, it generates an error:
Powershell Example:
([ADSI]"IIS://localhost/smtpsvc/1".RelayForAuth -like "*0*")
Output:
False
Command Prompt Example:
powershell -command "([ADSI]"IIS://localhost/smtpsvc/1".RelayForAuth -like "*0*")"
Output:
At line:1 char:8
+ ([ADSI]IIS://localhost/smtpsvc/1.RelayForAuth -like *0*)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unexpected token 'IIS://localhost/smtpsvc/1.RelayForAuth' in expression or
statement.
At line:1 char:8
+ ([ADSI]IIS://localhost/smtpsvc/1.RelayForAuth -like *0*)
+ ~
Missing closing ')' in expression.
At line:1 char:56
+ ([ADSI]IIS://localhost/smtpsvc/1.RelayForAuth -like *0*)
+ ~
Unexpected token ')' in expression or statement.
+ CategoryInfo : ParserError: (:) [],
ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
Since you're nesting (embedding) " chars. - to be passed verbatim to PowerShell - inside the syntactic outer double-quoting ("..."), you must escape those nested " chars.
Even though PowerShell-internally ` serves as the escape character, calling the PowerShell CLI (powershell.exe / pwsh) from the outside (cmd.exe) requires \-escaping of ":
# Embedded " chars. must be \-escaped
powershell -command "([ADSI]\"IIS://localhost/smtpsvc/1\").RelayForAuth -like \"*0*\""
Note that you can avoid the need for this escaping if you single-quote the strings inside the overall "..." string.
While this works fine in your case, given that your strings have only verbatim content, note that this is generally only an option if no string interpolation is required:
# Embedded strings use '...' -> no escaping needed.
powershell -command "([ADSI]'IIS://localhost/smtpsvc/1').RelayForAuth -like '*0*'"
Caveat: Using single-quoting to enclose the overall command ('...') does not work as expected from cmd.exe: the latter doesn't recognize these as quoting, and PowerShell simply interprets the string as using its syntax for a verbatim string, and therefore simply prints the contents of the string.
For more information, see this answer.
Related
In GNU/Linux I would do:
PROGPATH=/long/and/complicated/path/to/some/bin
$PROGPATH/program args...
but in Powershell if I try this:
$PROGPATH=\long\and\complicated\path\to\some\bin
$PROGPATH\program args...
I get:
At script.ps1:2 char:...
+ $PROGPATH\program args ...
+ ~~~~~~~~
Unexpected token '\program' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : UnexpectedToken
So how do I do this simple thing I know how to do in bash, in Powershell?
js2010's helpful answer shows the correct solution:
Because your command name/path contains a variable reference ($PROGPATH/...), you must invoke it with &.
The same applies if a grouping expression, (...) is used, or a subexpression, $(...) is involved.
Additionally, the same applies if a command name/path is quoted ('...' or "...")[1], as is required if the path contains spaces, for instance.
To put it differently: Direct invocation is only supported if the command name/path is a verbatim, unquoted string[1]; in all other cases, & must be used.
As for why:
&, the call operator is necessary to force interpretation of a statement as a command, i.e. to have it parsed in argument mode (see below), so as to result in command execution rather than expression evaluation.
PowerShell has two fundamental parsing modes:
argument mode, which works like a traditional shell, where the first token is a command name/path, such as a cmdlet or an external program, with subsequent tokens representing the arguments, which only require quoting if they contain shell metacharacters (chars. with special meaning to PowerShell, such as spaces to separate tokens).
expression mode, which works like expressions in programming languages.
PowerShell decides based on a statement's first token what parsing mode to apply:
If, among other things, the first token starts with a variable reference or is a quoted string, PowerShell parses in expression mode.
In expression mode, \ starts a new token, and unrecognized token \program results in the syntax error you saw.
(If you had used /, it would have been interpreted as the division operator, and program wouldn't be a valid divisor operand.)
[1] Note that if your executable path is a literal string (doesn't contain variable references of expressions) you may alternatively `-escape individual characters (spaces) in lieu of enclosing entire string in '...' or "...", in which case & is then not necessary; e.g.:
C:\Program` Files\Notepad++\notepad++.exe
With a literal string you can even employ partial single- or double-quoting as long as the first token is unquoted; e.g.:
C:\"Program Files"\Notepad++\notepad++.exe
Use the call operator "&". https://ss64.com/ps/call.html
Related: Executing a command stored in a variable from PowerShell
$progpath = 'c:\windows\system32'
& $progpath\notepad somefile.txt
Something with a space:
& 'C:\Program Files\internet explorer\iexplore' yahoo.com
Other options, adding to the path:
$env:path += ';C:\Program Files\internet explorer'
iexplore yahoo.com
And backquoting the spaces:
C:\Program` Files\internet` explorer\iexplore yahoo.com
Due to some limitations, I have to execute the Power Shell command from Windows Command Prompt
powershell -Command "(gc C:\my_configuration.conf) -replace 'INSERT_URL', \`"https://mytestserver/WW48.2'22/testing.bin\`" | Out-File C:\my_configuration.conf"
However, I am constantly getting the ParserError like below
The string is missing the terminator: '.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
How should I properly wrap the URL string with double quotes? Thanks for answering.
Remove the ` before ", and your command should work; that is, when calling powershell.exe from cmd.exe / outside PowerShell, use \" , not \`" (or `") in order to escape " chars.:
powershell -Command "(gc C:\my_configuration.conf) -replace 'INSERT_URL', \"https://mytestserver/WW48.2'22/testing.bin\" | Out-File C:\my_configuration.conf"
While you do need to escape the " characters embedded in your overall "..." command string, escaping them as \" is sufficient - no need to also use `, the backtick, PowerShell's usual escape character.
The PowerShell CLI (powershell.exe) expects \-escaping of ", so as to better align with most CLIs, even though inside a PowerShell session you need to use `" or (inside "..." only) "".[1]
You'd only need both \ and ` - in the form `\", note that ` comes first - if your embedded "..." itself contained " chars; a contrived example:
:: OK: Prints '3" of snow.'
powershell.exe -c " Write-Output \"3`\" of snow.\" "
As iRon notes, an alternative solution is to use embedded '...' quoting (single-quoting) instead.
Since your URL itself contains a ' char., that character must then be escaped as '':
:: Note the use of '...' around https://... and the inner ' escaped as ''
powershell -Command "(gc C:\my_configuration.conf) -replace 'INSERT_URL', 'https://mytestserver/WW48.2''22/testing.bin' | Out-File C:\my_configuration.conf"
[1] In PowerShell (Core) 7+, whose CLI is pwsh.exe, you may alternatively use "" inside overall "..." on the command line too, which is actually the more robust choice when calling from cmd.exe. When calling powershell.exefromcmd.exe, the robust choice is "^""(sic) - see [this answer](https://stackoverflow.com/a/49060341/45375). However, the PowerShell CLI recognizes"in _both_ editions, and"also works for"chars. _not_ inside overall"..."`.
Try using this syntax, always works
"%windir%\System32\WindowsPowerShell\v1.0\powershell.exe" -Command "& { <# PUT ANYTHING HERE #> }"
You won't need to worry about escaping anything.
Your code:
"%windir%\System32\WindowsPowerShell\v1.0\powershell.exe" -Command "& { (gc C:\my_configuration.conf) -replace 'INSERT_URL', "https://mytestserver/WW48.2%2722/testing.bin" | Out-File 'C:\my_configuration.conf' }"
EDIT1: Check here for URL special characters. the single quote (') can be handled by its replacement (%27) in your hard-coded string. (I changed it above in the 2nd code sample)
In my dockerfile I have the line
RUN [Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\oracle\instantclient_19_10", "Machine")
I get this returned, even though when I run the above command in PowerShell everything "just works"
At line:1 char:114
+ ... = 'SilentlyContinue'; [Environment]::SetEnvironmentVariable(Path, $e ...
+ ~
Missing ')' in method call.
At line:1 char:114
+ ... SilentlyContinue'; [Environment]::SetEnvironmentVariable(Path, $env:P ...
+ ~~~~
Unexpected token 'Path' in expression or statement.
At line:1 char:118
+ ... ilentlyContinue'; [Environment]::SetEnvironmentVariable(Path, $env:Pa ...
+ ~
Missing argument in parameter list.
At line:1 char:162
+ ... entVariable(Path, $env:Path + ;C:\oracle\instantclient_19_10, Machine ...
+ ~
Missing argument in parameter list.
At line:1 char:171
+ ... ntVariable(Path, $env:Path + ;C:\oracle\instantclient_19_10, Machine)
+ ~
Unexpected token ')' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordEx
ception
+ FullyQualifiedErrorId : MissingEndParenthesisInMethodCall
The error message implies two things:
PowerShell is configured as your default shell in your dockerfile (by default it is cmd.exe)
However, the " characters were stripped from your PowerShell command, which broke it.
Therefore, escape the " character as \":
RUN [Environment]::SetEnvironmentVariable(\"Path\", $env:Path + \";C:\oracle\instantclient_19_10\", \"Machine"\)
Alternatively, you can simply use '-quoting in this case:
RUN [Environment]::SetEnvironmentVariable('Path', $env:Path + ';C:\oracle\instantclient_19_10', 'Machine')
As for why escaping " as \" is needed:
Presumably, what follows RUN is copied as-is to the powershell.exe -Command command line that is used behind the scenes.
During PowerShell's command-line parsing, unescaped " characters are removed before the resulting code is interpreted as PowerShell code. Thus, " characters that must be retained as part of the PowerShell code must be \"-escaped.
See this answer for a detailed explanation.
Note: This answer isn't quite correct, check out the accepted answer https://stackoverflow.com/a/74142485/3684640 for the correct reason for why this is happening
This is an unfortunate clash with Docker's two forms of run commands referenced here https://docs.docker.com/engine/reference/builder/#run.
There's shell form:
RUN (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows)
And there's exec form
RUN ["executable", "param1", "param2"] (exec form)
In Powershell with the command you're trying to use "[Environment]" is at the beginning which makes Docker think we are in exec form.
A potential fix that works is
RUN ["powershell.exe", "[Environment]::SetEnvironmentVariable(\"Path\", $env:Path + \";C:\\oracle\\instantclient_19_10\", \"Machine\")"]
Which works by using exec form instead of shell form, since this is in json syntax we have to escape all the necessary characters as well.
When I run the backtick (`) command on this snippet:
Get-WmiObject win32_service | Where-Object { $_.pathname -notlike "C:\windows\*" -and $_.startmode -eq "auto" -and $_.startname -eq "localsystem"} | Select-Object displayname, `
pathname, startmode, startname | Format-List | Out-Host
I get some errors. What are those errors?
First, by pressing F8 just on the first line, I get this:
Incomplete string token.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : IncompleteString
Objective: Running the snippet and assuming the PC will jump onto the next line automatically, since it has the ` character.
Second, when I highlight just the first line, by clicking to the left of the line numbers, I now get this:
At line:1 char:170
... to" -and $_.startname -eq "localsystem"}|Select-Object displayname, `
~ Missing expression after ',' > in pipeline element.
CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
FullyQualifiedErrorId : MissingExpression
Objective: Running the snippet and assuming the PC will jump onto the next line automatically, since it has the ` character.
However, when I press F5 it works like a charm. Please forgive my ignorance on PowerShell, but what am I doing wrong here?
Additional info:
This is my powershell information:
Name: Windows PowerShell ISE Host
Version: 5.1
Your errors are coming from features of PowerShell ISE.
First you're trying to use F8 which is "Run Selection", on the first line, with no selection made. That will implicitly select all the characters of the first line, then try to run that.
When you do so, you get the incomplete string token error, and that's because the parser has encountered the lone backtick ` (the escape character), with no character following it. That's because the newline at the end of the line, which the backtick is usually escaping (that's how it works as a line continuation character), is missing, since the single line selection didn't include it.
Second, when I highlight just the first line, by clicking to the left of the line numbers
Now in this case you'll notice that your selection has placed the cursor at the beginning of the next line. That means this selection does include the newline, and so you now have a complete string token.
Your error is that you've now ended your command with a comma, as though you're going to pass more parameters, and then nothing comes after (the rest of the parameters were not included in your selection).
The root of the issue is that the commands in ISE that deal with running a selection, are doing exactly that, so if you want them to include things that are on the next line, you must include them in the selection too.
As a side note, I might recommend that you look for code elements which let you naturally use line breaks, such as the pipe | character, operators, and scriptblock braces {}.
Get-WmiObject win32_service |
Where-Object {
$_.pathname -notlike "C:\windows\*" -and
$_.startmode -eq "auto" -and
$_.startname -eq "localsystem"
} |
Select-Object displayname, pathname, startmode, startname |
Format-List |
Out-Host
This doesn't solve your selection problem, but it's nicer to read in my opinion, and doesn't require the awkward backtick.
Following up on #Santiagos link comment:
This is referred to as Statement Termination. When using Powershell, there are 2 statement terminator charcters.
Semicolon - ;
Newline (sometimes)
The rule for the newline is only sometimes due to the nature of how some users will use commands. Basically meaning that if the previous text is syntactically a complete statement, a new line is considered to be a statement termination. So, if it isn't complete, the newline is treated as whitespace.
Quick example:
PS C:\Users\Abraham> 3 +
>> 4
7
When I added the + operator, it was expecting another argument which is why it didn't error out.
In your case, I will assume the error came from powershells Tokenizer (lexical analyzer) when parsing through your command, as it read your backtick as an escape character for your comma (assuming it was complete - hence the statement terminator - reading the next line as a newline and not whitespace); in my opinion ( and someone correct me if im wrong ), I think it was a bug which was a False-Positive.
The Backtik (`) also known as the Escape Character can extend a line that isn't extensible. If the last character in the line is a backtick, then the newline will be treated as whitespace and not a "newline".
So you don't need that backtick due to your comma (,) telling powershell that theres more that come after it, which we reference back to the 2 paragraph for being syntactically incomplete.
In summary: it was a mistake on powershells end(:
PS - Sorry about the long post, since the first part isn't really needed to answer your question; just some info that can help you understand how it comes together.
EDIT:
Didn't see the F8 being the culprit here lol thanks to #briantist for pointing it out. Error wasn't on Powershells end. Disregard this post (:
I have a curl which works perfectly fine on linux system. I am just remotely triggering a Jenkins job with some parameters.
However the same command in Windows errors out.
curl.exe -k --user abc:xyz -X POST https://myjenkins.com/job/abc/buildWithParameters??token=deploy\&release_version=2.3.1.0-5-auto2\&docker_registry=10.0.0.12:8083\&vcmts_build=vcmts_pi07
Following is the error:
At line:1 char:260
+ ... ??token=deploy\&release_version=2.3.1.0-5-auto2\&docker_registry=96.118.23.36:80 ...
+ ~
The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double
quotation marks ("&") to pass it as part of a string.
At line:1 char:293
+ ... .3.1.0-5-auto2\&docker_registry=10.0.0.12:8083\&vcmts_build=vcmts_pi07
+ ~
The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double
quotation marks ("&") to pass it as part of a string.
At line:1 char:328
+ ... 0.0.12:8083\&vcmts_build=vcmts_pi07
+ ~
The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double
quotation marks ("&") to pass it as part of a string.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : AmpersandNotAllowed
What is the formatting change should i do to avoid this issue?
Wrap your arguments in single quotes, which are not expanded like double-quoted strings.
curl -k --user 'abc:xyz' -X POST 'https://myjenkins.com/job/abc/buildWithParameters?token=deploy&release_version=2.3.1.0-5-auto2&docker_registry=10.0.0.12:8083&vcmts_build=vcmts_pi07'