Run external PS commands with string - powershell

I want to run the CheckNetIsolation command from powershell that uses a string variable I have assigned earlier in the powershell script.
When I try
.\CheckNetIsolation loopbackexempt -d -n=$thePackage.PackageFamilyName
I think it takes the $thePackage.PackageFamilyName literally. I want the string it is assigned instead. How can I run this command with it using the string that variable is assigned to?

For me this should work
.\CheckNetIsolation "loopbackexempt" "-d" "-n=$($thePackage.PackageFamilyName)"
I just use double quotes as string delimiter for params and $() to get the value inside the string.

Related

Escape and preserve double quotes inside parameter in command line

I am testing group migration using ADMT cmd line, but the migration is failing for a specific case when the OU name contains double quotes.
ADMT GROUP /n "TestGroup" /sd:Child.A.COM /sdc.CHILD.A.COM /td.COM /tdc.A.COM /to:"ParentOU/TEST!##$%^&*()_+{}|:"<>?[]\;',./" /intraforest:yes
In cmd this throws "> was unexpected at this time" and in powershell it keeps waiting for more parameters. The main purpose is to convert this to a c# script the migrates the users/groups but it failed in the testing phase with cmd/powershell. Is there any way to make this possible at least in C#?
I have tried escaping the double quotes with "", ^", ", `" but nothing seems to work. I have also tried assigning the value to a variable and using the variable in powershell. Using "" (as suggested in this Escaping special characters in cmd) is the only time the command runs but it still throws the following error.
Error: Unable to migrate groups. Unable to bind to container
'ParentOU/TEST!##$%^&()+{}|:<>?[];',./ /intraforest:yes'. Unable to
get distinguished name for
'A.COM/ParentOU/TEST!##$%^&;()+{}|:<>?[];',./ /intraforest:yes'. :
The parameter is incorrect. (0x80070057)
The same is working if I create another OU with same name except for the double quotes.
Please help in resolving this issue.
You can do solve it in different ways:
With escaping the characters with carets outside of the quote
setlocal EnableDelayedExpansion
set "to_param=ParentOU/TEST^!##$%^&*()_+{}|:"^^^^^<^^^^^>?[];',./"
call ADMT GROUP /to:"%%to_param%%"
The main problem will be the ADMT program, you need to know how it parses the arguments, particularly with regard to the rules how it escape quotes inside arguments.
You could test \" in set "to_param=ParentOU...\"^^^^^<^^^^^>?[];',./"

Powershell Variable replacement not working from command line

I have the following command I want to run from PowerShell:
docker run -v C:\src\docker_certs:/root/.dotnet/https -it MyContainer:MyTag /bin/bash
When I run that it works perfectly. (It mounts a volume using the source folder at the destination folder.)
But when I run this:
docker run -v $env:DOCKER_CERTS_PATH:/root/.dotnet/https -it MyContainer:MyTag /bin/bash
The volume does not get mounted.
I run this to check the value:
echo $env:DOCKER_CERTS_PATH
And it returns:
C:\src\docker_certs
As I understood things, it should have replaced the value of $env:DOCKER_CERTS_PATH with C:\src\docker_certs in the second command.
How can I get the PowerShell reference to an environment variable to replace when I run a command?
Enclose the environment-variable reference in {...}:
docker run -v ${env:DOCKER_CERTS_PATH}:/root/.dotnet/https ...
Alternatively, `-escape the : char. following the env.-var. reference:
docker run -v $env:DOCKER_CERTS_PATH`:/root/.dotnet/https ...
As for what you tried:
docker run -v $env:DOCKER_CERTS_PATH:/root/.dotnet/https ...
If you don't use {...} to explicitly delineate a variable name, PowerShell may have a different idea of where the variable name ends than you do.
As an alternative to using {...}, you can `-escape the first character you don't want to be considered part of the variable name.
Note that your command argument is in this case implicitly treated as if it were enclosed in "...", so the above applies to expandable strings ("...") too.
For an comprehensive discussion of how unquoted tokens are parsed as command arguments, see this answer.
In the case at hand, the : that follows $env:DOCKER_CERTS_PATH is not considered the end of the variable reference; instead, it is considered part of the variable name, so that PowerShell looks for an environment variable (env:) literally named DOCKER_CERTS_PATH: (sic).
Since no such environment variable (presumably) exists, $env:DOCKER_CERTS_PATH: expands to the empty string and all that is passed to docker is /root/.dotnet/https.
You can verify that DOCKER_CERTS_PATH: is a valid environment variable name as follows:
PS> $env:DOCKER_CERTS_PATH: = 'hi'; $env:DOCKER_CERTS_PATH:
hi
By contrast, a regular (shell) variable is not permitted to contain :, because that : - in the absence of a namespace prefix such as env: - is itself considered a namespace prefix, which fails, because then the variable-name part is missing:
PS> $DOCKER_CERTS_PATH: = 'hi' # BREAKS, even with {...}
Variable reference is not valid. ':' was not followed by a valid variable name character. Consider using ${} to delimit the name.
The first : in a variable identifier is invariably considered the end of the namespace identifier, which must refer to an existing PowerShell drive name, as reported by Get-PSDrive.
This notation is called namespace variable notation, as explained in this answer.

Jenkins to Powershell - Do I need to escape dollar signs in passed parameters?

I have a Jenkins pipeline that invokes a Powershell script via the Powershell plugin. The pipeline uses withCredentials to put the user/password for Powershell to use in SQL connections into variables. I pass them as properties on the command:
def psCmd="./Set-CheckmarxTeams -server ${server} -jkuser $sqluser -jkpass $sqlpass"
The script has them defined as parameters:
param ([string]$server='ad1hfddbst930\shared',[string]$jkuser,[string]$jkpass)
but the SQL connection using $jkuser and $jkpass fails. The password has a $ in the middle. I tried to Write-Host $jkpass and it only shows the part up to the $, but nothing after it. Do I need to modify the string before passing it in? If so, how?
"Escaping" the dollar sign is easy and good to know. In this case, #Richard Schaefer needed to pass the entire string of a password that included the dollar sign.
Storing a string in the $jkpass variable like so:
$jkpass = "thisisa$password"
Would output: thisisa
Therefore, storing the password with single quotes eliminates this issue.
$jkpass = 'thisisa$password'
This outputs: thisisa$password

Run command line in PowerShell

I know there are lots of posts regarding this, but nothing worked for me.
I am trying to run this command line in PowerShell:
C:/Program Files (x86)/ClamWin/bin/clamd.exe --install
I have this in PowerShell:
&"C:/Program Files (x86)/ClamWin/bin/clamd.exe --install"
But all this does is execute clamd.exe, ignoring the --install parameter
How can I get the full command line to run?
Josef Z's comment on the question provides the solution:
& "C:/Program Files (x86)/ClamWin/bin/clamd.exe" --install # double-quoted exe path
or, given that the executable path is a literal (contains no variable references or subexpressions), using a verbatim (single-quoted) string ('...'):
& 'C:/Program Files (x86)/ClamWin/bin/clamd.exe' --install # single-quoted exe path
As for why your own solution attempt failed: The call operator, &, expects only a command name/path as an argument, not a full command line.
Invoke-Expression accepts an entire command line, but that complicates things further and can be a security risk.
As for why this is the solution:
The need for quoting stands to reason: you need to tell PowerShell that C:/Program Files (x86)/ClamWin/bin/clamd.exe is a single token (path), despite containing embedded spaces.
&, the so-called call operator, is needed, because PowerShell has two fundamental parsing modes:
argument mode, which works like a traditional shell, where the first token is a command name, 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);
that is why --install need not, but can be quoted (PowerShell will simply remove the quotes for you before passing the argument to the target executable.)
expression mode, which works like expressions in programming languages.
PowerShell decides based on a statement's first token what parsing mode to apply:
If the first token is a quoted string - which we need here due to the embedded spaces in the executable path - or a variable reference (e.g., $var ...), PowerShell parses in expression mode by default.
A quoted string or a variable reference as an expression would simply output the string / variable value.
However, given that we want to execute the executable whose path is stored in a quoted string, we need to force argument mode, which is what the & operator ensures.
Generally, it's important to understand that PowerShell performs nontrivial pre-processing of the command line before the target executable is invoked, so what the command line looks like in PowerShell code is generally not directly what the target executable sees.
If you reference a PowerShell variable on the command line and that variable contains embedded spaces, PowerShell will implicitly enclose the variable's value in double quotes before passing it on - this is discussed in this answer to the linked question.
PowerShell's metacharacters differ from that of cmd.exe and are more numerous (notably, , has special meaning in PowerShell (array constructor), but not cmd.exe - see this answer).
To simplify reuse of existing, cmd.exe-based command lines, PowerShell v3 introduced the special stop-parsing symbol, --%, which turns off PowerShell's normal parsing of the remainder of the command line and only interpolates cmd.exe-style environment-variable references (e.g., %USERNAME%).

Escape sequence for $ (dollar sign) in T-sql script

I am running a T-SQL script, called from a powershell script, that contains a text row which includes a sequence containing $(MV).
When I run the script I get the error "'MV' scripting variable not defined." which I assume is because it interpretates the $(MV) string as a variable instead of being a part of the text string.
How can I write the dollar sign as an escape sequence? Is that possible in a string?
Are you executing the script with sqlcmd? It will interpret $(variablename) and try to expand it.
You can disable this using the -x command-line option.
Oh, if you're using Invoke-Sqlcmd you can use the -DisableVariables parameter.
I was assuming you didn't want to have the sqlcmd variable substitution done. If you were just trying to get the $ past Powershell, use the back-tick (`$) as in another suggestion.
You can use the backtick character to escape a $ sign in PowerShell:
`$