Powershell - How to pass arguments with apostrophes in them? - powershell

I'm using a third party tool to do some AD manipulation. I run a powershell script and pass arguments to it.
Everything works except if that argument contains an apostrophe in it like Jerry O'Connor. I've tried lots of different escape combinations without any luck.
Here is my command: script.ps1 -name "'%name%'" and name contain is Jerry O'Connor.
The error is
Result:The string is missing the terminator: '.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
I've tried:
script.ps1 -name "'%name%'"
script.ps1 -name \"%name%\"
script.ps1 -name ''name''
all with same error.
If you run this at the PS CMD level you'll see the error
powershell echo -name "'Jerry O'Connor'"
Anyone know how to pass an argument to script.ps1 -name "name" where that argument contains an apostrophe?
Cheers

You need to escape any ' chars. inside the value of %name% as '' to make them work inside a single-quoted PowerShell string, which from cmd.exe you can do with %name:'=''%:
From cmd.exe / a batch file:
powershell.exe -Command ./script.ps1 -name "'%name:'=''%'"
If %name% contains verbatim Jerry O'Connor, the above expands to the following, which should work as intended:
powershell.exe -Command ./script.ps1 -name "'Jerry O''Connor'"
However, you can simplify quoting if you use the -File CLI parameter instead of -Command:
powershell.exe -File ./script.ps1 -name "%name%"
See also:
For guidance on when to use -Command vs. -File, see this answer
For a comprehensive overview of the PowerShell CLI, see this answer

Try the escape character as shown here:
$Test = "`'test`'"
$Test

Related

Run a powershell command from run.exe

I'm trying to run this command that works perfectly fine, but from the run.exe
(new-object System.Net.WebClient).DownloadFile("host", "filename.ext");
Tried:
powershell.exe -noexit -Command "(new-object System.Net.WebClient).DownloadFile(\"host\", \"filename.ext\");"
But I get this error:
Exception calling "DownloadFile" with "2" argument(s): "An exception occurred during a WebClient request."
At line:1 char:1
+ (new-object System.Net.WebClient).DownloadFile("host ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
host and filename.ext are just placeholders.
Consider using Invoke-WebRequest instead:
powershell.exe -c "Invoke-WebRequest -Uri http://server.domain.tld/path/to/file.ext -OutFile C:\path\to\save\download\file.ext"
If you need to use the old method, which is what you attempted above, you have escaped your quotes incorrectly. The download call should look like this:
powershell.exe -noexit -Command "(new-object System.Net.WebClient).DownloadFile(`"host`", `"filename.ext`");"
Your problem with the command above is that you are trying to escape your double-quotes with a \ instead of a `. The escape character in PowerShell is `. Of course, you could always avoid the need to escape your string by using a single quote for the DownloadFile parameter instead:
powershell.exe -noexit -Command "(new-object System.Net.WebClient).DownloadFile('host', 'filename.ext');"
Note that in PowerShell, double-quoted strings can have variables and subexpressions run directly in it, and can have escaped characters. Single-quoted strings escape all special characters and thus cannot have variables or subexpressions inserted directly into them. Both single-quoted and double-quoted strings do support Format Strings, however.
This should work:
Powershell.exe -NoExit -Command "& {$wc = New-Object System.Net.WebClient; $wc.DownloadFile(`"\\host\"`, `"targetfullpathname.ext"`)}"
A script block is needed to execute multiple commands.
Don't use backticks unless there are special miserable character(s).
Another method is already described by #Bender The Greatest.
This works for me with singlequotes that cmd doesn't interpret like doublequotes.
powershell (new-object Net.WebClient).DownloadFile('https://live.sysinternals.com/procmon.exe', 'procmon.exe')
Note that the first parameter is the full address of the file, not just the host.
powershell (new-object Net.WebClient).DownloadFile
OverloadDefinitions
-------------------
void DownloadFile(string address, string fileName)
void DownloadFile(uri address, string fileName)

How to execute the below command in the powershell in a single line from server to the remote client

msiexec /i "example.msi" /q UserName="my username" password="my password"
The above command is executed perfectly in the command line but I need to execute in the powershell in a single line.
So any one please suggest.
I am new to the powershell.
I have tried below one:
Start-Process -FilePath msiexec -ArgumentList / /i, example.msi, "UserName='my username'","password='my password" -Wait
but it shows some issue:
Start-Process : A positional parameter cannot be found that accepts argument 'System.Object[]'.
At line:1 char:1
+ Start-Process -FilePath msiexec -ArgumentList / /i, "'example.msi ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Start-Process], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.StartProcessCommand
You've nearly got it, try this:
start msiexec -ArgumentList
"/i example.msi /q UserName=""my username"" password=""my password"""
If any of your arguments need quotes, you need to double them up.
Try using the "Invoke-Command" cmdlet. Should look something like this:
$computerlist = get-content c:\temp\ComputerNames.txt
foreach ($computer in $computerlist) {
Invoke-Command -ComputerName $computer -ScriptBlock {msiexec /i "\\servername\pathToFile\example.msi" /q UserName="my username" password="my password"}
}
Try looking at the help for this command.
In general when you see parameters such as arguments or argumentslist always keep in mind that an array is expected. Same for the `& path args' format.
The cool thing about the array is that each item will be offered to the executable as if it was implicitly quoted, similar to you surrounding with quotes a parameter in command prompt that contains a space.
For this reason I always use structures like
$arguments=#($var1,$var2)
Like this I never have to worry about what is in the variables. When creating the array in multi line and depending on each case it also makes easier the change management because adding a parameter is a line change. It also helps with commenting one out when troubleshooting
For example
$arguments=#(
$var1
$injectedVar
#$disabled
$var2
)

How to pass path with spaces to script

I am trying to use PowerShell to call an EXE that is at a location/path containing spaces. When I call the script from the command line, the EXE's full path is not being passed to the script. Any ideas as to why this is happening?
PowerShell Script Contents (Untitled1.ps1)
Here is the entire script that gets called from the command line:
param(
[string] $ParamExePath
)
function Run-CallThisExe {
param(
[string] $ThisExePath
)
Write-Host "ThisExePath: " "$ThisExePath"
start-process -FilePath $ThisExePath
}
write-host "ParamExePath: " $ParamExePath
Run-CallThisExe -ThisExePath "$ParamExePath"
Command Line String
Here is the command line string being run from the PowerShell script's parent folder:
powershell -command .\Untitled1.ps1 -NonInteractive -ParamExePath "C:\path with spaces\myapp.exe"
Output
Here is what is output after running the script
ParamExePath: C:\path
ThisExePath: C:\path
start-process : This command cannot be run due to the error: The system cannot
find the file specified.
At C:\sample\Untitled1.ps1:11 char:5
+ start-process -FilePath $ThisExePath
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
Just change this:
powershell -command .\Untitled1.ps1 -NonInteractive -ParamExePath "C:\path with spaces\myapp.exe"
To This:
powershell -file .\Untitled1.ps1 -NonInteractive -ParamExePath "C:\path with spaces\myapp.exe"
The -Command Parameter used to execute commands for example {Get-Date}
The -File Parameter used to Run .ps1 Script File
-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.
-File
Runs the specified script in the local scope ("dot-sourced"), so that the
functions and variables that the script creates are available in the
current session. Enter the script file path and any parameters.
File must be the last parameter in the command, because all characters
typed after the File parameter name are interpreted
as the script file path followed by the script parameters.
Type Powershell /? to get full details on each Parameter
A couple of other ways to call it:
powershell -command .\Untitled1.ps1 -NonInteractive "-ParamExePath 'C:\path with spaces\myapp.exe'"
powershell -command ".\Untitled1.ps1 -ParamExePath 'C:\path with spaces\myapp.exe'" -NonInteractive
Note that if you pass a folder path to Powershell that has a trailing backslash it cannot handle it. e.g. -ParamFolder "C:\project folder\app\bin debug\". The parameter string ends up with a double quote at the end. So when you try to append the name of a file to it you end up with something like C:\project folder\app\bin debug"Filename.txt. In this case you have to send in a second backslash at the end.

Running .cmd/.bat script in Powershell

I'm trying to write and execute a .cmd script in powershell. The code I have for this is:
$script = #'
#echo off
SETLOCAL
CALL something here
'#
Invoke-Expression -Command: $script
This is based off this link which explains the here string in powershell. It's at the bottom of the link. Here's the related msdn.
Here's another related link to someone trying to do the same thing.
I keep getting an error that has to do with including the '#' operator within the string:
Invoke-Expression : At line:1 char:7
+ #echo off
+ ~~~
Unexpected token 'off' in expression or statement.
At line:1 char:1
+ #echo off
+ ~~~~~
The splatting operator '#' cannot be used to reference variables in an expression. '#echo' can be used only as an argument to a command. To reference variables in an expression use '$echo'.
I've tried escaping the '#' symbol, and a plethora of other things. I'd like to know why it seemed to work for them in the third link, but throws this error in my case.
Edit:
Writing to a .bat file then running the bat file resulted in the same error:
$batchFileContent = #'
#echo off
c:\windows\system32\ntbackup.exe backup "C:\Documents and Settings\Administrator\Local Settings\Application Data\Microsoft\Windows NT\NTBackup\data\chameme.bks" /n "1file.bkf1 created 06/09/2013 at 09:36" /d "Set created 06/09/2013 at 09:36" /v:no /r:no /rs:no /hc:off /m normal /j chameme /l:s /f "\\fs1\Exchange Backups$\1file.bkf"
'#
$batchFileContent | Out-File -LiteralPath:"$env:TEMP\backup.cmd" -Force
Invoke-Expression -Command:"$env:TEMP\backup.cmd"
Remove-Item -LiteralPath:"$env:TEMP\backup.cmd" -Force
As Bill Stewart pointed out, I should write the content of the .cmd script in powershell.
Edit:
This
$script = #'
cmd.exe /C "#echo off"
cmd.exe /C "SETLOCAL"
cmd.exe /C "CALL something here"
'#
Invoke-Expression -Command: $script
Seems to work.
This happens because Invoke-Expression interprets your string with PowerShell. PowerShell allows you to run shell commands, but it interprets things as PowerShell first. The # character is the splatting operator in PowerShell.
You should save the commands in a batch file, and then execute that.
Or you can execute single line commands by shelling out to cmd.exe:
Invoke-Expression "cmd.exe /c #echo something"

Invoke-Expression: Positional parameter cannot be found that accepts argument /s

I have a .ps1 script which contains a line
Invoke-Expression -Command "C:\Builds\$BuildName /s /v`"/l*v c:\build_install.txt /qn`""<br/>
This is performing Silent installation of a product.
Now, if I try to run this command from Linux box through ssh it gives the following error:
Invoke-Expression : A positional parameter cannot be found that accepts argument '/s'.
At line:1 char:1
+ Invoke-Expression C:\NWTBuilds\Setup-NimbleNWT-x64.2.0.4.117.exe /s /v`/l*v c:\n ...
+ CategoryInfo : InvalidArgument: (:) [Invoke-Expression], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.InvokeExpressionCommand
Do you have any suggestions on this? Do I need to provide any credentials?
So I have also tried the following options:
Send the command through ssh or telnet powershell.exe -Command ...
Call the powershell Script from ssh or telnet powershell.exe -File C:\Sample.ps1
However If I ran the same Sample.ps1 from windows Powershell, silent installation is done?
Your /s is being interpreted as being part of your Invoke-Expression call. Can you try Invoke-Command, i.e.:
Invoke-Command { C:\Builds\$BuildName /s /v "/l*v c:\build_install.txt /qn" }
The error message indicates that PowerShell is trying to parse /s as the name of a parameter of Invoke-Expression rather than as part of the argument supplied to -Command, which it would not do if the /s were part of the string. This implies that the string is being terminated just before that. Check the value of $BuildName, it probably contains something that terminates the string. I'm not quite sure what that might be, because a pair of double quotes within the variable value shouldn't have that effect. At least it wouldn't at a PowerShell prompt. Maybe the ssh client is interpreting what you're typing in some way that terminates the string before /s?
In any case, I'd be willing to bet money that the answer lies in the value of $BuildName, because logically the error indicates that the string argument to -Command terminates at that point.