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

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

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.

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

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

Pass batch variables with spaces in them to powershell script?

I have a batch/powershell script that I use to make a list of all my movies and tv series but have run into a small problem, I can't have spaces in my batch variables when passing them to the powershell script.
I have tried all kinds of combos of ' and " around the variables without any luck.
My batch variables
SETLOCAL enabledelayedexpansion
SET "listfolder=%CD%\ContentList\"
SET "listname1=TVSeries"
SET "RootFolder1=\\SERVER\Storage\TV Series\"
SET "Folder1Width=70"
SET ScanFolder1=TRUE
My batch code to run and pass variables to powershell
"%listfolder%Script\Powershell.exe" -executionpolicy remotesigned -File "%listfolder%Script\folder1list.ps1" %RootFolder1% %listname1% %Folder1Width%
My powershell script code to set the variables.
param([String]$RootFolder1, [String]$listname1, [int32]$Folder1Width)
This is the error I get if I have space in %RootFolder1% path, without spaces all three variables get passed to powershell just fine.
C:\Users\hflat\Desktop\Folder Content List Maker v4.5\ContentList\Script\folder1list.ps1 : Cannot process argument
transformation on parameter 'Folder1Width'. Cannot convert value "TV" to type "System.Int32". Error: "Input string was
not in a correct format."
I found the solution here How to pass in a string with spaces into PowerShell?
What did work was to use a cmd wrapper with /S to unwrap outer quotes and removing my own path to powershell.exe
cmd /S Powershell.exe -executionpolicy remotesigned -File "%listfolder%Script\folder1list.ps1" "%RootFolder1%" "%listname1%" "%Folder1Width%"
I found the solution here How to pass in a string with spaces into PowerShell?
What did work was to use a cmd wrapper with /S to unwrap outer quotes and removing my own path to powershell.exe
cmd /S Powershell.exe -executionpolicy remotesigned -File "%listfolder%Script\folder1list.ps1" "%RootFolder1%" "%listname1%" "%Folder1Width%"

How can I redirect the error stream when calling powershell.exe using -File parameter

I'm executing a powershell script during an OS deployment task sequence using SCCM. Due to idiosyncrasies with this ecosystem I have to call the script with syntax like this (to the best of my experimentation):
powershell.exe -executionpolicy bypass -file "w:\scripts\script.ps1" -param1 "%param1%" -param2 "%param2%"
This works fine, but I wanted to capture the output of this and any error messages it throws. Normally I would do something like:
powershell.exe -executionpolicy bypass -file "w:\scripts\script.ps1" -param1 "%param1%" -param2 "%param2%" > "%logfile" 2>&1
However, per the documentation, the -file parameter must be the last parameter, and the above triggers an error since it's trying to interpret the ">" as a parameter.
Obviously I can't use:
powershell.exe -executionpolicy bypass -file "w:\scripts\script.ps1" -param1 "%param1%" -param2 "%param2%" | out-file "%logfile"
because this is a commandline engine, so even if the pipe wasn't interpreted as a parameter, out-file would be interpreted as an executable, not a cmdlet. And even if that worked, out-file doesn't capture the error stream.
Is my only option to output the script's internal logging to a file/transcript, within the script? I feel like there should be a way to do this all from the executable call. The parsing behavior of the -file parameter makes sense, but is obnoxiously limiting.
Thanks,
== Matt
As noted in my comment to the question, this was apparently due to an idiosyncrasy with SCCM's task sequence engine, which somehow causes cmd /c powershell.exe to be interpreted differently than powershell.exe.
Adding the cmd /c solved the issue of > being interpreted as a -file parameter input, rather than as a stream redirection operator.
In fact, I rediscovered that I do use syntax like:
powershell.exe -executionpolicy bypass -file "w:\scripts\script.ps1" -param1 "%param1%" -param2 "%param2%" > "%logfile" 2>&1
successfully outside of the task sequence engine, in other powershell scripts and batch scripts, so it's not a powershell nor commandline interpreter issue.

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('\')