Why does a trailing backslash break Powershell parameter parsing? [duplicate] - powershell

This question already has an answer here:
Argument escaping not interpreted correctly when running node.js script from Windows PowerShell
(1 answer)
Closed 2 years ago.
I've been pulling my hair out trying to figure out why Powershell was ignoring a command line parameter and I think I finally found that somehow a trailing backslash on a string parameter confuses parameter parsing.
I have
param (
[Parameter(Mandatory=$true)][String]$p1,
[Parameter(Mandatory=$true)][String]$p2
)
Write-Output "p1:$p1, p2:$p2"
Ultimately, I need to invoke something like this from the Windows task scheduler which means using powershell.exe as the program and adding this script and arguments as args.
In production, p1 is a file path. So I try:
PS C:\source> C:\Windows\System32\windowspowershell\v1.0\powershell.exe -ExecutionPolicy Bypass -File .\myScript.ps1 -p1 'C:\Program Files\' -p2 asdf
cmdlet myScript.ps1 at command pipeline position 1
Supply values for the following parameters:
p2:
Why the prompt? The parameter is right there. I eventually stumbled on removing the trailing backslash for p1:
PS C:\source> C:\Windows\System32\windowspowershell\v1.0\powershell.exe -ExecutionPolicy Bypass -File .\myScript.ps1 -p1 'C:\Program Files' -p2 asdf
p1:C:\Program Files, p2:asdf
Is this a bug?

This works for me in cmd (double backslash and double quotes). I guess the backslash is an escape character for the powershell command line options.
C:\Windows\System32\windowspowershell\v1.0\powershell.exe -ExecutionPolicy Bypass -file .\myScript.ps1 -p1 "C:\Program Files\\" -p2 asdf
p1:C:\Program Files\, p2:asdf

Related

Powershell via VBScript - Environmental Variable path terminated when username contains spaces [duplicate]

This question already has answers here:
How can I run a PowerShell script with white spaces in the path from the command line?
(5 answers)
Closed 1 year ago.
I have been working on a Powershell Winforms app that requires the console window to be hidden. To do this, I am calling a .ps1 script from a .vbs file (as starting via another .ps1 script and using "-WindowStyle Hidden" still briefly shows the console window upon opening the script). I am using the following code:
Dim shell,command
command = "powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -command ""%localappdata%\test\test.ps1"""
Set shell = CreateObject("WScript.Shell")
shell.Run command,0
This works with no issues when using an account name with no spaces (e.g. "TESTUSER" will resolve to "C:\USERS\TESTUSER\AppData\Local"). However, when any part of the path generated by the "%localappdata%" environmental variable contains spaces (in this case, using something like "TEST USER 1"), Powershell will terminate the command at "C:\Users\TEST" with an error stating: "The term "C:\Users\TEST" is not recognised as the name of a cmdlet, function, script file or operable program."
I am aware that any strings with spaces in VBScript need to use two sets of surrounding double quotes (""path with spaces""), but this doesn't work in this case - I have tried every combination that has been suggested and the %localappdata% path still has the same issue.
Things I have tried:
Two quotes surrounding path (Working with no spaces):
command = "powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -command ""%localappdata%\test\test.ps1"""
Two quotes surrounding entire argument:
command = ""powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -command ""%localappdata%\test\test.ps1""""
Single quotes surrounding both:
command = "powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -command "%localappdata%\test\test.ps1""
Expanding %localappdata% variable:
Dim shell,path,command
Set shell.CreateObject("WScript.Shell")
path = shell.ExpandEnvironmentStrings("%localappdata%")
command = "powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -command " & path &"\test\test.ps1"
shell.Run command,0
Adding "Chr(34)" to replace spaces:
command = "powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -command ""%localappdata%\test\test.ps1""" & Chr(34)
Using:
"$env:localappdata" or "$env:username"
(both inside and out of "command" quotes) to replace
"%localappdata%" or "C:\Users\%username%\AppData\Local"
I have also tried various solutions provided here and here, but nothing works in this case.
I also tried replacing %localappdata% with the absolute file path ("C:\Users\TEST USER 1\AppData\Local\test\test.ps1"), but this also gives the same error.
Any help would be greatly appreciated! Thanks in advance.
Since you're invoking a script file by path rather than passing PowerShell statements to PowerShell's CLI, use the -File parameter, not -Command, which implicitly solves your quoting problems:
' Note the use of -File instead of -Command
command = "powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File ""%localappdata%\test\test.ps1"""
The reason that -Command didn't work in your case is that its argument(s) are subject to another round of interpretation, namely as PowerShell code, after stripping syntactic " chars. during command-line parsing. This means that a path with spaces is then seen unquoted by PowerShell, causing the invocation to fail; you'd need additional quoting -either escaped " quotes (\"...\", i.e. \""...\"" from inside a VBScript string) or single quotes ('...'), which in turn would necessitate use of &, the call operator:
' With -Command: note the embedded '...' quoting and the need to call with `&`
' However, there's usually no need for -Command to invoke scripts with arguments.
command = "powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -Command ""& '%localappdata%\test\test.ps1'"""
See this answer for more information.

How can I run a PowerShell script with white spaces in the path from the command line?

So I've tried a bunch of different ways to run a PowerShell script from the command line and every single one returns an error.
Here is this path:
C:\Users\test\Documents\test\line space\PS Script\test.ps1
I've tried these:
powershell -File '"C:\Users\test\Documents\test\line space\PS Script\test.ps1"'
powershell "& ""C:\Users\test\Documents\test\line space\PS Script\test.ps1"""
Powershell "& 'C:\Users\test\Documents\test\line space\PS Script\test.ps1'"
Powershell -File 'C:\Users\test\Documents\test\line space\PS Script\test.ps1'"
I get all these errors:
& : The term 'C:\Users\test\Documents\test\line space\PS Script' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Processing -File ''C:\Users\test\Documents\test\line space\PS Script'' failed: The given path's format is not support ed. Specify a valid path for the -File parameter.
How can I fix this?
The -File parameter
If you want to run powershell.exe -File from the command line, you always have to set paths with spaces in double quotes ("). Single quotes (') are only recognized by PowerShell. But as powershell.exe is invoked (and hence the file parameter processed) by the command line, you have to use ".
powershell.exe -File "C:\Users\test\Documents\Test Space\test.ps1" -ExecutionPolicy Bypass
The -Command parameter
If you use the -Command parameter, instead of -File, the -Command content is processed by PowerShell. Hence you can - and in this case have to - use ' inside ".
powershell.exe -Command "& 'C:\Users\test\Documents\Test Space\test.ps1'" -ExecutionPolicy Bypass
The double quotes are processed by the command line, and & 'C:\Users\test\Documents\Test Space\test.ps1' is a command that is actually processed by PowerShell.
Solution 1 is obviously simpler.
Note that -Command is also the default parameter that is used, if you do not specify any.
powershell.exe "& 'C:\Users\test\Documents\Test Space\test.ps1'" -ExecutionPolicy Bypass
This would work, too.
The -EncodedCommand parameter
You can encode your command as Base64. This solves many "quoting" issues and is sometimes (but not in your case though) the only possible way.
First you have to create the encoded command
$Command = "& 'C:\Users\test\Documents\Test Space\test.ps1'"
[Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($Command))
And then you can use the the -EncodedCommand parameter like this
powershell.exe -EncodedCommand JgAgACcAQwA6AFwAVQBzAGUAcgBzAFwAdABlAHMAdABcAEQAbwBjAHUAbQBlAG4AdABzAFwAVABlAHMAdAAgAFMAcABhAGMAZQBcAHQAZQBzAHQALgBwAHMAMQAnAA== -ExecutionPolicy Bypass
Try this:
& "C:\Users\test\Documents\test\line space\PS Script\test"
In your examples, you're mixing quotes and double quoting for no reason.
IF EXIST "C:\Users\test\Documents\test\line space\PS Script\test.ps1" (
powershell -ExecutionPolicy Unrestricted -File "C:\Users\test\Documents\test\line space\PS Script\test.ps1"
)
In case you use parameters you can do as follows.
powershell.exe -command "& {&'C:\A B C\foo.ps1' param1 param2}"
Thanks at this point to a blog post by Hesham A. Amin :-)
I needed to pass a parameter with spaces.
I am dragging and dropping a file onto a batch file, and the file is off on the server with spaces in the path and/or file name. After testing the above answers, I got this to work. Note I am changing to the working directory prior to starting the PowerShell executable.
Batch file:
pushd O:\Data\QuickList
start powershell -noexit -Command ".\QuickList.ps1 -datafile '%1'"
popd

passing \ in argument to powershell script causes unexpected escaping

This is my powershell script test.ps1:
Write-Output $args;
Now suppose I have a batch script that calls this powershell script with all kinds of paths. One of those is c:\:
powershell -executionpolicy Bypass -file test.ps1 "c:\"
The output is:
c:"
Is there any way to quote my arguments such that c:\ would actually be taken and stored as is in the $args[0] variable? I know I can solve this quick'dirty by passing "c:\\", but that's not a real solution.
EDIT: using named parameters in test.ps1 doesn't make any difference:
[CmdletBinding()]
param(
[string]$argument
)
Write-Output $argument;
EDIT2: using a batch file instead works fine.
My test.bat script:
echo %~1
I run it:
test.bat "c:\"
Returns nicely:
c:\
Are you sure this comes form powershell and not from the program which invokes your statement? The backslash is no escape code in powershell.
my test.ps1 is working, when run from ise.
this works for me:
powershell -executionpolicy Bypass -command "test.ps1 -argument 'C:\'"
(end with quote double-quote)
Help file for PowerShell.exe says:
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.
You are against Powershell.exe's command line parser, which uses "\" to escape quotes. Do you need quotes? Not in your case:
powershell -file test.ps1 c:\
prints
c:\
Similarly, this works too
powershell -file test.ps1 "c:\ "
c:\
but then your arg has that extra space which you would want to trim. BTW, Single quotes do not help here:
powershell -file test.ps1 'c:\'
'c:\'
If you need the final backlash to be passed to the command, you can use
$ArgWithABackslashTemp = $ArgWithABackslash -replace '\\$','\\'
&$ExePath $ArgWithABackslashTemp
Or, if the exe is smart enough to handle it without the trailing backslash
&$ExePath $ArgWithABackslash.trim('\')

Executing a Powershell script in CMD.EXE from a location with "Illegal characters in path"

I am attempting to call a Powershell script in cmd.exe and the script is in a location that looks like this: c:Data\foo - bar\location-1\ShellScript.ps1
When I am calling this script I have tried using single and double quotes around the path with no luck.
PowerShell.exe -File "c:\Data\foo - bar\location-1\ShellScript.ps1" Arg1 Arg2
From what I have read I assumed that the above would work but this did not work nor did single quotes.
I appreciate any ideas.
Thanks
*Edit * Mistype on my example path. Sorry.
One solution is to move to PowerShell v3 where this works fine:
PS> powershell.exe -file 'C:\temp\foo - bar\location-1\foo.ps1' arg1 arg2
made it!, args are arg1, arg2
If you need to stay on V2 try escaping the spaces e.g.:
PS> powershell.exe -file "C:\temp\foo` -` bar\location-1\foo.ps1" arg1 arg2
From cmd.exe, this should work:
C:\> PowerShell.exe -Command "& {& 'c:\Data\foo - bar\location-1\ShellScript.ps1' Arg1 Arg2}"
PowerShell.exe -File "c:\Data\foo - bar\location-1\ShellScript.ps1"
should be escaped
PowerShell.exe "& ""c:\Data\foo - bar\location-1\ShellScript.ps1"""
yep that really is a total of 6 double quotes

Execute powershell script inside batch file [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to execute powershell commands from a batch file?
I want to execute the below powershell statement from a batch file with out creating a ps1 file
if([System.Diagnostics.EventLog]::SourceExists("dfgdjg") -eq $false){[System.Diagnostics.EventLog]::CreateEventSource("dfgdjg","dfgdjgLogs");}
else{write("Event Log already exists");}
Is it possible to do so?
In general you can do:
#powershell -command "yourpowershellcommand"
You can use powershell.exe directly, but I would recomment you to use the above form of #powershell
The command line help powershell.exe /? covers this:
-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.
If the value of Command is a script block, the script block must be enclosed
in braces ({}). You can specify a script block only when running PowerShell.exe
It shows an example at the end:
EXAMPLES
PowerShell -PSConsoleFile SqlSnapIn.Psc1
PowerShell -version 1.0 -NoLogo -InputFormat text -OutputFormat XML
PowerShell -Command {Get-EventLog -LogName security}
PowerShell -Command "& {Get-EventLog -LogName security}"