Executing PowerShell script via explorer context menu on items containing ampersands in their names

2

2

I'm using a slightly modified version of the technique given in this answer to create a context menu item in Windows' file explorer that allows me to run a PowerShell script against specific folders.

The command looks like:

cmd /K PowerShell "C:\PowerShellScript\folder_script.ps1 \"%1\" | clip" 

This works fine except when the folder has an ampersand (&) in its name. Then I get the following error (target folder was named Testing & Testing):

The string starting:
At line:1 char:37
+ C:\PowerShellScript\folder_script.ps1  <<<< "E:\tmp\Testing
is missing the terminator: ".
At line:1 char:53
+ E:\Dropbox\PowerShell\namefixer.ps1 "E:\tmp\Testing  <<<<
    + CategoryInfo          : ParserError: (E:\tmp\Testing :String) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : TerminatorExpectedAtEndOfString

Clearly something is interpreting the ampersand as a special character but I'm at a loss as how to fix this. Eliminating the ampersand from the folder name is not a viable solution for me.

A solution that doesn't involve a batch script would be preferred.

I'm using Windows 7 Enterprise (64-bit) with PowerShell 2.

Kris

Posted 2013-11-28T13:43:04.327

Reputation: 644

Answers

2

You can use the verbatim marker of Powershell : --%, it tells Powershell that anything following it should not be interpreted.

This way, your command would become :

cmd /K PowerShell "C:\PowerShellScript\folder_script.ps1 --% \"%1\" | clip" 

Unless there are double quotes in your filenames, it should be ok.

This marker is new to Powershell 3.0, so make sure you have it up to date.

Levans

Posted 2013-11-28T13:43:04.327

Reputation: 2 010

1

You can try to modify your PowerShell script. And change cmd line to batch file...

Your batch (runner.cmd)

set ps_arg="%~1"
@cd /d %~dp0
PowerShell "folder_script.ps1 | clip"

The second line means sets the folder that the runner.cmd file is in as the current folder so you can run the PowerShell script without full path. Makes it easier to move things around as you don't have to edit the runner.cmd file.

And access your path via the following in your script:

$value = $env:ps_arg -replace """",""

The quotes from the batch file seem t o get passed to the PowerShell script and need to be stripped off, hence the -replace """","". As double quotes are illegal in Windows filenames, this will never remove anything important.

So, the command line will be

cmd /K runner.cmd "%1"

Maximus

Posted 2013-11-28T13:43:04.327

Reputation: 19 395

No, ps_arg's value will not include the ampersand or anything after it. – Kris – 2013-11-29T10:50:39.280

Try set ps_arg="%~1" – Maximus – 2013-11-29T16:31:53.387

Yes, that will work but you'll wind up with a string containing the quotes in the ps script. Need to remove them before using the input. – Kris – 2013-12-05T12:46:18.303

0

It's a quoting issue. Replace the escaped double quotes with escaped single quotes so that your command looks like this:

cmd /K PowerShell "C:\PowerShellScript\folder_script.ps1 \'%1\' | clip"

You're using two different programs (cmd and powershell) and running three different pieces of code which can take arguments (cmd, powershell, and the .ps1 script).

cmd needs three arguments: /K Powershell and the arguments for powershell. The arguments for powershell must be one string, that's why they are inside quotes.

Powershell needs one argument: the command line you want to execute.

The .ps1 script needs on argument: the folder to run against. Powershell needs to interpret the path as a single string so it needs to be in quotes.

When you run the command, cmd launches Powershell and sends it the quoted string with the variable expanded and without the quotes or escape characters: C:\PowerShellScript\folder_script.ps1 "Testing & Testing" | clip

The quotes ensure that the script sees one argument instead of three.

(I'm not sure why the different types of quotes produced different results (they shouldn't have as far as I know), but they did when I tested so I provided the solution that worked on my system. If you can provide more details, I might be able to come up with a solution that works for you as well.)

Mark

Posted 2013-11-28T13:43:04.327

Reputation: 94

Why would I need to escape a single quote? Using a single quote (no escaping) doesn't solve the issue (and also breaks if the folder name contains a single quote) while using an escaped single quote just fails on any input as it seems to view the backslash as part of the argument and not as an escape character. – Kris – 2013-12-05T12:29:34.033

I'll try to explain in more depth in an edit to my answer. It worked for my test. What version of windows are you using? What version of powershell? – Mark – 2013-12-05T16:40:01.353